6 ms·
For such a young discipline, it's amazing how much of software practice used to be standard operating procedure and is now all but forgotten. At one time Dijks
by zetalyrae 5y ago
For such a young discipline, it's amazing how much of software practice used to be standard operating procedure and is now all but forgotten.
At one time Dijkstra had to actually argue for structured programming. No-one would take the counter position today.
The equivalent debate nowadays is between languages that separate statements and expressions and expression-oriented[0] languages.
[0]: https://en.wikipedia.org/wiki/Expression-oriented_programming_language https://en.wikipedia.org/wiki/Expression-oriented_programmin...
- TeMPOraL 5y agoIs that really a debate? Gosh, I'd love to see the "separatist" arguments, because ever since I've discovered Lisp, I've automatically assumed that separating statements and expressions is one of those stupid historical baggage things, a stepping stone in early PL design that we can't just get rid of. I mean, how many libraries with weird APIs were created just because you can't write the following in most Algol-like languages: return if(sth) { foo = SomeProcessing(); Transform(foo); } else if(sthelse) { Transform(someDefault); } else { someErrorDefault; }; In many languages, people are resorting to "immediately invoked function expressions" to simulate this pattern (whether for returning or assigning). And those that can't, well, here goes another pointless little function to encapsulate it[0]. -- [0] - Which transitions into what is a real debate - "lots of small functions" vs. "fewer but larger functions". It's one of those holy wars that can't die, because both sides have good arguments. But it's a false choice - a limitation of the tools we're using to write programs. 'emilprogviz has a nice summary of that last point here: https://emilprogviz.com/ep05/ep05-transcript.html https://emilprogviz.com/ep05/ep05-transcript.html Linking to transcript, in the spirit of "text with screenshots is almost always better than a video" - (nice job providing it Emil!) - but the video itself is good too, as are others on that site.
- zetalyrae 5y agoOk it may not exist as a debate outside my own head :) To offer one argument: the problem with expression oriented languages is their generality, in that you can write "weird" expressions, e.g.: let x = [giant block of code with multiple nested lets, ifs, etc.] in f(x) I've definitely done this a number of times. Languages that separate statements and expressions force you to break things down further and prevent the code from going too far to the right. Also, for low level languages, the mapping between code and assembly is clearer in languages that separate statements and expressions (I need a more succinct term). EDIT: Also, by preventing statements from being used as expressions, you encourage breaking up long and complex statements into smaller functions.
- TeMPOraL 5y ago> in that you can write "weird" expressions Oh, I see what you mean. I discovered Lisp after working in C++ and Java, so I avoided this pitfall in my code, but if I had a dollar for every instance of: (let ((some-variable (progn (do stuff) (do other stuff) (let ((some-helper-var ...)) (some more code with some-helper-var) (more-of-the-same (progn ...))) ;; 50-100 lines later, just return one of the values some-variable) that I saw in Lisp codebases, particularly in Emacs, well... I could feed my family for a month or two from that money. There's plenty of abuse potential here (and for the love of god, if your language has 'let', it probably also has lambdas or 'flet', use that to create local functions...). But mitigating this, arguably, is a problem for style guides - the overall feature of "everything is an expression" is powerful. It has nice simplicity to it, and reduces boilerplate :). > Also, for low level languages, the mapping between code and assembly is clearer in languages that separate statements and expressions I'm guessing this is where the separation originally came from. Assembly is essentially statement-only. But at this point, I think all programming languages in use crossed the threshold where we're actually programming to an "abstract machine", and being expression-oriented seems to confer greater expressiveness. > (I need a more succinct term). "Separatist"? :). > EDIT: Also, by preventing statements from being used as expressions, you encourage breaking up long and complex statements into smaller functions. Ah yes. The real debate. I edited my comment to mention it before I saw your edit :).
- zetalyrae 5y agoYes, thank you, your code example is much better than mine. The simplifying potential of expression-oriented languages is huge. Alan Perlis said[0]: "symmetry is a complexity-reducing concept; seek it everywhere", and this is a great example of that. For example, languages like C and Ada have both if statements and if expressions, this is a duplication that can be eliminated by making them expression-oriented so you only have an if expression like in Haskell or ML. But, interestingly, there is one historical case of a language going from expression-oriented to statement/expression separation: ALGOL-W[1] was expression oriented, Pascal[2], its successor, separates statements from expressions. Wirth designed both. I don't know what the motivation was, but I suspect it's because Pascal was designed to be an educational language, and Wirth must have thought that separating expressions and statements made didactic sense when teaching programming as a recipe or list of things to do, as opposed to the more mathematized formulation of expression-oriented languages (of having an evaluation function from expressions to values). The successors of Pascal (Ada, Modula and its sequels) retain the statement/expression separation. [0]: http://pu.inf.uni-tuebingen.de/users/klaeren/epigrams.html http://pu.inf.uni-tuebingen.de/users/klaeren/epigrams.html [1]: https://en.wikipedia.org/wiki/ALGOL_W https://en.wikipedia.org/wiki/ALGOL_W [2]: https://en.wikipedia.org/wiki/Pascal_(programming_language) https://en.wikipedia.org/wiki/Pascal_(programming_language)
- ratww 5y agoI think the "separatist" side (yep I'm adopting your term) has already accepted that the war is lost, but I still see battles being waged often in programming language spec committees, whenever there's a suggestion for allowing if to be treated as an expression. The arguments against it are always that it requires having keywords that behave differently when being expressions or statements. Often the alternatives and compromises proposed always have the same issues, such as Javascript repurposing the do keyword for enclosing expression ifs.
- ItsMonkk 5y agoThe intuition that I've built up is that most of the time that you have a debate that goes on for more than about 5 minutes, there's a problem at a different abstraction level. For instance with Imperial vs Metric System, Metric optimizes for multiplication, while Imperial optimizes for division. You can never unify these under the current system. But you can, if you change our base to base 12. Then they suddenly merge. With CLI vs GUI, we've realized that we needed a mixture. We need a GUI that runs through a CLI. And now we have that, it's called a website. I think tabs vs spaces was solved similarly, with tabs as spaces that editors config can treat n-straight-spaces as tabs. I'm firmly on the expression only and lots of functions sides, but that transcript is very interesting. You can already do local functions in C#, it seems to be implying that we should strive for that to be our mixture.
- TeMPOraL 5y ago> The intuition that I've built up is that most of the time that you have a debate that goes on for more than about 5 minutes, there's a problem at a different abstraction level. I strongly agree. Also, that's poetically put. I'm saving this in my quotes file.
- lmilcin 5y agoThe issue with these debates is that these tend to be driven by people with strong opinions coming usually from misunderstanding of the other side of the debate. I like to think that there is no OOP vs FP, there is no strong typing vs no typing, there should be just adding to a shelf with tools that each has application in some situations but also constraints on when it can be used effectively. And your job as developer is to understand the bounds on application and effectiveness. The road to mastery of development then should be by learning and understand those various tools (in the broadest possible sense) rather than by forming strong opinions and shunning the other side of the debate. People who cut off themselves from OOP will never learn its benefits just as people who cut themselves from FP.
- kragen 5y agoWell, I'm not sure I'm on one side or the other of the statements-or-no-statements debate, but in general I think the argument in favor of separating statements from expressions is that it adds redundancy to your programs, which makes them easier to read and enables the compiler to produce better error messages when you have a syntax error. Sometimes you can trade this off against other aspects of syntax you'd like to improve; Lua, for example, omits semicolons and isn't white-space sensitive, but the compiler can still emit reasonable syntax error messages because of its strict separation of statements and expressions. I think you're overstating the case with return if(sth) { foo = SomeProcessing(); Transform(foo); } else if(sthelse) { Transform(someDefault); } else { someErrorDefault; }; You can transform this to the following in even the most limited ALGOL-like languages, which is less clear but not nearly as heinous as the alternatives you mention: var rv: SomeType; -- return value rv = someErrorDefault; if(sth) { foo = SomeProcessing(); rv = Transform(foo); } else if(sthelse) { rv = Transform(someDefault); } return rv; The more popular ALGOL-derived programming languages like C, Java, and post-walrus Python have conditional expressions and assignments inside expressions, which means that in this case you don't need to resort to declaring a variable. In Golang and Pascal you can just assign to the named return value rather than declaring it as a normal variable and then explicitly returning it. The argument against separating expressions from statements is also that it adds redundancy to your programs, as in the above example. I wrote an essay about this tradeoff in general, not limited to expressions vs. statements, at http://www.paulgraham.com/redund.html http://www.paulgraham.com/redund.html.
- valyagolev 5y agovon Neumann was angry at a student for writing a program that would produce binary code rather than assembling it by hand https://twitter.com/sigfpe/status/1420961392585154569 https://twitter.com/sigfpe/status/1420961392585154569
- TeMPOraL 5y agoOh, the brief time in computing history when computer time was more expensive than human time.
- valyagolev 5y agohighlights the point that not valuing either will waste both
- microtherion 5y agoIf you take into account that the particular humans whose time was (not) valued here were graduate students, that time may not have been so brief after all.
- lou1306 5y agoI mean, it sounds weird now, but back then the assembler would indeed have eaten up precious CPU time. Imagine if, nowadays, a grad student took a node in a scientific cluster to run Dreamweaver in a Windows VM instead of writing HTML by hand. (Sorry, it's the closest analogy I could come up with)
- zetalyrae 5y agovon Neumann was probably the most intelligent person ever documented. He was probably frustrated that people couldn't see the machine code fully formed in their mind's eye :)
- runlaszlorun 5y agoAgreed! I also think that von Neumann (and some of his contemporaries as well) were likely the last to be able to understand the entire breadth of math, physics, and computer science at the time. These days we’re all far too specialized…
- AnimalMuppet 5y agoNo, I don't think that's the equivalent debate today. Structured programming vs "the old way" was about clarity of control flow. Structured programming was clearly superior once you had machines with enough muscle to handle the overhead. (And once you realized that you were trying to optimize for programmer time rather than for machine time.) I don't see expression-oriented as being similar to that at all. Expression-oriented may provide a boost to programmer efficiency, but it's not nearly on the order of structured programming vs. unstructured. It doesn't require changing peoples' mindset to realizing that programmer time is more valuable than machine time; they already know that. And, the parallel problem would be clarity of data flow, and I'm not sure that expression-oriented is a huge win in that area.
- smnplk 5y ago>> And, the parallel problem would be clarity of data flow, and I'm not sure that expression-oriented is a huge win in that area. In my opinion it is, because you can compose data transformations from smaller parts. Each part can do only one thing. For example in Clojure, you could do. (def transform (comp (do-thing-a) (do-thing-b) (do-thing-c)) (map transform my-collection) Or you could use a threading macro, with thread first or thread last semantics, which can also help you build clear pipelines. (-> basket-of-apples (select-ripe) (clean) (cut-to-pieces-of-size 4) (pack)) Not to mention transducers, which can further improve and clarify data flows.