Why the difference between expression and expression

In batches (in fact, everything that I have ever used) of functional languages, there is no difference between an operator and an expression, and the last value of each block of code is the "return value" of the block. On the other hand, languages ​​that are not usually considered purely functional usually introduce this distinction.

As an example of what I'm saying, the following python code prints None :

 def foo(): 5 + 5 print(foo()) 

while circuit code prints 10

 (define (foo) (+ 5 5)) (display (foo)) 

Obviously, I am not interested in the subjective answers of people who prefer one style to another, but objective reasons.

It seems to me that the difference makes the grammar and implementation of the language more complex (one of the less obvious examples of this is the necessary exceptions in the C ++ standard for void templates and types or the introduction of "shortcut if statements", for example, in c-influence languages) without real benefits - but most likely there is a reason why even new, modern languages ​​still have this difference.

+4
source share
3 answers

The ubiquitous side effects.

If you are in a purely functional language, this is all an expression. Even “statements” that return something like () (perhaps differ in their type, for example, IO () .

However, by default, most programming languages ​​allow effects everywhere or everywhere, so sequencing becomes the key, and thus you bake in a special syntax to organize the statements on the computer, often separated by semicolons.

This does not apply to pure expressions that can be evaluated in any order that preserves the semantics of the expression.

Actions with a side effect are considered such special expressions that they receive special syntax.

+5
source

First, let me say that I think you are asking two, maybe different, different questions: "Why do some expressions differ syntactically from others?" and "Why semantics for sequencing what they are?"

For your first question: the meaning that I get from many of the things I read is that expressions are expressions, but a limited class of expressions that cannot be displayed as subexpressions under any circumstances, for example,

 x = 4 y = (x += 1) 

The python code above generates a syntax error because the statement appears in the place where the (unlimited) expression was expected. I associate claims with side effects, sequencing, and an imperative style. I don’t know if you think the programming style is a subjective answer to your question (the style itself is certainly subjective).

I am very interested to hear how others accept this question too.

In the second question: Semantics is sometimes arbitrarily decided, but the goal is reasonable semantics, and different language developers simply differ in what is the most reasonable (or most expected). I was surprised that if control reaches the end of the function body in Python, it returns None, but this is semantics. Designers should answer similar semantics questions: "What should be the type of while loop?" and "What should the if statement type be if it does not have an else branch?" and "Where should such statements be syntactically resolved (problems may arise if such an if statement is the last statement in a sequence of statements)?"

+4
source

The question is, “why do new languages ​​still have expressions, and not expressions exclusively?”, Right?

The programming language constructs address various problems, for example.

  • simple grammar
  • simple implementation
  • simple semantics

is one of the most theoretical design goals and

  • execution speed of the resulting compiled code
  • compilation speed
  • program expenditure
  • ease of use (e.g. easy to read)

is one of the most practical ...

These design goals do not have clear definitions, for example. a short grammar is not necessarily the one with the cleanest structure, and which one is simpler?

(considering your example)

For ease of use or reading code, a language designer may require that you write "return" before the view (or rather, the expression) that results from the function. This is a return statement. If you can leave a “return”, this is still implied, and it can still be considered as a return statement (this is just not so obvious in the code). If it is considered as an expression, this implies the semantics of substitution, for example, Schema, but probably not Python. From a syntactic point of view, it makes sense to distinguish between expressions and expressions where "return" is required.

Looking at the machine code (which I did not do a lot, so I could be wrong), it seems to me that there are only statements, without expressions.

eg. your example:

 ld r1, 5 ld r2, 5 add r3, r1, r2 ret r3 

(I'm doing it, obviously)

Thus, for people who like to think about how the kernel actually works (von Neumann), or who want to simplify compilation for such a targeted architecture, statements are a way.

There is also a specific expression “evil” (as in non-functional) assignment. This is necessary to express loop contours without recursion. According to Dijkstra, loops have simpler semantics than recursion (see EW Dijkstra, Programming Discipline, 1976). The loop is faster and consumes less memory than recursion. If your language is not optimized for tail recursion (e.g. schemas).

0
source

All Articles