I'm thinking of doing this for symbolasm also.
This here seems like a very good idea and I hope other languages in active development take note. And als JS’ Prettier, which actively removes parentheses like these.
E.g. 1 & 2 == 0:
Python => True
C => 0 (False)Lisp because everything is explicit and only the form just inside an opening parenthesis does anything. APL as all is scanned right to left.
a op1 b op2 c
is an error if op1 is unequal to op2 and they have the same precedence. Do I see that right?Also, it seems each operator will have to have a associativity to handle a future operator for exponentiation or (also potential future) custom operators.
Finally, the “What you need to know” section doesn’t mention orelse. Where does that fit in?
Presumably orelse is not in the table because it requires parentheses for any other operator.
Operators cause issues because it is not possible to cleanly express error output from an operator, it is not possible to express the bit-width of the operation, have to understand precedence.
All of these issues cause other downstream issues.
Why not add_u64()?
> have to understand precedence
Precedence is not in any way an argument against using operators; you could disallow precedence at all (eg. each expression must have at most one operator, or rather two counting the assignment operator) while still having operators. That said, precedence is also very beneficial to readability when not abused.
> Operators cause issues because it is not possible to cleanly express error output from an operator
Incorrect. An operator can simply desugar to functions, and therefore has the exact same error semantic possibilities. If you take issue with a language not returning errors from operators, that is a language design issue, not something inherent to the existence of operators.
Also, functions can be used as callbacks, and offer overloads to handle partial applications with ease, pipe(2, sum(3), multiply(2)), e.g.
This Zig change is the best of both worlds: avoid the ambiguity, but keep the readability.
If your language doesn't allow you to do the same thing with operators as you can do with functions, that's a language design issue and has nothing to do with operators as a concept.
It depends on what things you work on. When I'm writing 'math-y' code (GPU shaders for renderng etc) then I want the expressions to look close to the reference paper and not artificially split them up into multiple lines of code with function calls instead of operators.
(a + b + c + d) * e
mult(add(a, add(b, add(c, d))), e)
a
|> add(b)
|> add(c)
|> add(d)
|> mult(e)
> mult(add(a, add(b, add(c, d))), e) c
|> add(d)
|> add(b, _)
|> add(a, _)
|> mult(e):)
(* (+ a b c d) e)Though the main reason for infix notation is to signal associativity. Which a lot of these don't satisfy.
A lot of these are just trying to mimic natural language, which can be useful but as lisp demonstrates is not that important if the grammar is clear enough.
assign(result, add(b, mul(c, sub(d, e)), add(add(f, g), array_get(arr, i)));
(I bet I messed up the parentheses somewhere).At that point, even assembly code is more readable. Also there's a reason why Lisp and Forth haven't exactly taken the world by storm ;)
I ended up doing a bunch of work on it in a slightly broader and more formal setting during my phd (https://dl.acm.org/doi/abs/10.1145/3571251) with the expectation that it probably wouldn’t be relevant for more mainstream languages any time soon, very happy to be wrong on that.
-a ** b
Someone who learned PEMDAS in school may argue it should be equivalent to -(a * b), while a programmer may be used to unary operators binding tightest, so (-a) * b.