Python should take a lesson from APL: Walrus operator not needed
102 points| robomartin | 6 years ago | reply
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.pd...
[+] [-] viraptor|6 years ago|reply
[+] [-] ken|6 years ago|reply
I for one am tired of programming languages trying to eke out the best ASCII art they can manage with the symbols that happened to end up on American keyboards by historical accident. Or wanting to look 97% the same as ANSI C, even though their semantics are completely different.
For the people who really cannot type anything but US-ASCII on their DEC VT100 terminals, and don't use an editor or operating system which allows them to compose other characters, there are still ASCII combinations that look more or less like a left-arrow, and which are invalid Python syntax today.
[+] [-] aaron_m04|6 years ago|reply
[+] [-] catalogia|6 years ago|reply
[+] [-] thomasahle|6 years ago|reply
[+] [-] goatinaboat|6 years ago|reply
While I agree that everything should be ASCII the Python community believes everything should be Unicode, since Python 3.
[+] [-] danso|6 years ago|reply
I wouldn't mind seeing `<-` in Python. My biggest issue with `←` is that it's too inconvenient to type, as others have pointed out.
[+] [-] squiggleblaz|6 years ago|reply
Would programming in a language with first class variables like Haskell help you? In Haskell, x = y means "let x and y be synonyms, which the compiler can freely substitute" whereas to mutate a value you have to say something like `put x y` (x is not a variable, it merely refers to a variable). It's approach is so different from standard that it explodes my head but I wonder if it's more approachable to nubs.
[+] [-] fred256|6 years ago|reply
[+] [-] BerislavLopac|6 years ago|reply
[+] [-] jodrellblank|6 years ago|reply
[+] [-] improbable22|6 years ago|reply
[+] [-] oefrha|6 years ago|reply
Here's the full list of Python operators[2] as of 3.8:
The post is probably just trolling, but still.[1] https://docs.python.org/3/reference/simple_stmts.html#gramma...
[2] https://docs.python.org/3/reference/lexical_analysis.html#op...
[+] [-] tuukkah|6 years ago|reply
Interestingly, the PEP considered the close alternatives "if x from -5" and "if -5 -> x": https://www.python.org/dev/peps/pep-0572/#alternative-spelli...
[+] [-] jacquesm|6 years ago|reply
[+] [-] urda|6 years ago|reply
[+] [-] robomartin|6 years ago|reply
[+] [-] ryl00|6 years ago|reply
[+] [-] jmount|6 years ago|reply
[+] [-] patrec|6 years ago|reply
[+] [-] phlakaton|6 years ago|reply
I mean, I've never attempted to actually type that beastly notation during programming, but it does print out quite beautifully!
[+] [-] squiggleblaz|6 years ago|reply
[+] [-] sedachv|6 years ago|reply
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|6 years ago|reply
Yes. It seems like programmers are people who make the technology of the next generation using the technology of the previous generation.
[+] [-] sloaken|6 years ago|reply
[+] [-] robomartin|6 years ago|reply
As is often the case, the responses contain a bunch of hateful stuff as well as people who actually try to engage with the ideas presented in a constructive manner. To state the obvious: I am not changing anything, so chill people.
Now to address some of the responses, starting with the best:
> I wanted to just drop a comment that I appreciate the time you took into this write up with code examples. It made understanding your POV very easy.
Thank you. Some of the comments lead me to believe we might have created a society where everything needs to be done in 140 characters. I am old school, arguments needs to be presented with enough background information for the reader to understand the perspective that led to the proposal or conclusion. Without that we are all just screaming things and waiting to see what sticks.
> APL is an almost perfect textbook example of write-only code.
Sure, just like math and musical notation are write-only. The only people who say stuff like this are those who don't know a thing about APL. There are two major APL compilers still on the market, the licenses for these cost in excess of $2,500 per year. If APL was "write-only" these two companies (IBM and Dyalog) would have shelved these products decades ago. The fact is that, while not mainstream (and for good reasons), APL is still in use and large codebases are being maintained and expanded. Historically this has mostly been in the financial sector.
Point of interest: My last large APL application was for a hardware/software system used during the race to decode the human genome. Among other things, my application interfaced with the hardware and was used to search for genomes in the sequences being produced. It also produced reports, graphs, managed the database, etc. The hardware portion was coded in Forth.
> APL's assignment operator is very strange to me
Thanks for a very detailed comment with code examples. I think I can help clarify the basic ideas.
The first thing to do is realize the assignment operator isn't passive but rather an active component of a statement being evaluated from right to left. That last part is important, APL evaluates from right to left, the only precedence rule being parenthesis are evaluated first. One could say indexing is also an exception but indexing "variable[23]" is a single monolithic expression that isn't separable, so it is evaluated as one item, not two.
So, if A and B are defined as vectors (APL's name for one dimensional arrays), each consisting of a few random values between 1 and 10:
We can, for example, concatenate them like this: Again, right-to-left evaluation says "take b, set it up to concatenate to something, ah, we are concatenating to a, another vector".However, we can modify this process by giving the interpreter further instructions within the assignment. The simplest one is where we select, or index, the vectors and only grab specific elements to concatenate. I'll define a pair of new vectors to make this easier to see:
With this: The first few are the obvious cases, where we pull elements out of the right side vector and concatenate them to the left side vector. In the other cases we take the entire right side vector and concatenated to a subset of elements of the left side vector. I'd say this forms the basis for understanding the expressions you presented.The above statements can be combined with assignment in order to do the work more efficiently, plain concatenation being the simplest case:
Again, right-to-left, we have vector "f", it will be concatenated to something, the assignment is a concatenation, it is concatenated and assigned to vector "e".In other words, one can specify operations as part of the assignment. Because evaluation is from right to left, it stands to reason that the add-on operation has to be specified after you told the interpreter you are going to assign. This might be strange from the context of other paradigms but it makes complete sense once you grok the simple "everything is right-to-left" idea. If I were to propose how to read something like ",←" I would say "assign with concatenation"; "+←" would be "assign with addition".
We can do even more. It's easier to show this with multidimensional arrays:
The first statement reads something like this: Take the character vector "ABCDEFGHIJKL" we are going to reshape it "⍴" using a two dimensional numeric vector "3 4", thereby creating a 3x4 matrix and assign it to "g".Note that "i" contains characters, not numbers, so if I try to add 1 to every value I get an error:
Now I can do a few things, for example:Concatenate g and h along the first axis (they both have four columns):
Of course, all I have to do is add the assignment operator to change g: As you can see, this is a natural extension of the syntax and the order of evaluation.We can concatenate along the second axis if we use g and i:
Assignment works just as well in this case: This syntax does have limitations. For example, what if I actually wanted to end-up with this? Well, we transpose the matrices during the concatenation, this works: This does not work: I don't recall why this is so. I think it has to do with starting to gobble-up piles of memory to keep intermediate results or something like that. You also end-up executing transpose (⍉) twice, which is inefficient. I don't remember.This is a case where you have to resort to the simpler case:
With assignment: In other words, concatenate along the first axis, transpose and then assign.I got a little off track here with respect to the idea of using a different assignment symbol for Python but I thought your comment and implied question was one of the most interesting ones in the thread, which made it fun to address. I hope this helps. Here's a very useful resource:
https://www.dyalog.com/uploads/documents/MasteringDyalogAPL....
Ah, I do have to address one more:
> That's not on my keyboard.
Really people? It's 2019. I was typing APL characters back in the 1980's on DEC and Tektronix terminals and the IBM PC. Imagine the audacity of proposing that one can actually enter things other than ASCII or what's on the keyboard in 2019.
On the free NARS2000 interpreter you enter "←" very simply with "Alt [". In fact most APL characters are entered this way. The reshape operator, rho, "⍴", is entered using "Alt r". Not that complicated. I am sure this is well within the brain capacity of most mortals, it was so over 30 years ago.
Final thought: One of the interesting things about using APL long enough to internalize it (something like what happens when you don't think about reading musical notation any more and just see the music) is that you start thinking and seeing objects and their manipulation in your brain.
The analogy that comes to mind is what I do when I run SolidWorks. I can extrude, cut, scale, rotate, cut holes, create solids from rotated profiles, slice, animate and manipulate complex assemblies of three dimensional objects visually and with ease. The --imperfect-- analogy to conventional programming would be something like AutoCAD, which I have been using since version 1.0 in the dark ages. It's a flat 2D world. Yes, it can do 3D but the cognitive load and lack of tools makes it a terrible tool for working with three dimensional solid objects and assemblies.
Live long and prosper.
[+] [-] anthony_doan|6 years ago|reply
So being pragmatic I would choose <- over ←.
[+] [-] kelnos|6 years ago|reply
(In case it isn't clear, that evaluates as "if x is less than negative two".)
[+] [-] goodside|6 years ago|reply
[+] [-] Sean1708|6 years ago|reply
[+] [-] b0rsuk|6 years ago|reply
[+] [-] geofft|6 years ago|reply
[deleted]
[+] [-] unknown|6 years ago|reply
[deleted]
[+] [-] rbanffy|6 years ago|reply
I would be extremely weary about borrowing syntax from APL or J.
[+] [-] stuaxo|6 years ago|reply