loading...

Instructions vs Expressions

s0kil profile image Daniel Sokil ・1 min read
  • Instructions (statements) are executed
  • Expressions (values) are evaluated

Here is one of my favorite ways to illustrate it:

In JavaScript if we nest console.log

console.log(console.log(console.log("AnAmazingValue")))
Enter fullscreen mode Exit fullscreen mode

we get

AnAmazingValue
undefined
undefined
Enter fullscreen mode Exit fullscreen mode

And in Scala

println(println(println("AnAmazingValue")))
Enter fullscreen mode Exit fullscreen mode

returns

AnAmazingValue
()
()
Enter fullscreen mode Exit fullscreen mode

To conclude, JavaScript instruction console.log does not return a value (hence the undefined), while Scalas println expression returns the value () of type Unit.

Discussion

pic
Editor guide
Collapse
curtisfenner profile image
Curtis Fenner

This basic classification works for simple programs, but I think it misses the real divide by a bit. It would be difficult to classify a snippet like

let total = 0;
function accumulate(a, b) {
    return total += a + b;
}

console.log(accumulate(1, 2));
console.log(accumulate(1, 2));
// is `accumulate(1, 2)` "evaluated" or "executed"?
Enter fullscreen mode Exit fullscreen mode

Looking back at the clearer cases, there are also some problems:
Because you can write console.log(console.log(5)) at all, we must know that console.log(5) is in fact an expression, since function arguments are expressions (it simply evaluates to undefined). In fact, when you write something; what you're writing is called an "expression statement" which tells you to "execute" that expression.

You can observe that it is in fact "executing" the expression because expressions that you would otherwise want to call merely 'evaluated' take time to execute, they can throw errors, or they can hang and never let anything else execute.

You can make a much more fine-grained classification of expressions by identifying their side effects. A side effect is something that evaluation of an expression results in other than the value computed.

console.log has a side effect of printing something to the console.

accumulate from above has a side effect of increasing the total variable.

+ on its own is side-effect-free, sometimes called a "pure" expression.

This analysis is even more important in the context of languages with more expressive classification of values like Haskell, in which case you can precisely annotate most of the side-effects that each expression has. (Though, not whether or not they hang or throw errors)

Collapse
stereobooster profile image
stereobooster

Unit is a subtype of scala.AnyVal. There is only one value of type Unit, (), and it is not represented by any object in the underlying runtime system. A method with return type Unit is analogous to a Java method which is declared void.


void is a Java keyword.

Used at method declaration and definition to specify that the method does not return any type, the method returns void. It is not a type and there is no void references/pointers as in C/C++.


A variable that has not been assigned a value is of type undefined. A method or statement also returns undefined if the variable that is being evaluated does not have an assigned value. A function returns undefined if a value was not returned.

undefined (in JS) ~ void (in Java) ~ Unit (Scala)

Maybe you meant expressions vs statements

Statement:

if (a > b) { return 1 } else { return 2 }
Enter fullscreen mode Exit fullscreen mode

Expression:

a > b ? 1 : 2
Enter fullscreen mode Exit fullscreen mode