Thank you for your reply, Ben :-)
It is true that when compiled, `a foo b` and ` a |> foo(b)`, both become
`foo(a, b)`. The argument that you gave against adding `` could just as
well be applied against the pipeline operator itself:
> "At the end of the day, |> is exactly identical to normal function
> application, it just looks a bit different. I don't see the value in extra
> syntax to do something we can already do."
Aesthetics *do* matter. And in contrast to |>, `` will not raise a warning
when the right hand side is not enclosed in brackets.
___
With my statement about 'writing binary functions in the same location as
the guard-safe operators' I meant that you could use infix notation on
them, rather than prefix. I totally agree that my statement was confusing,
sorry.
Maybe this fake infomercial, geared towards new Elixir users explains it
better:
Hey, new Elixir user! Want your homebuilt data structure behave just like
> the built-in Elixir types? Do not fret!
> While it is true that you cannot define new operators, and should not
> redefine operators like >, + and * because they would stop working in guard
> clauses, you can do the next best thing:
> create implementations for functions like *gt?*, *plus* and *pow*
> instead, and use them just like you would normally use the operators:
import YourModule
a `gt?` b
a `plus` b
if (ten `pow` (five `plus` three)) `div` two `gt?` fourty_two, do: "So
long, and thanks for all the fish!"
>
> Look at this stuff!
Isn't it neat?
Wouldn't you think your struct now feels complete?
Thank you for your replies, everyone!
~Wiebe-Marten
On Thursday, August 11, 2016 at 4:43:17 PM UTC+2, Ben Wilson wrote:
>
> I'm confused what you mean by "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." Your proposal still won't let `lt` be used
> in guard clauses, so I don't see how the guard clause discussion is
> relevant here.
>
> At the end of the day the `` is exactly identical to |>, it just looks a
> bit different. I don't see the value in extra syntax to do something we can
> already do. That isn't to say that aesthetics never matters, but the
> difference here is merely that it doesn't emphasize the left hand side,
> whereas the |> operator does a little bit. That seems like entirely too
> little of a distinction to warrant extra syntax.
>
> On Thursday, August 11, 2016 at 4:23:16 AM UTC-4, Aleksei Magusev wrote:
>>
>> I think backticks syntax makes sense for the Haskell since it has
>> function application via space, but for Elixir it hurts readability with no
>> (visible to me) benefits.
>> Calling non-guard-safe function as the guard-safe operators doesn't feel
>> like a good thing: we remove valuable hint about function property in our
>> code.
>>
>> – Aleksei
>>
>> On Thursday, August 11, 2016 at 8:51:47 AM UTC+2, Wiebe-Marten Wijnja
>> wrote:
>>>
>>> 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/835fbb57-c657-4329-a971-81f91342b44f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.