Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I am contemplating writing a programming language. Most grammars define expressions as being a kind of a statement. But really I cannot come up with a single example of any useful expression that would pass as a statement.

See http://stackoverflow.com/questions/19132/expression-versus-statement for an easy definition of expression vs statement.

EDIT: Why are so many grammars making the distinction between expr and stmt when as noted in the answers, it makes no sense.

share|improve this question
5  
What's wrong with a hobby project?? It already generates MSIL code for a hello world.. so I'm well on my way :-) –  Carlo V. Dango Aug 12 '12 at 17:24
5  
@JimG. How the heck does this warrant a downvote? To remind you, the button says "This question does not show any research effort; it is unclear and not useful". Also, writing programming languages is awesome, even if they never see any real-world adaption and suck. –  delnan Aug 12 '12 at 17:29
1  
There's nothing wrong with a hobby project; it's just that people who have a fighting chance of building a viable programming language tend to have more focused questions. // In any case, I highly recommend that you look at Eric Lippert's answer for general advice. Good luck! programmers.stackexchange.com/questions/84278/… –  Jim G. Aug 12 '12 at 17:30
2  
@CarloV.Dango: I just changed my downvote to an upvote. –  Jim G. Aug 12 '12 at 18:26
2  
Kudos to Jim G. for changing his mind instead of digging his heels in. –  Stuart Marks Aug 12 '12 at 20:14

4 Answers 4

up vote 3 down vote accepted

A function/method call is, of course, an expression. At the same time (in imperative programming languages, which I assume since you seem to take statements for granted) many functions have side effects and those side effects are often enough incentive to call the function. Consider functions like printf which exist primarily for their side effect and whose return value (in this case, number of chars printed) is usually not interesting. Or basically any function/method with no interesting return value -- i.e. void or () AKA unit. (While you could, in a statically-typed setting, differentiate between the two, doing so is entirely pointless.)

In languages with operator overloading, this extends to any expressions involving operators (read: almost all expressions), because these are basically functions as above, only called differently. Sometimes a bad idea, yes, but then there's embedded DSLs.

Also, if you make assignment an expression (bad idea IMHO, but rather common), you practically need it to also be valid as statement. Ditto for pre- and post-increment and -decrement -- these are expressions, yet mostly useful as standalone statements.

EDIT: As for why the distinction exists: Statements are distinct from expression so the grammar can prevent statements from being used as expressions. An example in Python: The "expression"

f(def g():
    pass
)

has multiple problems (primarily: does not work with the - otherwise great and simple - way indentation is handled; can be easily turned into a inner function definition) which make it utterly useless. For comparision, def g(): pass; f(g) is perfectly valid and sometimes (if f wants a callback and you want a no-op for that) useful. And not all languages accept every expression as statement -- many either rule out alternatives which never make sense (cf. Pascal, C#), or give a warning ("statement has no effect").

share|improve this answer
    
Very well put! Why is assignment a bad idea? eg. using(var conn = new DBConnection(..)) a bad idea? –  Carlo V. Dango Aug 12 '12 at 17:28
1  
@CarloV.Dango That example isn't a bad idea, but that's because it's not an assignment, it's a declaration (coupled with initialization). A bad idea is while (a = b) (typo'd a == b, bad because it is wrong) and almost any case where you use a = b as part of a larger expression, because it does not properly shout "side effect". A possible exception (some people like it, some don't) us chained assignment like a = b = c. –  delnan Aug 12 '12 at 17:33
1  
How about int c; while( (c=readChar()) != -1) { ... } –  Carlo V. Dango Aug 12 '12 at 17:37
1  
@CarloV.Dango Terribly unclear in my opinion, and only saves you very little. I use either while (true) { c = readChar(); if (c == -1) break; ... } or c = readChar(); while (c != -1) { ...; c = readChar(); }. –  delnan Aug 12 '12 at 17:42
    
I am not sure what to think. First time I saw the construct I hated it. In the simple context of this 1-line program it looks like a sweet pearl :-) do you have a website where your language design opinions are posted? –  Carlo V. Dango Aug 12 '12 at 17:47

"What useful expressiveness will be impossible in a language where an expression is not a statement?"

None.

The definitions of "expression" and "statement" are largely arbitrary. Different languages define them differently. I know of no programming language whose way of defining these terms makes any particular construct impossible to express. In some languages, some constructs may be a bit more awkward; in others, it may be easier to write code that's difficult to read because a single statement depends on multiple side effects.

