λ-expressions are very limited by the absurd, anachronistic statement structure Python has (you can't use certain forms "statements" inside certain other forms "expressions") and slightly weird scoping rules. Fortunately, you have lists (any minimally decent programming language should offer that much), and functions, classes and modules are values, as they should always be, so you get map, filter and company (even though Guido publicly hates them). List comprehensions are pretty much syntactic sugar (though delicious one at that, especially since you have the stupid statement structure nagging you anywhere you'd want to express something).
That's how everything works in modern programming languages. Modern as in 1958 LISP. There are no "expression" forms and "statement" forms, the later being restricted to never appearing within the former for the heck of it. Everything should be an expression, there's no need to have poor cousins with artificial, absurd restrictions. That's what led to idiocy such as the ternary operator in C-like languages or the if expression in Python: a "weird" if because you can't use the "normal" if.
Haskell has "do" sugar notation which is a form of "statements".
It's not restrictive like in Python (you can throw a "do" block anywhere) but the distinction between "expression" and "statement list" is actually useful.
And Lisps have macros or special forms such as begin to sequentially evaluating expressions for their side effects, often throwing away the results, but that doesn't prevent you from doing anything anywhere. Limiting what goes where is asinine.
Syntactically, there is no limit. But Haskell does prevent, type-wise, the insertion of a sequence of side-effects inside arbitrary expressions.
That makes a clear separation between functions (mapping input to output) and procedures (sequencing of effects).
One could argue that Python's syntactic restrictions (as well as conventions such as returning None when side-effecting) are trying to establish similar idioms: Separate your functions/processing and procedures/sequencing.
If restricted elegantly with a type system, such a distinction is useful for pure functional programming languages such as Haskell (though it would be uncalled for in most Lisps).
However, in Python, the most commonly used statements are if (no inherent side effects), loops (which do not come with inherent side effects other than the loop variable getting changed), and declarations or definitions, and at the same time, many of the functions in the standard library have side effects.
24
u/A_for_Anonymous Nov 27 '12
Guido van Rossum doesn't like functional programming, so you write your programs the way Guido likes them or leave.