[Python-ideas] Modern language design survey for "assign and compare" statements
Mike Miller
python-ideas at mgmiller.net
Fri May 18 20:54:04 EDT 2018
Background:
While the previous discussions about assignment-expressions (PEP 572)
(abbreviated AE below) have been raging one thing that was noticeable is that
folks have been looking back to C for a solution.
But how are newer languages solving the problem today? Believe Ryan brought
this up first on the list, but it had been in the back of my mind as well.
Finally have compiled my research, corrections welcome. In alphabetical order:
Dart, 2011:
Design goal: Less confusing, conservative replacement for JavaScript.
- Assignment is a statement, not an expression.
- JS allows AE to used freely, Dart doesn't support them.
- Only option is to write simple, mildly redundant code.
Details:
https://www.dartlang.org/guides/language/language-tour#assignment-operators
https://github.com/dart-lang/sdk/issues/55
Golang, 2009:
Design goal: Simple, maintainable replacement for C++/Java/C#.
- Assignment is a statement, not an expression.
- Precursors allowed AE to be used freely
- Golang doesn't them but allows assignment inside the if statement:
if x := f(); x < y { … }
- No assignment in while (spelled for) currently allowed. Use mildly
redundant code in other locations.
Details:
https://stackoverflow.com/questions/13127929/assign-and-compare-in-gos-while-equivalent
https://clipperhouse.com/statements-are-statements-and-expressions-are-expressions-in-go-4087d103e3b7
Kotlin, 2011:
Design goal: Terse, modern replacement for Java with high interop.
- Assignment is a statement, not an expression.
- Java allows AE to used freely, Kotlin doesn't support them.
- Main option is to write simple, mildly redundant code.
(Or use std lib functionality such as forEachLine, etc.)
Details:
https://blog.kotlin-academy.com/kotlin-programmer-dictionary-statement-vs-expression-e6743ba1aaa0
https://discuss.kotlinlang.org/t/assignment-not-allow-in-while-expression/339/
https://stackoverflow.com/questions/41537638/assignment-not-allowed-in-while-expression
Rust, 2010:
Design goal: Safe replacement for C/C++, etc.
- Assignment is a statement, not an expression.
- C/C++ allow AE
- Rust doesn't, but allows an assignment clause in if/while.
if let Some(3) = some_u8_value { … }
while let Some(byte) = input.next() { … }
Details:
https://doc.rust-lang.org/book/second-edition/ch06-03-if-let.html
https://doc.rust-lang.org/stable/rust-by-example/flow_control/while_let.html
Swift, 2014:
Design goal: Modern replacement for ObjectiveC with high interop.
- Assignment returns Void
- ObjC allows AE
- Swift doesn't, but allows an assignment clause in if/while statements:
if let NAME = … { … }
if var NAME = … { … }
while let line = aStreamReader.nextLine() { … }
Details:
https://stackoverflow.com/questions/34173084/what-was-the-reason-for-swift-assignment-evaluation-to-void
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Statements.html#//apple_ref/swift/grammar/while-statement
Conclusions
------------
It appears assignment expressions are no longer the favored solution for the
"assign and compare" use case. Not one of these five newer languages supports
them fully, as the language generations from C to C# did.
Of those that have recognized the use case to be large enough—the solution has
been rather more limited to the "if" and "while" statements only. Several
folks here have expressed the same desire to confine AE there. Since Python's
design goals are similar—to be safe and maintainable I'd recommend a similar
strategy, with the addition of the list comprehension case. Going back to the
C-style solution seems like the wrong direction.
Since that would mean this special assignment functionality is not allowed to
be used everywhere, it alleviates the pressure to make it fit into
with/import/except statements. Furthermore, that frees up the keyword "as"
again, which is Pythonic, short, memorable and has a history of being used for
various assignment purposes, not to mention a prominent feature of SQL.
In short, extend the "if/elif", "while", and comprehension to:
if pattern.search(data) as match:
…
while read_next_item() as value:
…
May be best to disallow multiple assignment/conditions for now, but up for
discussion. That leaves comprehensions, which could support a EXPR as NAME
target also:
filtered_data = [f(x) as y, x/y for x in data]
or perhaps reuse of the if…as statement to keep it simpler:
filtered_data = [y, x/y for x in data if f(x) as y]
That variant might need an extra test if f(x) returns a falsey value, perhaps
"is not None" on the end.
Thoughts?
-Mike
More information about the Python-ideas
mailing list