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
```

1 Like