Neat. I hadn't thought of it that way before.
Neat. I hadn't thought of it that way before.
Python comprehensions, etc. are mostly just SQL -- likewise most languages where "map" is part of the collections API.
SQL motivates the utility of functional programming for data-oriented applications.
And a map can be the same as a projection as found in sql.
The difference is that many languages have constructs that weren't value producing. It is why some have the ternary operator, but lisp just had if statements.
So, to that end, most loops do produce a value. And there are several common ways they do it. In many languages, you have to give the details of how they work. In some, you can only those details and the building if the output is a bit more declarative.
Maybe it's a language issue. I would say a 'loop' has a jump and a condition. So that's 'for', 'while' and 'do' in C, JS, Python, Pascal, Java...
Lots of languages including Lisp have recursion, maps etc but I wouldn't call that looping. Clojure even has TCO recursion but it only returns one value, not a sequence (unless you accumulate the whole thing)
I am just now reading Practical Common Lisp, and amusingly one of the first things they do is build a simple query language. Didn't even use loop. So, to your point, the imperative commands of looping can be far removed from what people today call comprehensions. That said, I don't think it is inherent. Just a quirk of history.
Loops in lots of languages have outputs. It's kind of necessary in expression-oriented languages.
But it's true that comprehensions are different than Python loops in that way (and are, in fact, equivalent to maps with joins and filters, like an SQL SELECT statement.)
I draw a distinction with map, recursion, lazy sequences etc
See TransformListComprehension section. Haskell uses tricks from SQL while still having nice syntax.
http://ekmett.github.io/discrimination/ - a library to perform what SQL engines do for optimization of relational queries, online and in Haskell.
The method-chains-vs-expression-tree semantics don't matter much when doing typical in-memory map/filter/reduce on lists but make LINQ to SQL and other more complex use cases much more powerful.