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.

Reply via email to