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/CAK-y3CsZ0QrCNMMnwOM7PM0XsEYMHc81GKV%3DDd%3DDk1Aw8_0eDw%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
