Expressions, Statements, and Blocks

The Shim language is built up from a few basic building parts, namely:

  • Expressions
  • Statements
  • Blocks

Expressions

Expressions are the most basic piece. An expression is a chunk of code that can be evaluated to get a value. A basic example is 13 + 4 or a more detailed example is (x*x + y*y).sqrt() where you have multiplication, addition, and method calling.

let x = 3
let y = 4
let hyp = (x*x + y*y).sqrt()
print(hyp)
Press the play button to execute

Statements

For the most part, statements are a chunk of code that doesn’t evaluate to a value. Typically, if a line starts with a keyword it’s a statement. The let x = 3 you can see in the above code block is an example of this. Additionally, you have fn declarations, struct declarations, while/for loops, and assignments.

fn greet(name) {
    print("Hi \(name)")
}
let names = ["Kate", "Stephen", "Ben"]
for name in names {
    greet(name)
}
Press the play button to execute

Statements can’t evaluate to a value. As an example, this code block should error out:

let test = (let a = 13)
Press the play button to execute

Some keywords can act as both an expression or a statement, however.

// This `if` is a statement
if true {
    print("is true")
}

// This `if` is part of an expression
let a = if true { "is true" }
Press the play button to execute

Blocks

You’ve already seen them, but the code contained in curly braces {} is called a block. A block defines a new scope where variables, functions, and structs defined in the block can’t be referenced outside of the block.

{
    let a = 12
}
print(a)  // <--- This fails since `a` doesn't exist outside of the block
Press the play button to execute

Knowing that the variable a can only be referenced inside the block is great for keeping code understandable. It means that when you’re looking at code outside of the block you don’t need to keep a mental record of that variable in your head. Outside of the block, you can forget that it even existed.

Evaluating Blocks

Like the if keyword that can be a statement or an expression, blocks can also be used as expressions. The value of a block is the last expression in the block.

Here’s an example:

let hyp = {
    let x = 3
    let y = 4
    (x*x + y*y).sqrt()
}
print(hyp)
Press the play button to execute

In this example, the last line (x*x + y*y).sqrt() is what the block evaluates to and what gets assigned to hyp. This is true for functions, where the last expression in the function body is the return value of the function, and it’s true for if/else expressions where the last expression of the branch is the value evaluated for the expression.

let length = 12
let description = if length > 10 {
    "long"
} else {
    "short"
}
print("It's \(description)")
Press the play button to execute