In LISP-like languages all language constructs are first-class citizens.
Consider the following example in Dylan:
let x = if (c)
foo();
else
bar();
end;
and in LISP:
(setf x (if c (foo) (bar)))
In Python you would have to write:
if c:
x = foo();
else:
x = bar();
Because Python destinguishes statements and expressions.
Can all language constructs in a language which adheres to the off-side rule (has an indention-based syntax) be expressions, so that you can assign them to variables or pass them as parameters?
I don’t see the relation with first-classness here – you’re not passing the
ifstatement to the function, but the object it returns, which is as fully first class in python as in lisp. However as far as having a statement/expression dichotomy, clearly it is possible: Haskell for instance has indentation-based syntax, yet as a purely functional language obviously has no statements.I think Python’s separation here has more to do with forbidding dangerous constructs like “if x=4:” etc than any syntax limitation. (Though I think it loses more than it gains by this – sometimes having the flexibility sufficient to shoot off your foot is very valuable, even if you do risk losing a few toes now and again.)