Thank you for your replies!

Indeed, the word 'guard' is missing from that sentence: The fact that 
Erlang only allows certain BIFs inside guard clauses, and therefore Elixir 
discouraging the overriding of operators that will not work in them. 

This suggestion is not at all meant as a replacement for the pipeline 
operator |>.
The pipeline operator is built to accomodate the need to pass a single, 
most important, subject through a sequence of functions.
These functions that work on a single, most important subject, can be 
described as 'Take the left-hand side, and perform the action outlined by 
the rest of the parameters'.


However, the functions in the cases outlined above (arithmetic, 
comparisons, access, combinatorial, and there are probably more), it feels 
very weird, very unnatural to use the pipeline operator. 
These functions do not work on a single most important subject. Both the 
left-hand side and the right-hand side are equally important.
These can be described as 'Take the left-hand side and the right-hand side, 
and perform the action ontlined by the name of the operation.'

Using these binary (arity-2) functions with the pipeline operator feels 
strange and distracts from what is going on: 
a |> div(b)
x |> lt?(y)
{1,2,3,4} |> elem(2)
%{foo: 1} |> Map.merge(%{bar: 2}) |> Map.merge(%{baz:3})

The pipeline operator also stops to be useful in the case that we want to 
expand on the second argument of something:

Observe that
Decimal.add(decimal_a, Decimal.div(decimal_b, Decimal.new(2)))
which the new syntax would let you write as
decimal_a `Decimal.add` (decimal_b `Decimal.div` Decimal.new(2))
was rewritten by Allen Madsen with the pipeline operator to
decimal_b |> Decimal.div(Decimal.new(2)) |> Decimal.add(decimal_a) 
which swaps the order of parameters passed into `Decimal.add`. For addition 
this is not a problem, but take a non-reflexive operation like subtraction:

Decimal.sub(decimal_a,Decimal.div(decimal_b, Decimal.new(2)))
When using the pipeline operator, this would mean creating a call structure 
in this way:
Decimal.sub(decimal_a, decimal_b |> Decimal.div(Decimal.new(2)))
which would definitely be less readable than:
decimal_a `Decimal.sub` (decimal_b `Decimal.div` Decimal.new(2))


What I am trying to get at, is that the new syntax lets you write binary 
functions in the same location as the guard-safe operators, which will make 
user-defined structs feel more integrated with the language.
If you can do 
a > b
when a and b are built-in types, but are forced to use 
lg?(a, b)
 or 
a |> lg?(b)
 when having custom data types, I am not very happy.
But if I can use 
a `lg?` b
, I am. The semantics of the comparison are kept intact.


~Wiebe-Marten/Qqwy




