-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use ⨟
instead of |>
(was: Use ∘
instead of |>
?)
#67
Comments
I think there is a way to resolve this problem, by chaning slightly how we think about the category of transducers and iterator transforms.
To move closer to this picture in julia, we should:
|
|
Thanks a lot for the comments! Very interesting!
So you mean fold(rf, Filter(pred) ∘ Map(f) ∘ Take(10), itr)
== fold(((rf ↫ Filter(pred)) ↫ Map(f)) ↫ Take(10), itr)
== fold(rf, Filter(pred) ↬ Map(f) ↬ Take(10) ↬ itr)
== fold(rf, Filter(pred)(Map(f)(Take(10)(itr))))
== fold(rf, itr |> Take(10) |> Map(f) |> Filter(pred)) # `|>` in the usual sense ? This is beautiful! In addition to this, I think it'd still be nice to have the "opposite" composition operator where the elements flow left to right. Do you know any symbols used for this purpose? Category (mathematics) - Wikipedia mentions "diagrammatic order" composition with Take(10) : Map(f) : Filter(pred)
=== Filter(pred) ∘ Map(f) ∘ Take(10) or maybe It'd be nice if we have other pipe-like ASCII operators in Julia. I wonder if it is feasible to add fold(rf, itr |> Take(10) |> Map(f) |> Filter(pred))
= fold(rf, itr |> (Take(10) \> Map(f) \> Filter(pred)))
= fold(rf, Take(10) \> Map(f) \> Filter(pred), itr)
= fold(rf ↫ Take(10) \> Map(f) \> Filter(pred), itr)
= fold(rf, (Filter(pred) <\ Map(f) <\ Take(10)) <| itr)
= fold(rf, (Filter(pred) <\ Map(f) <\ Take(10)) ↬ itr) |
Jup, this is what I meant.
I also often wished that julia, had an operator for opposite composition. The only math notation I am aware of is
|
A quick googling told me that Haskell's Control.Arrow has
I agree with this part. I wasn't suggesting to drop To stick with something like |
I was wrong 😆 julia> Base.vcat(xfs::Transducer...) = foldl(Base.:|>, xfs)
julia> [Map(sin); Map(cos); Map(tan)]
Map(sin) |>
Map(cos) |>
Map(tan) (No I'm not serious) |
It was super easy tkf/julia@56d2556 |
I just realized, that one can do right now in julia: julia> ∘ₒₚ(g,f) = f∘g
∘ₒₚ (generic function with 1 method) Maybe use |
That sounds good. I opened a PR to request adding the syntax JuliaLang/julia#34340. I'm not requesting adding the functions yet as I thought it may slow down the reviewing. |
I'm thinking to create a super simple package (say Compositions.jl) with const compose = ∘
flip(f) = (args...) -> f(reverse(args)...) If we have JuliaLang/julia#34340 but ∘ₒₚ(args...) = ∘(reverse(args)...)
const var"</" = ∘
const var"/>" = ∘ₒₚ I think it's nice to have ASCII functions Also, is |
|
BTW I've been wanting to define |
So, I've been wondering what the API of the "right action" of transducers (action on reducing functions) should be. It's a bit unfortunate that the left action is so easy ( adjoint(xf::Transducer) = rf -> reducingfunction(xf, rf) This way, both ( |
∘
instead of |>
?⨟
instead of |>
(was: Use ∘
instead of |>
?)
This is now implemented by #319. The new documentation (preview) is here: https://juliafolds.github.io/Transducers.jl/previews/PR319/ In particular, it's somewhat unfortunate (though expected) now that the notion of "transducer" is diverged from the rest of world: https://juliafolds.github.io/Transducers.jl/previews/PR319/explanation/glossary/#Transducer-1 (glossary). But I think practicality of @jw3126 Want to have a look at it? |
Cool thanks, I will take a look this week. |
This patch implements the idea discussed in #67. That is to say, ```julia collect(Map(f) |> Filter(g), xs) foldl(+, Map(f) |> Filter(g), xs) ``` is now written as ```julia xs |> Map(f) |> Filter(g) |> collect foldl(+, xs |> Map(f) |> Filter(g)) ``` or ```julia collect(opcompose(Map(f), Filter(g)), xs) foldl(+, opcompose(Map(f), Filter(g)), xs) collect(Map(f) ⨟ Filter(g), xs) foldl(+, Map(f) ⨟ Filter(g), xs) ``` or even (not recommended) ```julia collect(Filter(g)((Map(f)(xs)))) # Julia >= 1.3 collect(Filter(g) ∘ Map(f), xs) foldl(+, Filter(g) ∘ Map(f), xs) collect((Filter(g)' ⨟ Map(f)')', xs) foldl(+, (Filter(g)' ⨟ Map(f)')', xs) collect((Map(f)' ∘ Filter(g)')', xs) foldl(+, (Map(f)' ∘ Filter(g)')', xs) ``` Above syntax are all compatible with the view that `xf(itr)` is an iterator transformation. OTOH, `xf'` (`adjoint(::Transducer)`) is now the "classic" transducer; i.e., reducing function transformation. This makes it easy to use transducers with other "reducing function combinators" like `TeeRF`: ```julia rf = TeeRF(Filter(iseven)'(min), Filter(isodd)'(max)) reduce(rf, Map(identity), xs) # => (even minimum, odd maximum) ``` This PR only deprecates `::Transducer |> ::Transducer` to help migration from the old syntax.
Ever since I learnt that transducers are adjoint of iterator transforms #13, I've been wanting to rollback the decision to use
|>
instead of∘
. We'd then have this nice property (e.g., like we have with matrices (ABC)' = C'B'A'):Other reasons to avoid
|>
are∘
: Add ASCII aliascompose
of∘
JuliaLang/julia#33573 (one of the motivation behind|>
was to provide ASCII-based API)|>
: Define what is and is not covered by SemVer JuliaLang/julia#33684 (comment) / Deprecate |> JuliaLang/julia#24886 (comment)This does not mean that the original reason for using
|>
is solved; i.e., the usual order of evaluation due to∘
(left-to-right) is different from how elements in a collection are processed (right-to-left). But hiding this from users may just introduce more confusion.To solve this "flipped
∘
" problem, a better solution may be to use iterator transforms as surface API byThe text was updated successfully, but these errors were encountered: