7

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 https://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.

11
  • 5
    What's wrong with a hobby project?? It already generates MSIL code for a hello world.. so I'm well on my way :-) Commented Aug 12, 2012 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.
    – user7043
    Commented Aug 12, 2012 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.
    Commented Aug 12, 2012 at 17:30
  • 2
    @CarloV.Dango: I just changed my downvote to an upvote.
    – Jim G.
    Commented Aug 12, 2012 at 18:26
  • 2
    Kudos to Jim G. for changing his mind instead of digging his heels in. Commented Aug 12, 2012 at 20:14

4 Answers 4

3

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").

6
  • Very well put! Why is assignment a bad idea? eg. using(var conn = new DBConnection(..)) a bad idea? Commented Aug 12, 2012 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.
    – user7043
    Commented Aug 12, 2012 at 17:33
  • 1
    How about int c; while( (c=readChar()) != -1) { ... } Commented Aug 12, 2012 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(); }.
    – user7043
    Commented Aug 12, 2012 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? Commented Aug 12, 2012 at 17:47
3

"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;
3
  • How would you do a = b in C without using (C's definition of) an expression as statement?
    – user7043
    Commented Aug 13, 2012 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. Commented Aug 13, 2012 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.
    – user7043
    Commented Aug 13, 2012 at 7:57
1

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.

3
  • I don't want to look at LISP anymore :-) I want static typing a light weight syntax. I want to rid excessive () and ; Commented Aug 12, 2012 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).
    – user7043
    Commented Aug 12, 2012 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. Commented Aug 12, 2012 at 18:13
0

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.

2
  • 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. Commented Aug 12, 2012 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
    Commented Aug 12, 2012 at 20:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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