Suppose you wanted to repeatedly compose a certain function via piping. For sake of argument, say we want to do
3 |> sqrt |> sqrt |> sqrt |> sqrt
One can do this for an arbitrary number of times n (where n = 4 above) using something relatively convoluted like
3 |> ∘(fill(sqrt,n)...)
I think it would be great to have the following notation in Julia for this:
3 |n> sqrt
Is this even implementable? Thoughts, either for or against?
Why not overload ^ for functions?
At least that would not require changes to the parser.
julia> Base.:(^)(f::Function, n::Integer) = ∘(fill(f,n)...)
julia> sqrt^3
sqrt ∘ sqrt ∘ sqrt
julia> (sqrt^3)(3)
1.147202690439877
julia> cbrt^3
cbrt ∘ cbrt ∘ cbrt
julia> (cbrt^3)(3)
1.041528498231435
fph
January 9, 2023, 5:42pm
4
Isn’t this syntax ambiguous? One could parse it as (3 | n) > sqrt, where | is bitwise or and > is “greater than”. Currently this fails because isless is not defined for function types, but it isn’t hard to imagine an overload.
Thanks for all the responses. I’m still not clear that repeated piping is precisely the same as using function composition “exponentiation”.
Interestingly, the linked PR also links to issue #41579, where this way using the pipe repeatedly is also recorded:
foldl(|>, Iterators.repeated(foo, n))
and seems to be quite fast among the alternatives.
uniment
January 10, 2023, 11:02am
6
Toying with it a bit…
julia> |>ⁿ(x, (f, n)) = foldl(|>, Iterators.repeated(f, n); init=x)
|>ⁿ (generic function with 1 method)
julia> 3 |>ⁿ (sqrt, 4)
1.0710754830729146