Here's how I look at it...
First, a literal "counts" as a statement. You can say:
foo();
'this is a string';
bar();
The string-as-statement doesn't do anything, but it's syntactically "correct." You could have also put a number there. I use this sometimes when I want to loop while something is true, but I don't otherwise have a loop body.
1 while ( s/^\t// );
Rather than a simple scalar as a statement, you could also have a list, delimited with commas. The list elements can be calls to subs or whatever else you might stick in a list.
# assignment
@foo_and_bar = ( foo(), bar() );
# same thing, not assigned to anything
foo(), bar();
There may also be a way of thinking about this that has to do with operator precedence (the comma is an operator), but I personally don't look at it that way. Having written this now, I wonder how this compares to the actual semantics. This kind of construct is one that I encounter infrequently enough that I haven't needed to know the gory details.
Update: Upon further consideration, I think all these are expressions. A sub call is an expression, a literal scalar is an expression, and a comma-separated list of expressions is an expression. You could even have two semi-colons on top of each other and make an empty expression. |