I'm not really familiar with Algol, but I do know Pascal, and you should
think of the append method to be like a Pascal procedure. Because Python
doesn't have true procedures, it follows the convention that returning
the special object None signals the intention to return nothing at all.
Hence your example below:
Yes... Algol I dont know. But to the extent that it corresponds to
Pascal the following may help.
Pascal is remarkably clean and cleaner than what came before -- Lisp
-- and after -- C, all its derivatives, python... almost everything.
First off there are expressions and statements, and no messing with
the distinction. C started laissez-faire. No void, just default
functions intended to be used as procedures to int. This was
problematic to enough people that void was introduced soon enough.
But its still messy:
An assignment like x = 3 is both an expression and (like) a statement.
It is mostly used as a statement by appending a semicolon.
It can also be used as an expression as in y = x = 3.
Try explaining this to a first year class and you'd know what a mess it is.
For the most part if you think youve got it you probably havent.
Python is in some respects worse than C, in some better.
Its better in that assignment statements are not re-purposeable as
expressions. Its worse in that procedures are simulated by None
returning functions -- this means syntax errors which C would give
when using a void function as an expression, you wont get in python.
On the whole, whether your language supports it or not, its best to
think of the world as separated into actions and values.
Call the action-world the 'imperative' world.
Call the value-world the 'functional' world ('declarative' would be
better but 'functional' is too entrenched).
[Following table meant to be read with fixed (courier) font]
| | Imperative | Functional |
| Language entity | Statement | Expression |
| Denote (and think with) | Action | Value |
| Abstracted into | Procedure | Function |
| Atoms are | Assignment | Constant/Variable |
| Data Structures | Mutable | Immutable |
| Loop primitive | Recursion | Iteration |
| World is | In time | Timeless (Platonic) |
Generally mixing these two worlds is necessary for any non-trivial
programming but is commonly problematic.
Your error was to use a functional form -- list comprehension -- and
embed an imperative construct -- row.append -- into that. This is
always a gaffe
Legal mixing is done thus
Expression -> Statement by putting the expression on the rhs of an assignment
Statement -> Expression by putting the statement(s) into a function
While most programmers think this unproblematic, Backus' widely-cited
Turing Award lecture is devoted to showing why this is a problem
http://www.thocp.net/biographies/papers/backus_turingaward_lecture.pdf
For an old Algol/Fortran programmer it may be a worthwhile read considering
Backus invented Fortran