Why doesn't compiler automatically brace expr? - tcl

I was reading through Donal Fellows' excellent explanation on why you should brace your expr.
It makes me wonder why doesn't the tcl compiler automatically brace {} the expr? What are conditions under which this automatic bracing will fail?

Some random thoughts on this...
One of the strengths of the language is that evaluation is governed by a small number of rules which are applied uniformly. To have the arguments to expr automatically braced would mean that there would have to be an exception in the rules for this command.
It would also mean that the interpreter would have to be rewritten, since it evaluates the arguments before it determines which command it is dealing with. The expr command could be renamed or aliased, making it harder for the interpreter to figure out when to autobrace.
It would mean that if someone wanted double evaluation of the arguments, or wanted to construct the argument in a way that does not directly match the expression tokens, they would have to work around the automatic bracing.
It would mean possible incompatibilities with a lot of old code.
To have the interpreter as a "back seat driver" isn't really the Tcl Way.

It makes me wonder why doesn't the tcl compiler automatically brace {} the expr?
It actually did so during some of the alphas for 8.0. It was removed because the wider community absolutely hated it. The core Tcl language — the 12 rules on the Tcl(n) manual page — is kept extremely small and simple, and it's applied uniformly to everything.
No special cases. That is what most Tcl programmers want.
If I remember right, the auto-bracing was particularly considered for if and while. With if, it was because omitting the braces for a test of the result of a command was a particularly common practice with Tcl 7 because it was faster (the expression engine was rather embarrassingly slow). With while, it was because omitting the braces was a common user bug.
What are conditions under which this automatic bracing will fail?
Well, it would be noticeable in something like this:
set a 1
set b 2
set op +
set c [expr $a$op$b]
Right now, that sets c to 3. With auto-bracing, it would be a syntax error (since the expression grammar doesn't have anything it can do with three variables in a row). A work-around was proposed:
set c [eval expr $a$op$b]
But frankly, getting everyone to brace their expressions except when they really wanted double-substitution (and runtime expression compilation) was considered to be better.
Double-substitution is almost always an indication of a security bug, and it's always an indication of a performance problem; there's virtually always a better (faster, safer) way to do it. Brace your expressions. It's safer and faster and really easy to do: what's not to like?

Related

Having Multiple Commands for Calling a Specific Programming Language: To Provide a Delimiter-less Option or Not?

After re-reading the off/on topic lists, I'm still not certain if this question is best posted to this site, so apologies in advance, if it is not.
Overview:
I am working on a project that mixes several programming languages and we are trying to determine important considerations for the command used to call one in particular.
For definiteness, I will list the specific languages; however, I think the principles ought to be general, so familiarity with these specific languages is not really essential.
Specific Context
Specifically, we are using: Maxima, KaTeX, Markdown and HTML). While building the prototype, we have used the following (I believe, standard) conventions:
KaTeX delimited by $ $ or $$ $$;
HTML delimited by < > </ > pairs;
Markdown works anywhere in the body, except within KaTeX or Maxima environments;
The only non-standard convention we used during this design phase was to call on Maxima using \comp{<Maxima commands>}. This command works within all the other environments (which is desired).
Now that we are ready to start using the platform, it has become apparent that this temporary command for calling Maxima is cumbersome for our users. The vast majority of use cases involve simply calling a single variable or function, e.g.
As such, we have $\eval{function-name()}(\eval{variable-name})$
as opposed to actually using Maxima for computation, e.g.
Here, it is clear that $\eval{a} + \eval{b} = \eval{a+b}$
(where \eval{a+b} would return the actual sum, as calculated by Maxima).
As such, our users would prefer a delimiter-less command option for invoking a single variable or function, e.g. \#<variable-name-in-Maxima> and \#<function-name>(<argument>) (where # is some reserved character not used in the other languages), while also having a delimited alternative for the (much less frequent) cases where they actually want to use Maxima for computation; perhaps something like \#{a+b}.
However, we have a general sense that this is not a best practice, even though we can't foresee any specific issue.
"Research" / Comparisons:
Indeed, there is precedence for delimit-less expressions for single arguments like x^2 (on any calculator) or Knuth's a \over b in TeX (which persists in LaTeX with \frac12 being parsed as \frac{1}{2}.
IIRC Knuth's point was that this delimit-less notation was more semantic (and so, in his view, preferable), and because delimiters can be added, ambiguity can be avoided, whenever the need arises: e.g. x^{22}, {a+b}\over{c+d} and \frac{12}{3}.
The Question, Proper:
Can anyone point to or explain actual shortcomings / risks associated with a dual solution like:
\#<var>, \#<function>(<arg>) and,
\#[<extended expression>],
(where # is a reserved (& escapable) character), for calling one language amongst others, as opposed to only using a delimited command?
Any alternative suggestions for how to achieve the ease-of-use and more semantic code enabled by the above solution, while keeping the code unambiguous would be very much welcome and appreciated.

create_mutable/2 in SICStus Prolog

The SICStus Prolog manual page on mutable terms states that:
[...] the effect of unifying two mutables is undefined.
Then, why does create_mutable(data,x) fail?
Shouldn't that rather raise an uninstantiation_error?
I cannot think of a situation when above case is not an unintentional programming error (X vs x)... please help!
The short answer to "Why does create_mutable/2 not throw an exception when output unification fails?" is just: Because this was how it was done when the feature was added to SICStus Prolog, and no one has made a strong case for changing this.
One important "difference between the stream created by open/4 and the mutable term created by create_mutable/2" is that open/4 has side-effects that are not undone if the output-unification of the call to open/4 fails.
In this sense, create_mutable/2 is somewhat more like is/2 which also just quietly fails if the output argument is some non-numeric non-variable term, e.g. in x is 3+4. This seems to be the common, and traditional, way of handling output arguments in Prolog.
I agree that a non-variable as second argument is most likely a programming error. The next version of the SICStus IDE, SPIDER, will warn for this (as it already does for is/2).
None of this, nor the example in the question, seems directly related to the cited documentation "[...] the effect of unifying two mutables [...]".

TCL man page: it is better to place comment section way ahead

I know I am really picky here, but like to throw it out in case I am off in my interpreting the TCL man page, actually, I wish I was wrong here, as you see the below story.
So for every new TCL developer, we recommend reading the famous "11 rules" (now it is 12 rules).
Yesterday I was asked this question: why does the following script fail?
# puts "hello
world!"
Of course it fails, I said, the first line is taken as comment, that leaves world!" as a command.
But, the newbie said, the manpage indicates that the script is parsed in certain order:
As #2 Evaluation states, the command is parsed to words first.
As #4 Double quotes states, newline is taken as is in parsing double quotes. This makes hello and world! into one word, with a newline in between.
Comments at #10 does states everything up till the next newline is ignored, but after the above processing, the newline should be the 2nd newline, the one after world!.
I see he had a point.
It makes more sense to move the comment section way ahead in the man page, maybe at the second section. With this order change, it indicates that comment recognition is preceding the word-tokenizing process.
How do you think?
Again, I have no intention to ask for change of the manpage, just want to make sure if I miss anything in interpreting the bible.
[UPDATE]
To the people suggesting to close this question as not-a-technical question, it is the same as if my colleague came here asking why that script fails even though his understanding of TCL man page indicates it is a good script.
Again, I am not asking to change the man page.
Let me re-phrase my question - when you are asked this same question, what flaw do you see in his reasoning?
[UPDATE2]
Thanks Donal. I think this is what I learnt, TCL parser goes one char by another, there is no look-ahead.
This is another example:
puts [#haha]
Such script fails at tclsh for the same reason, TCL parser does not break down the script first and only parses the string embedded inside the matching brackets, instead it recognizes "#" as the start of comment and ignores everything after it.
The rules in the Tcl(n) manual page describe pretty precisely the parser that Tcl uses. Requests to change it substantively are usually denied as they tend to have far-reaching consequences and interact with each other trickily. Verifying that a reordering of the rules is not substantive is a non-trivial task, as they correspond to quite a bit of code (our parser and a chunk of our bytecode compiler).
Adding non-normative sections (e.g., EXAMPLES) is easier.
Update based on your updated question
The problem with the reasoning is that the rules are a whole, not really a layered set of parts. They do interact with each other. (The one that usually trips people up is the interaction between the brace rule and the comment rule when inside a braced string such as a procedure body.) Comments really are true comments, and extend up to the end of the line (allowing for backslash-newline sequences) but not beyond, but they only start at places where commands start, not at other places with a # character, and that's the genuinely tricky bit.
Unfortunately, the way that the Tcl parser works is a bit different to the way that programmers think, but most of the time it's pretty good at pretending to work in a “reasonable fashion”. The tricky edge cases don't actually come up too often other than when dealing with the brace-comment interaction mentioned above. The other cases which I hit tend to be either with a switch (resolvable by just putting the comment in the arm) or with long literal lists of things where I want to comment some sections of the list; in that latter case, I actually post-process the string before using it as a list.
set exampleList {
a b c
d e f
# Not really a comment but I want to use it like one!
g h i
j k l
}
# Convert “comment” lines to empty lines
regsub -all -line "^\\s*#.*$" $exampleList "" exampleList
The general advantage of Tcl's rules is that it is actually pretty easy to embed other languages within Tcl, precisely because Tcl only treats # (and other character) as special in well-defined contexts. As long as you can have the embedded language be one that uses balanced braces — and that's almost all of them in practice — then embedding it is utterly trivial. The other cases have to use backslashes and/or double quotes and are pretty ugly, but are also a minuscule fraction of all the embedding cases.
Your colleague's problem is that he's looking at the whole script in one go, whereas the Tcl parser handles one character at a time and doesn't do meaningful amounts of lookahead. It's just some dumb code.

Is there a programming language with no controls structures or operators?

Like Smalltalk or Lisp?
EDIT
Where control structures are like:
Java Python
if( condition ) { if cond:
doSomething doSomething
}
Or
Java Python
while( true ) { while True:
print("Hello"); print "Hello"
}
And operators
Java, Python
1 + 2 // + operator
2 * 5 // * op
In Smalltalk ( if I'm correct ) that would be:
condition ifTrue:[
doSomething
]
True whileTrue:[
"Hello" print
]
1 + 2 // + is a method of 1 and the parameter is 2 like 1.add(2)
2 * 5 // same thing
how come you've never heard of lisp before?
You mean without special syntax for achieving the same?
Lots of languages have control structures and operators that are "really" some form of message passing or functional call system that can be redefined. Most "pure" object languages and pure functional languages fit the bill. But they are all still going to have your "+" and some form of code block--including SmallTalk!--so your question is a little misleading.
Assembly
Befunge
Prolog*
*I cannot be held accountable for any frustration and/or headaches caused by trying to get your head around this technology, nor am I liable for any damages caused by you due to aforementioned conditions including, but not limited to, broken keyboard, punched-in screen and/or head-shaped dents in your desk.
Pure lambda calculus? Here's the grammar for the entire language:
e ::= x | e1 e2 | \x . e
All you have are variables, function application, and function creation. It's equivalent in power to a Turing machine. There are well-known codings (typically "Church encodings") for such constructs as
If-then-else
while-do
recursion
and such datatypes as
Booleans
integers
records
lists, trees, and other recursive types
Coding in lambda calculus can be a lot of fun—our students will do it in the undergraduate languages course next spring.
Forth may qualify, depending on exactly what you mean by "no control structures or operators". Forth may appear to have them, but really they are all just symbols, and the "control structures" and "operators" can be defined (or redefined) by the programmer.
What about Logo or more specifically, Turtle Graphics? I'm sure we all remember that, PEN UP, PEN DOWN, FORWARD 10, etc.
The SMITH programming language:
http://esolangs.org/wiki/SMITH
http://catseye.tc/projects/smith/
It has no jumps and is Turing complete. I've also made a Haskell interpreter for this bad boy a few years back.
I'll be first to mention brain**** then.
In Tcl, there's no control structures; there's just commands and they can all be redefined. Every last one. There's also no operators. Well, except for in expressions, but that's really just an imported foreign syntax that isn't part of the language itself. (We can also import full C or Fortran or just about anything else.)
How about FRACTRAN?
FRACTRAN is a Turing-complete esoteric programming language invented by the mathematician John Conway. A FRACTRAN program is an ordered list of positive fractions together with an initial positive integer input n. The program is run by updating the integer (n) as follows:
for the first fraction f in the list for which nf is an integer, replace n by nf
repeat this rule until no fraction in the list produces an integer when multiplied by n, then halt.
Of course there is an implicit control structure in rule 2.
D (used in DTrace)?
APT - (Automatic Programmed Tool) used extensively for programming NC machine tools.
The language also has no IO capabilities.
XSLT (or XSL, some say) has control structures like if and for, but you should generally avoid them and deal with everything by writing rules with the correct level of specificity. So the control structures are there, but are implied by the default thing the translation engine does: apply potentially-recursive rules.
For and if (and some others) do exist, but in many many situations you can and should work around them.
How about Whenever?
Programs consist of "to-do list" - a series of statements which are executed in random order. Each statement can contain a prerequisite, which if not fulfilled causes the statement to be deferred until some (random) later time.
I'm not entirely clear on the concept, but I think PostScript meets the criteria, although it calls all of its functions operators (the way LISP calls all of its operators functions).
Makefile syntax doesn't seem to have any operators or control structures. I'd say it's a programming language but it isn't Turing Complete (without extensions to the POSIX standard anyway)
So... you're looking for a super-simple language? How about Batch programming? If you have any version of Windows, then you have access to a Batch compiler. It's also more useful than you'd think, since you can carry out basic file functions (copy, rename, make directory, delete file, etc.)
http://www.csulb.edu/~murdock/dosindex.html
Example
Open notepad and make a .Bat file on your Windows box.
Open the .Bat file with notepad
In the first line, type "echo off"
In the second line, type "echo hello world"
In the third line, type "pause"
Save and run the file.
If you're looking for a way to learn some very basic programming, this is a good way to start. (Just be careful with the Delete and Format commands. Don't experiment with those.)

Expression Versus Statement

I'm asking with regards to c#, but I assume its the same in most other languages.
Does anyone have a good definition of expressions and statements and what the differences are?
Expression: Something which evaluates to a value. Example: 1+2/x
Statement: A line of code which does something. Example: GOTO 100
In the earliest general-purpose programming languages, like FORTRAN, the distinction was crystal-clear. In FORTRAN, a statement was one unit of execution, a thing that you did. The only reason it wasn't called a "line" was because sometimes it spanned multiple lines. An expression on its own couldn't do anything... you had to assign it to a variable.
1 + 2 / X
is an error in FORTRAN, because it doesn't do anything. You had to do something with that expression:
X = 1 + 2 / X
FORTRAN didn't have a grammar as we know it today—that idea was invented, along with Backus-Naur Form (BNF), as part of the definition of Algol-60. At that point the semantic distinction ("have a value" versus "do something") was enshrined in syntax: one kind of phrase was an expression, and another was a statement, and the parser could tell them apart.
Designers of later languages blurred the distinction: they allowed syntactic expressions to do things, and they allowed syntactic statements that had values.
The earliest popular language example that still survives is C. The designers of C realized that no harm was done if you were allowed to evaluate an expression and throw away the result. In C, every syntactic expression can be a made into a statement just by tacking a semicolon along the end:
1 + 2 / x;
is a totally legit statement even though absolutely nothing will happen. Similarly, in C, an expression can have side-effects—it can change something.
1 + 2 / callfunc(12);
because callfunc might just do something useful.
Once you allow any expression to be a statement, you might as well allow the assignment operator (=) inside expressions. That's why C lets you do things like
callfunc(x = 2);
This evaluates the expression x = 2 (assigning the value of 2 to x) and then passes that (the 2) to the function callfunc.
This blurring of expressions and statements occurs in all the C-derivatives (C, C++, C#, and Java), which still have some statements (like while) but which allow almost any expression to be used as a statement (in C# only assignment, call, increment, and decrement expressions may be used as statements; see Scott Wisniewski's answer).
Having two "syntactic categories" (which is the technical name for the sort of thing statements and expressions are) can lead to duplication of effort. For example, C has two forms of conditional, the statement form
if (E) S1; else S2;
and the expression form
E ? E1 : E2
And sometimes people want duplication that isn't there: in standard C, for example, only a statement can declare a new local variable—but this ability is useful enough that the
GNU C compiler provides a GNU extension that enables an expression to declare a local variable as well.
Designers of other languages didn't like this kind of duplication, and they saw early on that if expressions can have side effects as well as values, then the syntactic distinction between statements and expressions is not all that useful—so they got rid of it. Haskell, Icon, Lisp, and ML are all languages that don't have syntactic statements—they only have expressions. Even the class structured looping and conditional forms are considered expressions, and they have values—but not very interesting ones.
an expression is anything that yields a value: 2 + 2
a statement is one of the basic "blocks" of program execution.
Note that in C, "=" is actually an operator, which does two things:
returns the value of the right hand subexpression.
copies the value of the right hand subexpression into the variable on the left hand side.
Here's an extract from the ANSI C grammar. You can see that C doesn't have many different kinds of statements... the majority of statements in a program are expression statements, i.e. an expression with a semicolon at the end.
statement
: labeled_statement
| compound_statement
| expression_statement
| selection_statement
| iteration_statement
| jump_statement
;
expression_statement
: ';'
| expression ';'
;
http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
An expression is something that returns a value, whereas a statement does not.
For examples:
1 + 2 * 4 * foo.bar() //Expression
foo.voidFunc(1); //Statement
The Big Deal between the two is that you can chain expressions together, whereas statements cannot be chained.
You can find this on wikipedia, but expressions are evaluated to some value, while statements have no evaluated value.
Thus, expressions can be used in statements, but not the other way around.
Note that some languages (such as Lisp, and I believe Ruby, and many others) do not differentiate statement vs expression... in such languages, everything is an expression and can be chained with other expressions.
For an explanation of important differences in composability (chainability) of expressions vs statements, my favorite reference is John Backus's Turing award paper, Can programming be liberated from the von Neumann style?.
Imperative languages (Fortran, C, Java, ...) emphasize statements for structuring programs, and have expressions as a sort of after-thought. Functional languages emphasize expressions. Purely functional languages have such powerful expressions than statements can be eliminated altogether.
Expressions can be evaluated to get a value, whereas statements don't return a value (they're of type void).
Function call expressions can also be considered statements of course, but unless the execution environment has a special built-in variable to hold the returned value, there is no way to retrieve it.
Statement-oriented languages require all procedures to be a list of statements. Expression-oriented languages, which is probably all functional languages, are lists of expressions, or in tha case of LISP, one long S-expression that represents a list of expressions.
Although both types can be composed, most expressions can be composed arbitrarily as long as the types match up. Each type of statement has its own way of composing other statements, if they can do that all. Foreach and if statements require either a single statment or that all subordinate statements go in a statement block, one after another, unless the substatements allow for thier own substatements.
Statements can also include expressions, where an expression doesn't really include any statements. One exception, though, would be a lambda expression, which represents a function, and so can include anything a function can iclude unless the language only allows for limited lambdas, like Python's single-expression lambdas.
In an expression-based language, all you need is a single expression for a function since all control structures return a value (a lot of them return NIL). There's no need for a return statement since the last-evaluated expression in the function is the return value.
Simply: an expression evaluates to a value, a statement doesn't.
Some things about expression based languages:
Most important: Everything returns an value
There is no difference between curly brackets and braces for delimiting code blocks and expressions, since everything is an expression. This doesn't prevent lexical scoping though: A local variable could be defined for the expression in which its definition is contained and all statements contained within that, for example.
In an expression based language, everything returns a value. This can be a bit strange at first -- What does (FOR i = 1 TO 10 DO (print i)) return?
Some simple examples:
(1) returns 1
(1 + 1) returns 2
(1 == 1) returns TRUE
(1 == 2) returns FALSE
(IF 1 == 1 THEN 10 ELSE 5) returns 10
(IF 1 == 2 THEN 10 ELSE 5) returns 5
A couple more complex examples:
Some things, such as some function calls, don't really have a meaningful value to return (Things that only produce side effects?). Calling OpenADoor(), FlushTheToilet() or TwiddleYourThumbs() will return some sort of mundane value, such as OK, Done, or Success.
When multiple unlinked expressions are evaluated within one larger expression, the value of the last thing evaluated in the large expression becomes the value of the large expression. To take the example of (FOR i = 1 TO 10 DO (print i)), the value of the for loop is "10", it causes the (print i) expression to be evaluated 10 times, each time returning i as a string. The final time through returns 10, our final answer
It often requires a slight change of mindset to get the most out of an expression based language, since the fact that everything is an expression makes it possible to 'inline' a lot of things
As a quick example:
FOR i = 1 to (IF MyString == "Hello, World!" THEN 10 ELSE 5) DO
(
LotsOfCode
)
is a perfectly valid replacement for the non expression-based
IF MyString == "Hello, World!" THEN TempVar = 10 ELSE TempVar = 5
FOR i = 1 TO TempVar DO
(
LotsOfCode
)
In some cases, the layout that expression-based code permits feels much more natural to me
Of course, this can lead to madness. As part of a hobby project in an expression-based scripting language called MaxScript, I managed to come up with this monster line
IF FindSectionStart "rigidifiers" != 0 THEN FOR i = 1 TO (local rigidifier_array = (FOR i = (local NodeStart = FindsectionStart "rigidifiers" + 1) TO (FindSectionEnd(NodeStart) - 1) collect full_array[i])).count DO
(
LotsOfCode
)
I am not really satisfied with any of the answers here. I looked at the grammar for C++ (ISO 2008). However maybe for the sake of didactics and programming the answers might suffice to distinguish the two elements (reality looks more complicated though).
A statement consists of zero or more expressions, but can also be other language concepts. This is the Extended Backus Naur form for the grammar (excerpt for statement):
statement:
labeled-statement
expression-statement <-- can be zero or more expressions
compound-statement
selection-statement
iteration-statement
jump-statement
declaration-statement
try-block
We can see the other concepts that are considered statements in C++.
expression-statements is self-explaining (a statement can consist of zero or more expressions, read the grammar carefully, it's tricky)
case for example is a labeled-statement
selection-statements are if if/else, case
iteration-statements are while, do...while, for (...)
jump-statements are break, continue, return (can return expression), goto
declaration-statement is the set of declarations
try-block is statement representing try/catch blocks
and there might be some more down the grammar
This is an excerpt showing the expressions part:
expression:
assignment-expression
expression "," assignment-expression
assignment-expression:
conditional-expression
logical-or-expression assignment-operator initializer-clause
throw-expression
expressions are or contain often assignments
conditional-expression (sounds misleading) refers to usage of the operators (+, -, *, /, &, |, &&, ||, ...)
throw-expression - uh? the throw clause is an expression too
The de-facto basis of these concepts is:
Expressions: A syntactic category whose instance can be evaluated to a value.
Statement: A syntactic category whose instance may be involved with evaluations of an expression and the resulted value of the evaluation (if any) is not guaranteed available.
Besides to the very initial context for FORTRAN in the early decades, both definitions of expressions and statements in the accepted answer are obviously wrong:
Expressions can be unvaluated operands. Values are never produced from them.
Subexpressions in non-strict evaluations can be definitely unevaluated.
Most C-like languages have the so-called short-circuit evaluation rules to conditionally skip some subexpression evaluations not change the final result in spite of the side effects.
C and some C-like languages have the notion of unevaluated operand which may be even normatively defined in the language specification. Such constructs are used to avoid the evaluations definitely, so the remained context information (e.g. types or alignment requirements) can be statically distinguished without changing the behavior after the program translation.
For example, an expression used as the operand of the sizeof operator is never evaluated.
Statements have nothing to do with line constructs. They can do something more than expressions, depending on the language specifications.
Modern Fortran, as the direct descendant of the old FORTRAN, has concepts of executable statements and nonexecutable statements.
Similarly, C++ defines declarations as the top-level subcategory of a translation unit. A declaration in C++ is a statement. (This is not true in C.) There are also expression-statements like Fortran's executable statements.
To the interest of the comparison with expressions, only the "executable" statements matter. But you can't ignore the fact that statements are already generalized to be constructs forming the translation units in such imperative languages. So, as you can see, the definitions of the category vary a lot. The (probably) only remained common property preserved among these languages is that statements are expected to be interpreted in the lexical order (for most users, left-to-right and top-to-bottom).
(BTW, I want to add [citation needed] to that answer concerning materials about C because I can't recall whether DMR has such opinions. It seems not, otherwise there should be no reasons to preserve the functionality duplication in the design of C: notably, the comma operator vs. the statements.)
(The following rationale is not the direct response to the original question, but I feel it necessary to clarify something already answered here.)
Nevertheless, it is doubtful that we need a specific category of "statements" in general-purpose programming languages:
Statements are not guaranteed to have more semantic capabilities over expressions in usual designs.
Many languages have already successfully abandon the notion of statements to get clean, neat and consistent overall designs.
In such languages, expressions can do everything old-style statements can do: just drop the unused results when the expressions are evaluated, either by leaving the results explicitly unspecified (e.g. in RnRS Scheme), or having a special value (as a value of a unit type) not producible from normal expression evaluations.
The lexical order rules of evaluation of expressions can be replaced by explicit sequence control operator (e.g. begin in Scheme) or syntactic sugar of monadic structures.
The lexical order rules of other kinds of "statements" can be derived as syntactic extensions (using hygienic macros, for example) to get the similar syntactic functionality. (And it can actually do more.)
On the contrary, statements cannot have such conventional rules, because they don't compose on evaluation: there is just no such common notion of "substatement evaluation". (Even if any, I doubt there can be something much more than copy and paste from existed rules of evaluation of expressions.)
Typically, languages preserving statements will also have expressions to express computations, and there is a top-level subcategory of the statements preserved to expression evaluations for that subcategory. For example, C++ has the so-called expression-statement as the subcategory, and uses the discarded-value expression evaluation rules to specify the general cases of full-expression evaluations in such context. Some languages like C# chooses to refine the contexts to simplify the use cases, but it bloats the specification more.
For users of programming languages, the significance of statements may confuse them further.
The separation of rules of expressions and statements in the languages requires more effort to learn a language.
The naive lexical order interpretation hides the more important notion: expression evaluation. (This is probably most problematic over all.)
Even the evaluations of full expressions in statements are constraint with the lexical order, subexpressions are not (necessarily). Users should ultimately learn this besides any rules coupled to the statements. (Consider how to make a newbie get the point that ++i + ++i is meaningless in C.)
Some languages like Java and C# further constraints the order of evaluations of subexpressions to be permissive of ignorance of evaluation rules. It can be even more problematic.
This seems overspecified to users who have already learned the idea of expression evaluation. It also encourages the user community to follow the blurred mental model of the language design.
It bloats the language specification even more.
It is harmful to optimization by missing the expressiveness of nondeterminism on evaluations, before more complicated primitives are introduced.
A few languages like C++ (particularly, C++17) specify more subtle contexts of evaluation rules, as a compromise of the problems above.
It bloats the language specification a lot.
This goes totally against to simplicity to average users...
So why statements? Anyway, the history is already a mess. It seems most language designers do not take their choice carefully.
Worse, it even gives some type system enthusiasts (who are not familiar enough with the PL history) some misconceptions that type systems must have important things to do with the more essential designs of rules on the operational semantics.
Seriously, reasoning depending on types are not that bad in many cases, but particularly not constructive in this special one. Even experts can screw things up.
For example, someone emphasizes the well-typing nature as the central argument against the traditional treatment of undelimited continuations. Although the conclusion is somewhat reasonable and the insights about composed functions are OK (but still far too naive to the essense), this argument is not sound because it totally ignores the "side channel" approach in practice like _Noreturn any_of_returnable_types (in C11) to encode Falsum. And strictly speaking, an abstract machine with unpredictable state is not identical to "a crashed computer".
A statement is a special case of an expression, one with void type. The tendency of languages to treat statements differently often causes problems, and it would be better if they were properly generalized.
For example, in C# we have the very useful Func<T1, T2, T3, TResult> overloaded set of generic delegates. But we also have to have a corresponding Action<T1, T2, T3> set as well, and general purpose higher-order programming constantly has to be duplicated to deal with this unfortunate bifurcation.
Trivial example - a function that checks whether a reference is null before calling onto another function:
TResult IfNotNull<TValue, TResult>(TValue value, Func<TValue, TResult> func)
where TValue : class
{
return (value == null) ? default(TValue) : func(value);
}
Could the compiler deal with the possibility of TResult being void? Yes. All it has to do is require that return is followed by an expression that is of type void. The result of default(void) would be of type void, and the func being passed in would need to be of the form Func<TValue, void> (which would be equivalent to Action<TValue>).
A number of other answers imply that you can't chain statements like you can with expressions, but I'm not sure where this idea comes from. We can think of the ; that appears after statements as a binary infix operator, taking two expressions of type void and combining them into a single expression of type void.
Statements -> Instructions to follow sequentially
Expressions -> Evaluation that returns a value
Statements are basically like steps, or instructions in an algorithm, the result of the execution of a statement is the actualization of the instruction pointer (so-called in assembler)
Expressions do not imply and execution order at first sight, their purpose is to evaluate and return a value. In the imperative programming languages the evaluation of an expression has an order, but it is just because of the imperative model, but it is not their essence.
Examples of Statements:
for
goto
return
if
(all of them imply the advance of the line (statement) of execution to another line)
Example of expressions:
2+2
(it doesn't imply the idea of execution, but of the evaluation)
Statement,
A statement is a procedural building-block from which all C# programs are constructed. A statement can declare a local variable or constant, call a method, create an object, or assign a value to a variable, property, or field.
A series of statements surrounded by curly braces form a block of code. A method body is one example of a code block.
bool IsPositive(int number)
{
if (number > 0)
{
return true;
}
else
{
return false;
}
}
Statements in C# often contain expressions. An expression in C# is a fragment of code containing a literal value, a simple name, or an operator and its operands.
Expression,
An expression is a fragment of code that can be evaluated to a single value, object, method, or namespace. The two simplest types of expressions are literals and simple names. A literal is a constant value that has no name.
int i = 5;
string s = "Hello World";
Both i and s are simple names identifying local variables. When those variables are used in an expression, the value of the variable is retrieved and used for the expression.
I prefer the meaning of statement in the formal logic sense of the word. It is one that changes the state of one or more of the variables in the computation, enabling a true or false statement to be made about their value(s).
I guess there will always be confusion in the computing world and science in general when new terminology or words are introduced, existing words are 'repurposed' or users are ignorant of the existing, established or 'proper' terminology for what they are describing
Here is the summery of one of the simplest answer I found.
originally Answered by Anders Kaseorg
A statement is a complete line of code that performs some action, while an expression is any section of the code that evaluates to a value.
Expressions can be combined “horizontally” into larger expressions using operators, while statements can only be combined “vertically” by writing one after another, or with block constructs.
Every expression can be used as a statement (whose effect is to evaluate the expression and ignore the resulting value), but most statements cannot be used as expressions.
http://www.quora.com/Python-programming-language-1/Whats-the-difference-between-a-statement-and-an-expression-in-Python
Statements are grammatically complete sentences. Expressions are not. For example
x = 5
reads as "x gets 5." This is a complete sentence. The code
(x + 5)/9.0
reads, "x plus 5 all divided by 9.0." This is not a complete sentence. The statement
while k < 10:
print k
k += 1
is a complete sentence. Notice that the loop header is not; "while k < 10," is a subordinating clause.
In a statement-oriented programming language, a code block is defined as a list of statements. In other words, a statement is a piece of syntax that you can put inside a code block without causing a syntax error.
Wikipedia defines the word statement similarly
In computer programming, a statement is a syntactic unit of an imperative programming language that expresses some action to be carried out. A program written in such a language is formed by a sequence of one or more statements
Notice the latter statement. (although "a program" in this case is technically wrong because both C and Java reject a program that consists of nothing of statements.)
Wikipedia defines the word expression as
An expression in a programming language is a syntactic entity that may be evaluated to determine its value
This is, however, false, because in Kotlin, throw new Exception("") is an expression but when evaluated, it simply throws an exception, never returning any value.
In a statically typed programming language, every expression has a type. This definition, however, doesn't work in a dynamically typed programming language.
Personally, I define an expression as a piece of syntax that can be composed with an operator or function calls to yield a bigger expression. This is actually similar to the explanation of expression by Wikipedia:
It is a combination of one or more constants, variables, functions, and operators that the programming language interprets (according to its particular rules of precedence and of association) and computes to produce ("to return", in a stateful environment) another value
But, the problem is in C programming language, given a function executeSomething like this:
void executeSomething(void){
return;
}
Is executeSomething() an expression or is it a statement? According to my definition, it is a statement because as defined in Microsoft's C reference grammar,
You cannot use the (nonexistent) value of an expression that has type void in any way, nor can you convert a void expression (by implicit or explicit conversion) to any type except void
But the same page clearly indicates that such syntax is an expression.
A statement is a block of code that doesn't return anything and which is just a standalone unit of execution. For example-
if(a>=0)
printf("Hello Humen,I'm a statement");
An expression, on the other hand, returns or evaluates a new value. For example -
if(a>=0)
return a+10;//This is an expression because it evalutes an new value;
or
a=10+y;//This is also an expression because it returns a new value.
Expression
A piece of syntax which can be evaluated to some value. In other words, an expression is an accumulation of expression elements like literals, names, attribute access, operators or function calls which all return a value. In contrast to many other languages, not all language constructs are expressions. There are also statements which cannot be used as expressions, such as while. Assignments are also statements, not expressions.
Statement
A statement is part of a suite (a “block” of code). A statement is either an expression or one of several constructs with a keyword, such as if, while or for.
To improve on and validate my prior answer, definitions of programming language terms should be explained from computer science type theory when applicable.
An expression has a type other than the Bottom type, i.e. it has a value. A statement has the Unit or Bottom type.
From this it follows that a statement can only have any effect in a program when it creates a side-effect, because it either can not return a value or it only returns the value of the Unit type which is either nonassignable (in some languages such a C's void) or (such as in Scala) can be stored for a delayed evaluation of the statement.
Obviously a #pragma or a /*comment*/ have no type and thus are differentiated from statements. Thus the only type of statement that would have no side-effects would be a non-operation. Non-operation is only useful as a placeholder for future side-effects. Any other action due to a statement would be a side-effect. Again a compiler hint, e.g. #pragma, is not a statement because it has no type.
Most precisely, a statement must have a "side-effect" (i.e. be imperative) and an expression must have a value type (i.e. not the bottom type).
The type of a statement is the unit type, but due to Halting theorem unit is fiction so lets say the bottom type.
Void is not precisely the bottom type (it isn't the subtype of all possible types). It exists in languages that don't have a completely sound type system. That may sound like a snobbish statement, but completeness such as variance annotations are critical to writing extensible software.
Let's see what Wikipedia has to say on this matter.
https://en.wikipedia.org/wiki/Statement_(computer_science)
In computer programming a statement is the smallest standalone element of an imperative programming language that expresses some action to be carried out.
Many languages (e.g. C) make a distinction between statements and definitions, with a statement only containing executable code and a definition declaring an identifier, while an expression evaluates to a value only.