As explained in the many others pipe proposals sent to this mailing list,
we don't plan to add more complexity to the pipe operator.

Despite the suggestions of many, anonymous functions are not the solution
when you can't pipe. Well named and defined private functions are. Elixir
is a functional language. So create small named functions to improve code
readability.

On Wed, May 3, 2017 at 01:48 OvermindDL1 <[email protected]> wrote:

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


*José Valim*
www.plataformatec.com.br
Skype: jv.ptec
Founder and Director of R&D

-- 
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/CAGnRm4Jdgg0eh8n8wbgkofjHQDAQ2HgtQ-J0D2bYC%2BFSAMT8zQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to