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 <https://www.youtube.com/watch?v=_ahvzDzKdB0>': "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.
