21 ms·
Python should take a lesson from APL: Walrus operator not needed
During a recent HN discussion about the walrus operator I came to realize yet another advantage of notation. I used APL professionally for about ten years, which made it an obvious source of inspiration for an example that, in my opinion, demonstrates why the Python team missed a very valuable opportunity to take this wonderful language and start exploring the judicious introduction of notation as a valuable tool for thought (borrowing from Ken Iverson's APL paper with that title [0]).
To simplify, I'll define the desire for this walrus operator ":=" as "wanting to be able to make assignments within syntax where it was previously impossible":
if x = 5 # was impossible
# and now
if x := 5 # makes is possible
A more elaborate example given in the PEP goes like this:
Current:
reductor = dispatch_table.get(cls)
if reductor:
rv = reductor(x)
else:
reductor = getattr(x, "__reduce_ex__", None)
if reductor:
rv = reductor(4)
else:
reductor = getattr(x, "__reduce__", None)
if reductor:
rv = reductor()
else:
raise Error(
"un(deep)copyable object of type %s" % cls)
Improved:
if reductor := dispatch_table.get(cls):
rv = reductor(x)
elif reductor := getattr(x, "__reduce_ex__", None):
rv = reductor(4)
elif reductor := getattr(x, "__reduce__", None):
rv = reductor()
else:
raise Error("un(deep)copyable object of type %s" % cls)
At first I thought, well, just extend "=" and be done with it. The HN thread resulted in many comments against this idea. The one that made me think was this one [1]:
These two are syntactically equal and in Python there's no
way a linter can distinguish between these two:
if reductor = dispatch_table.get(cls):
if reductor == dispatch_table.get(cls):
A human being can only distinguish them through careful inspection.
The walrus operator not only prevents that problem, but makes
the intent unambiguous.
Which is a perfectly valid point. I get it.
Still, the idea of two assignment operators just didn't sit well with me. That's when I realized I had seen this kind of a problem nearly thirty years ago, with the introduction of "J". I won't get into the details unless someone is interested, I'll just say that J turned APL into ASCII soup. It was and is ugly and it completely misses the point of the very reason APL has specialized notation; the very thing Iverson highlighted in his paper [0].
Back to Python.
This entire mess could have been avoided by making one simple change that would have possibly nudged the language towards a very interesting era, one where a specialized programming notation could be evolved over time for the benefit of all. That simple change would have been the introduction and adoption of APL's own assignment operator: "←"
In other words, these two things would have been equivalent in Python:
a ← 23
a = 23
What's neat about this is that both human and automated tools (linters, etc.) would have no problem understanding the difference between these:
if reductor ← dispatch_table.get(cls):
if reductor == dispatch_table.get(cls):
And the larger example would become this:
if reductor ← dispatch_table.get(cls):
rv ← reductor(x)
elif reductor ← getattr(x, "__reduce_ex__", None):
rv ← reductor(4)
elif reductor ← getattr(x, "__reduce__", None):
rv ← reductor()
else:
raise Error("un(deep)copyable object of type %s" % cls)
This assignment operator would work everywhere and, for a period of time, the "=" operator would be retained. The good news is that old code could be updated with a simple search-and-replace. In fact, code editors could even display "=" as "←" as an option. The transition to only allowing "←" (and perhaps other symbols) could be planned for Python 4.
Clean, simple and forward-looking. That, to me, is a good solution. Today we have "=" and ":=" which, from my opinionated perspective, does not represent progress at all.
[0] http://www.eecg.toronto.edu/~jzhu/csc326/readings/iverson.pdf http://www.eecg.toronto.edu/~jzhu/csc326/readings/iverson.pd...
[1] https://news.ycombinator.com/item?id=21426338 https://news.ycombinator.com/item?id=21426338
- sedachv 7y agoSmalltalk (among other languages of the 1960s and 1970s) had a left arrow symbol as the assignment operator. 95 was ← instead of _ in ASCII pre-1967. Also, anyone pretending to be a competent computer programmer while whining about being unable to use Unicode in your text editor, please find a new hobby.
- squiggleblaz 7y ago> Also, anyone pretending to be a competent computer programmer while whining about being unable to use Unicode in your text editor, please find a new hobby. Yes. It seems like programmers are people who make the technology of the next generation using the technology of the previous generation.
- tuukkah 7y agoIn summary, Python needs it to be written := and not ← because the latter is not ASCII and not on standard keyboard layouts. And it cannot be written <- either because that would redefine what "if x<-5" currently means, ie. "if x < -5". Interestingly, the PEP considered the close alternatives "if x from -5" and "if -5 -> x": https://www.python.org/dev/peps/pep-0572/#alternative-spellings https://www.python.org/dev/peps/pep-0572/#alternative-spelli...
- phlakaton 7y agoI like it! Reminds me of one of my favorite Haskell extensions: https://wiki.haskell.org/Unicode-symbols https://wiki.haskell.org/Unicode-symbols I mean, I've never attempted to actually type that beastly notation during programming, but it does print out quite beautifully!
- squiggleblaz 7y agoIt's not beastly. Just a few :imap's will get you there in vim.
- rbanffy 7y agoPython and APL are almost opposite extremes of the readability spectrum. APL is an almost perfect textbook example of write-only code. I would be extremely weary about borrowing syntax from APL or J.