Hmm, I rather like it, `|>` is pipe-start (still think it should be pipe
into the end of the argument list) and `|^` could be pipe-pin, interesting
approach, I like it.
On Tuesday, May 2, 2017 at 5:09:57 PM UTC-6, Josh Bourgeois wrote:
>
> Many significant apologies for reopening this very-very-well-treaded
> topic, but I do want to advocate this *one* more time.
>
> The pipe operator is used to illustrate the flow of data transformation,
> but while functional programming is very expressive, there are times when a
> signature requires the data in question to be used as a different argument.
> In those cases, you must either break the pipe chain (and thus the flow of
> data transformation) to assign the transformed data to a variable, or send
> the data through an anonymous function to continue the program flow.
>
> Take a process where data should be transformed before being saved to a
> database:
>
> # intermediary value
> def encrypt_password(user, password) do
> encrypted = password
> |> Salt.add
> |> BCrypt.hash
> put_in(user[:hashed_password], encrypted)
> |> EctoOrSomething.UpdateIGuess.ImStillNewHere
> end
>
> # anonymous function wrap
>
> def encrypt_password(user, password) do
> password
> |> Salt.add
> |> BCrypt.hash
> |> (fn(encrypted) -> put_in(user[:hashed_password], encrypted) end).()
> # or |> (&(put_in(user[:hashed_password], &1)).()
> # but considerably messy either way
> |> ...
> end
>
> The main issue in conceptualizing a more elegant workflow to represent
> these transformations is that any construct implemented will make an
> affordance in one direction or the other. A pipe-to-argument operator would
> offer strong reusability, but proposals in this group suggested a token
> that poorly expresses its usage (I'm thinking of a thread where ~| had
> been proposed as an anonymous variable binding with |>) . The other
> proposals are for inflexible cases that would necessitate more extensions
> for further implementations, and/or borrow symbols from other languages
> that are ambiguous in their usage (such as proposals for <|, |<, and |>> as
> tokens for pipe-to-last).
>
> I think Elixir is in a unique position to solve this problem, though. If I
> could draw a correlation, the pin macro, Kernel.^/1 is used to bind a
> variable in at a location for pattern-matching...
>
> good_status = "200"
> {^good_status, response} = fetch("www.example.com")
> # expands to {"200", response} = fetch("www.example.com")
>
> I believe there's syntactic justification for a new pipe macro,
> Kernel.|^/2, that would interact with a Kernel.^/0 macro, to combine the
> concepts of the pipe and the pin. Assuming the current pipe operator
> symbolically translates | to "pipe to" and > to "the left", |^ would
> represent "pipe to the pin". The pin would appear at least once in the
> expression on the right in order to represent where the expression on the
> left will appear, expanded, like such:
>
> def encrypt_password(user, password) do
> password
> |> Salt.add
> |> BCrypt.hash
> |^ put_in(user[:hashed_password], ^)
> |> ...
> # expands to ...(put_in(user[:hashed_password],
> BCrypt.hash(Salt.add(password)))
> end
>
> Benefits to this approach:
>
> - The current pipe operator behavior remains pristine
> - ^/0 continues to act as a reference to expanding a variable
> - No introduction of new symbolic concepts
> - Syntax is flexible enough to expand to any (or multiple) argument
> position
>
> # more contrived examples!!
> > map = %{little_bunny: %{}}
> > :foo
> |^ put_in(map[:little_bunny][^], ^)
> %{little_bunny: %{foo: :foo}}
>
> > "Ton" |^ (^<>"y! " <> ^<>"i! " <> ^<>"é!")
> "Tony! Toni! Toné!"
>
> Again, I know there've been many discussions about the drawbacks to
> implementing a new pipe mechanism, and the Elixir community may have
> already come to a consensus around how to handle transformations like this,
> but I think the longevity of this topic points to a desire for some kind of
> better solution.
>
> If everyone is tired of talking about this, I'll happily let it end here,
> but I thought one more perspective couldn't hurt.
>
> Thanks for reading! ^_^
>
> On Wednesday, July 9, 2014 at 5:10:19 AM UTC-7, José Valim wrote:
>>
>> at the risk of being painfully obvious, this works:
>>>
>>> :crypto.rand_bytes(8)
>>> |> Base.encode16
>>> |> (&("--------FormDataBoundary" <> &1)).()
>>>
>>
>> Yup, this form works and is usually the solution proposed for such cases.
>>
>> I concur that allowing such forms would be a special case for pipe and
>> possibly confusing in the long term. However, given that many were
>> expecting it to work, I decided to gather everyone's feedback. And based on
>> this thread, it doesn't seem we should change the pipe operator.
>>
>>
>> *José Valim*
>> www.plataformatec.com.br
>> Skype: jv.ptec
>> Founder and Lead Developer
>>
>>
>>
--
You received this message because you are subscribed to the Google Groups
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/elixir-lang-core/9d0fde3b-c366-4097-9070-695551ffe36b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.