The biggest (IMHO) justifiable complaint against Python's indentation-sensitive syntax is that it makes copying and pasting harder (in editors that don't support it or with people who don't know the indentation commands...), but I've had more luck copying-and-pasting Python (with no adjustment) than I have Erlang. With Python you have good odds that you're on the same indentation in both source and dest, with Erlang the odds that you're going to screw up ",;. " (and note the space in that quote on the end, it's part of the set) approach 100% in my experience.
Nice language in many ways... shame about the syntax.
"." ends an expression in the shell.
In modules, "." ends forms. Forms are module attributes and function declarations. Forms are technically not expressions as they don't return anything. This is why they are terminated in a different manner than the rest. Given forms =/= expressions, It could be argued that the shell's use of "." is what's not standard here.
"," separates expressions:
C = A+B, D = A+C
Note that 'if ... end', 'case ... of ... end', 'begin ... end', 'fun() ... end' and 'try ... catch ... end' are all considered expressions as they return a single value. As an example, it's possible to do Var = case ... of ... end
to get a single value out of it. As such, you might see conditional expressions followed by ",".";" Has two roles: separating different function clauses:
fac(0) -> 1;
fac(N) -> N * fac(N-1).
And separating different branches of expressions like 'if ... end', 'case ... of ... end' etc.: if X < 0 -> neg;
X > 0 -> pos;
X == 0 -> zero
end
It's probably the most confusing one because the last branch doesn't need to have the ";" following it: it separates them, not ends them. As such, you might encounter code written the following way, which is arguably more readable: if X < 0 -> neg
; X > 0 -> pos
; X == 0 -> zero
end
This makes things a bit more explicit. Because function clauses contain expressions, you might see a 'case' construct followed by ";", too (and similarly for nested constructs like the aforementioned 'try ... catch ... end' and others).So as you can see, "." is for Forms, and ",;" are for separating language constructs/expressions. This is why You can see an if expression's 'end' done the three following ways: 'end.', 'end,' and 'end;'. Depending on where the expression is, it will be followed by different stuff.
You need to see it more like a template you can fill in than "here, let me put an end to this line!":
head1(Args) [Guard] ->
Expression1,Exp2,...,ExpN;
head2(Args) [Guard] ->
Expression1,Exp2,...,ExpN;
headN(Args) [Guard] ->
Expression1,Exp2,...,ExpN.
I don't see the rules as complex; they make sense, but you need to get used to them. If you think about it, things like 'for(int i = 0; i >= x; i++){ ... }' (or even 'for(...);') have a weird syntax when compared to most other constructs in languages supporting them. We're just so used to them we don't mind them anymore.Also, to put it in a C context, when you do:
if (condition)
thing();
else
other_thing();
you frequently want to put debugging code in the "thing()" clause, and so eventually many people (including me) adopt a style of always using the braces, after getting bitten a few time. Erlang basically mandates the lack of braces, so I'm always getting annoyed by adding a statement here or there, or twiddling a function definition. It's a constant low-level annoyance that never stops me from using it for what it is good for (because it is oh-so-good at it), but it doesn't have to be there.