Almost all programming languages are Turing-complete and are able to express the same behaviors as any other Turing-complete languages.

Two good examples are Pascal and C.

In Pascal, an assignment is a statement, not an expression. A subroutine can be either a procedure (which doesn't return a value) or a function (which does). A procedure call is a statement, and cannot be part of an expression. A function call is an expression, and cannot appear in a statement unless you explicitly do something with the result, such as assigning it to a variable. Statements can contain expressions, but expressions cannot contain statements.

In C, an assignment is an expression. All subroutines are functions; functions that return no value are declared with a return type of void. A function call is an expression; it can be made into a statement by adding a semicolon. The result of a function call, or of any expression, can be silently discarded. Any expression can be turned into a statement by adding a semicolon. As in Pascal, statements can contain expressions, but expressions cannot contain statements (but gcc provides statement expressions as a language extension).

Here's a typical C construct that depends on the ability to treat assignments as expressions (item is some arbitrary type, and last_item is a constant of that type):

item x;
while ((x = get_next_item()) != last_item) {
    do_something_with(x);
}

In Pascal, you can implement exactly the same behavior like this (if I remember the syntax correctly):

var
    x: item;
    done: boolean = false;
begin
    while not done do
    begin
        x := Next_Item;
        if x = last_item then
            done := true
        else
            do_something_with(x);
    end;
end;
share|improve this answer
    
How would you do a = b in C without using (C's definition of) an expression as statement? –  delnan Aug 13 '12 at 6:47
    
@delnan: If C didn't have expression statements, surely it would have an assignment statement. But to answer your question, if (a = b); isn't an expression statement. –  Keith Thompson Aug 13 '12 at 7:48
    
Yeah, you'd have to sacrifice expression statements for that (though I'd be a hypocrite to cling onto them, I'm sure many people lean towards finding them useful). Sure, you can define assignment and function calls to also be statements, without pulling in the rest of all expressions. But allowing a subset of expressions as statements should already qualify for "an expression is a statement" IMHO, considering that some modern languages do this (and still talk of "expression statements"), and others allow it but give a warning. –  delnan Aug 13 '12 at 7:57

If you refer to the definitions that are provided on those pages, its easy to see why its difficult to come up with an expression that would pass as a statement.

Expression: Something which evaluates to a value. Example: 1+2/x

Statement: A line of code which does something. Example: GOTO 100

The expression is only the subject of the statement. If you're not assigning it to something in the end, then there's not a whole lot you can do with it.

You might want to look into lisp though.

share|improve this answer
    
I don't want to look at LISP anymore :-) I want static typing a light weight syntax. I want to rid excessive () and ; –  Carlo V. Dango Aug 12 '12 at 17:26
    
As you should know (since you refer to Lisp), evaluating to something does not imply not doing anything, and vice versa. Things like f() and a = b evaluate to values in many, many languages. In many functional languages, even launchTheMissles evaluates to a value (namely, the empty tuple). –  delnan Aug 12 '12 at 17:40
    
@delnan yes, and in Smalltalk there are no void methods, they return 'this' instead. I've searched my soul and prefer void. I have to read up on F# options though before making any decitions in stone. –  Carlo V. Dango Aug 12 '12 at 18:13

Things like the traditional send call for sockets is a good example:

int send(int socket, char* buffer, int flags);

The 'bytes sent' return isn't strictly vital for the function to do its business.

You could of course say that not checking the bytes sent is an error and that your language should not allow that as input. The issue comes that parsing is done before the types are ever known. When parsing

send( socket, buffer, 0 );

your compiler has no idea if send returns a value or not. In most languages, that simple standalone expression is desirable to be allowed as a statement.

share|improve this answer
    
The compiler does know the return type of send when it's performing semantic analysis. If the language disallowed using a value-returning function call as a statement, the compiler could easily diagnose the error at that point. The fact that the return type isn't known during parsing is not an obstacle. In Pascal, for example, send could be either a function or a procedure; the latter would be legal in this context, but the former would not. –  Keith Thompson Aug 12 '12 at 19:49
    
@KeithThompson - the OP asked specifically about grammars of existing languages, which mean lexing or parsing. This could certainly be done at the semantic analysis step, but would not change the grammar to not accept expressions as statements. –  Telastyn Aug 12 '12 at 20:35

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.