3 ms·
Either everyone involved with language design has never heard of Lisp or there are inherent tradeoffs with "everything that can possibly be an expression should
by orf 6y ago
Either everyone involved with language design has never heard of Lisp or there are inherent tradeoffs with "everything that can possibly be an expression should be" that you are either ignoring or wilfully ignorant of in order to score internet points.
I know which one I would bet my money on.
- JadeNB 6y ago> Either everyone involved with language design has never heard of Lisp or there are inherent tradeoffs with "everything that can possibly be an expression should be" that you are either ignoring or wilfully ignorant of in order to score internet points. Entirely seriously, what are the trade-offs? I've heard general defences of it, for example nchammas's quote from van Rossum in a sister post to yours, but they all seem quite general—"it'll complicate things", but in a way that seems only to boil down to "it's unfamiliar and I don't like it." Which, to be fair, is van Rossum's prerogative to say—but it doesn't seem persuasive in light of general language design.
- neolog 6y agoPython has some non-expression statements and you wouldn't be able to use them in match expressions.
- rsj_hn 6y agoSome constructs are more natural (e.g. easier to read and write) as statements, others as expressions. It's never good to have rigid rules about programming style as each problem domain is different. There are many situations where you want lots of branching because that's the problem domain, and trying to hide the essential aspect of the problem domain isn't helpful for code readability or maintainability. If you are writing an interpreter, case statements are a natural thing. Yes, you can write that intepreter with expressions that are statements in disguise, but just because something can be done doesn't mean that it should be done. An interpreter is just a dispatcher waiting for some trigger from the outside and then firing off a command handler depending on the trigger. Just like a UI. GUIs are are also natural things to write with event driven patterns. If user clicks on box A, then do X, if User clicks on box B, do Y. That is a big case statement in disguise except the underlying framework handles that for you and you just write the code for X and Y. But if you didn't have that UI toolkit doing heavy lifting you would find yourself writing event loops and case statements to implement it as the most natural (non-ideological) solution. Similarly, there are many situations where you want to handle exceptional conditions separately in a clear way that allows you to easily understand what the exceptional logic is and change it without touching the main processing flow at all. It all depends on the problem domain. Or the problem domain may require feedback where the handler tells the dispatcher to change the dispatch algorithm. On the other hand, fluent APIs work well with streams of data that are processed sequentially. There the natural approach is to apply a sequence of functions to the stream. You want to avoid lots of nesting of case statements as the code would be ugly. It boils down to minimizing complexity. You could write that event driven dispatcher as a function that takes as its inputs all the possible callbacks and the state of the world and spits out a specific callback. But that would be a more complex program that is harder to read and write, and thus is more error prone, regardless of the fact that in theory it is easier to refactor and unit test by dropping in a different function. In practice, it is not easier, it is harder. So when someone like Guido says, "it will complicate things", no it doesn't boil down to "I'm unfamiliar and don't like it", what it means is "I've spent a couple of decades writing code, have been up and down this road more times than you have, and I know it's a harder road to travel".
- creata 6y ago> Some constructs are more natural (e.g. easier to read and write) as statements, others as expressions. Yes but imo, Haskell (which has do notation) and Rust (where most things are expressions, but you still write them as expression statements when writing imperative code) actually have solutions to this problem. On the other hand, Python has a sharp divide between expressions and statements, so it needs strange duplicate forms of statements as expressions, like ternaries (if expressions but in a really weird order!) and lambdas (function expressions but your body is just an expression!) > So when someone like Guido says, "it will complicate things" Yes, it would complicate Python, which already has this division. In other languages, it's perfectly simple.
- pansa2 6y agoIn Rust, some expressions (e.g. `while`) always evaluate to `()`. What’s the benefit of that compared to making `while` a statement?
- deleted 6y ago[deleted]
- creata 6y agoI can't think of a benefit (besides consistency, which might be nice for some macros) but is it doing any harm? And, in the future, if Rust does get some kind of return-via-break for while loops (like it has for `loop`s) then there'll be less syntax to change.
- creata 6y agoSure, in an existing language like Python, it can be a poor fit to make everything an expression, but what are the tradeoffs for a new language? For example, Rust makes (almost) everything an expression, and I don't think it's suffered at all for it.