On Thursday, August 11, 2016 at 2:12:07 AM UTC+2, Ben Wilson wrote:
>
> I agree, this suggestion reads like the |> does not exist.
>
> I'm also not clear on what is meant by "One of the more longstanding 
> problems in Elixir is the fact that there is a difference between how code 
> is executed inside clauses and outside." What is a clause?
>
> On Wednesday, August 10, 2016 at 7:48:39 PM UTC-4, Allen Madsen wrote:
>>
>> In my opinion, the pipeline operator already solves this problem. I 
>> would rewrite some of your examples as follows: 
>>
>> decimal_b |> Decimal.div(Decimal.new(2)) |> Decimal.add(decimal_a) 
>> Timex.today |> Timex.shift(days: 1) |> Timex.before?(Timex.today) 
>> a |> div(b) 
>> Allen Madsen 
>> http://www.allenmadsen.com 
>>
>>
>> On Wed, Aug 10, 2016 at 6:17 PM, Wiebe-Marten Wijnja 
>> <[email protected]> wrote: 
>> > One of the more longstanding problems in Elixir is the fact that there 
>> is a 
>> > difference between how code is executed inside clauses and outside. 
>> > 
>> > The choice was made to only define infix operators for the kinds of 
>> > operations that are guard-safe, so it is not confusing as to when you 
>> are 
>> > and when you are not allowed to use these infix operators. 
>> > 
>> > There is another problem that operators have: They are very cryptic. 
>> The 
>> > only way to know what an operator does, is if you've read its 
>> definition, 
>> > and still remember it. (Could you guess what `<|>`, `|^|` and `~?=` do 
>> in 
>> > Haskell?) 
>> > 
>> > Names of functions, on the other hand, are self-describing (as long as 
>> they 
>> > are named well, of course), so you instantly see what a piece of code 
>> does. 
>> > 
>> > 
>> > However, there are many operations that take two equally-important 
>> > arguments, which are much more natural to write in an infix-style than 
>> in a 
>> > prefix-style, as this is also the direction in which we 'think' them 
>> in. 
>> > 
>> > Some common examples include: 
>> > - Arithmetic operations like `+`, `-`, `*`, `/`, `div`, `mod`, `pow`. 
>> > - Comparison operations like `>`, `<=`, `!=`, `match?`, 
>> `MapSet.subset?`, 
>> > `lt?`, `gte?`, `neq?`. 
>> > - Access-based operations like the Access Protocol's `arr[x]`, `elem`, 
>> > `put_in`, `List.delete`. 
>> > - Operations that combine two structures, like `|`, `Map.merge`, 
>> > `MapSet.intersection`. 
>> > 
>> > 
>> > Because it is discouraged to override the infix operators for 
>> operations 
>> > that are not (and often cannot be) guard-safe, it feels a little 
>> 'clunky' to 
>> > use custom data structures, as we're forced to do things like: 
>> > Decimal.add(decimal_a, Decimal.div(decimal_b, Decimal.new(2)) 
>> > 
>> > Timex.before?(Timex.shift(Timex.today, days: 1), Timex.today) 
>> > 
>> > 
>> > 
>> > As Guy Steele said in his marvelous talk 'Growing a Language': "When 
>> faced 
>> > with this, programmers that are used to performing addition using a 
>> plus 
>> > sign, quetch". (It is one of the most amazing talks I've ever seen, by 
>> the 
>> > way. I totally recommend tha you watch it right now.) 
>> > 
>> > If there were a way to use an infix notation for non-operators, users 
>> could 
>> > instead improve on the language in a "smooth and clean" way. 
>> > 
>> > 
>> > Taking inspiration from Haskell's syntax, I realized that there is a 
>> way to 
>> > circumvent this problem: 
>> > 
>> > My proposal: Introduce backtick-syntax to use arity-2 functions inline. 
>> > 
>> > - Functions (and macros) with arity 2, can be written as 
>> > a `div` b 
>> > This is rewritten during compilation into 
>> > div(a, b) 
>> > 
>> > 
>> > Some more examples: 
>> > users[1][:name] `put_in` "José" 
>> > {x, _} `match?` foo 
>> > {1, 2, 3} `elem` 2 
>> > 
>> > 
>> > - Both local and remote functions can be called this way. The following 
>> is 
>> > thus also valid: 
>> > %{a: 1, b: 2} `Map.merge` %{c: 3, d: 4} 
>> > ["foo", "bar", "baz"] `List.delete` "bar" 
>> > 
>> > 
>> > - This rewriting happens from left-to-right,(left-associative) so: 
>> > import Map 
>> > a `merge` b `merge` c 
>> > is rewritten into: 
>> > merge(merge(a, b), c) 
>> > 
>> > 
>> > As far as I know, this is completely backwards-compatible: Backticks 
>> are not 
>> > allowed inside Elixir syntax right now. 
>> > The only place where they are 'used' is inside documentation strings, 
>> to 
>> > delimit in-line markdown code snippets. 
>> > This is not a problem, however; To create an in-line code snippet that 
>> > allows backticks to be used internally, one can simply delimit it with 
>> two 
>> > backticks. This is already used inside the documentation of Elixir 
>> itself, 
>> > such as on the page about writing documentation. 
>> > 
>> > ------- 
>> > 
>> > 
>> > Adding infix backtick-syntax is better than the current situation, 
>> because: 
>> > - It allows a more natural syntax for binary operations, making the 
>> language 
>> > more readable. 
>> > - It makes custom data structures feel more integrated into the 
>> language. 
>> > 
>> > This solution is better than 'just adding more possible operators' 
>> because: 
>> > - It keeps it very clear what is allowed inside guard-clauses and what 
>> > isn't. 
>> > - It is explicit what an operation does, as names are self-describing 
>> while 
>> > operator symbols are not. 
>> > 
>> > 
>> > -------- 
>> > 
>> > 
>> > Please, tell me what you think. :-) 
>> > 
>> > 
>> > ~Wiebe-Marten/Qqwy 
>> > 
>> > -- 
>> > 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/2d7507ef-9ea3-4d0e-809b-8c1c674eb951%40googlegroups.com.
>>  
>>
>> > For more options, visit https://groups.google.com/d/optout. 
>>
>

-- 
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/24b1cf10-914b-4b9e-99f4-0d3a10602ba8%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to