Happy Precedence Day!
Happy precedence day!
(For my non-American followers, it's a pun on a national holiday we got today)
New Consulting Offering
I'm now available to do paid talks! Currently offering my TLA+ lecture, my empirical engineering lecture, and the crossover project talk I'm working on. Spread the word!
Formal Methods Tweetstorm
I just listed a very broad layout of the different categories in FM and the respective tools available. You can read it here.
Precedence is weird
Okay let's talk precedence. Everybody knows that multiplication comes before addition. So we interpret 6x + 5
as (6*x) + 5
instead of 6*(x+5)
, which makes it easy to express polynomials. 6x² + x + 9
. We also know that when things have the same precendence, we go left to right. So 1/2*x
is half of x, not one over 2x
.
Not so fast! What's 1/2x
? A lot of scientists and mathematicians would actually parse that as 1/(2x)
! There's a much easier way to write half of x: x/2
, which is shorter and clearer. So if you're not doing that you must have a reason, like you actually want to express 1/(2x)
.
If that seems like a stretch, try 3y/2x
. Everybody parses that as (3y)/(2x)
. Operator precedence can actually be contextual. Or try e^2x^2
. That's reasonably interpretable as e^(2x^2)
, as opposed to what the conventional precedence rules give you, which is (x*e)^2
.
Yes, you could fix this all by using parenthesis, but for some reason people really hate parens? Like so do I, 1/(2x)
just looks "worse" than 1/2x
. And it's hard to balance parenthesis. It's easy to lose track of (a + ((b - c)/((d^(2)*f)+e)y))x
. People tend to use layouts to make this easier to parse, so we'd instead write
( b - c )
(a + ------- y ) x
( fd² + e )
A lot easier to follow. Unfortunately we can't easily type that out on screens, not without pulling in something like LaTeX, which is itself a pain. Contextual precedences make things look cleaner, which people want. But it's inconsistent to machines, which makes it impossible to program with. Almost all languages use infix, and if it looks ambiguous it resolves to something consistent, just not necessarily what you intended. IE is A && B == C
equivalent to (A && B) == C
or A && (B == C)
? It'll do one, but unless you're familiar with the precedence rules it's not clear which one.
There are a few ways people have tried to make it either more consistent or less ambiguous:
- Polish Notation: Treat the entire operation as a stack, where you push and pop values. In regular PN, you'd write
(1+2)*3
as* + 1 2 3
and1+2*3
as+ 1 * 2 3
. You could also reverse it into1 2 + 3 *
and1 * 2 3 +
respectively.¹ RPN used to be be used in HP calculators - Lisp Style: Prefix notation, with explicit parenthesis.
(1+2)*3
is written(* (+ 1 2) 3)
and1+2*3
is(+ 1 (* 2 3))
. Never ambiguous, but people dislike a lot of parens to the everlasting frustration of lisp fans. -
APL Style: No precedence at all, everything is strict right to left.
(1+2*3)=7
, but(2*3+1)=8
. Also1+2*3=7
⇒1 + (2 * (3=7))
⇒1
. It has its prons and cons.I think the real upshot of this is when you gotta introduce entirely new symbols that mix with conventional ones. Like how does precedence work for
A+B⊕C
? Better just make it all the exact same and avoid the problem entirely.
"What do we mean by precedence, anyway" is one of those cool questions that shows how math conventions are just that, conventions. There's a similar question I really like: "what number do you round -1.5
to? And that usually triggers a discussion of what we mean by rounding, what we actually want to accomplish, and why we choose the conventions we do.
I got nothing to close this out, I just really liked the pun
¹ No promises I got this right
If you're reading this on the web, you can subscribe here. Updates are once a week. My main website is here.
My new book, Logic for Programmers, is now in early access! Get it here.