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
6 Likes
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.
2 Likes
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.
1 Like
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
2 Likes