Catspeak Reference


Statements

Unlike GameMaker Language (GML), Catspeak only has two kinds of statement: Let Statements, and Expression Statements. This is because Catspeak is an expression-oriented language, where almost every statement and/or expression evaluates to a value.

As a result, things like "if" statements become If Expressions:

Catspeak (.meow)
Copylet result = if a > b { "a is bigger" } else { "b is bigger" }

Other notable languages in this family are Ruby and Rust.

§ Let Statementstop ^

The let statement creates a new local variable in the current block scope. It can optionally be followed by an initialiser expression. If no initialiser expression is used, then the variable will be initialised to undefined:

Catspeak (.meow)
Copylet a = 1 + 3 -- initialised to the value 3 let b -- initialised to undefined

Unlike GML, local variables in Catspeak are only visible from within the scope they are defined in. This means that the following code is incorrect in Catspeak:

Catspeak (.meow)
Copyif condition { let result = 1 -- local to the "true" branch of the if expression } else { let result = 2 -- local to the "false" branch of the if expression } -- local variable 'result' does not exist here -- instead, 'result' gets interpreted as a global variable here return result

You must always define the local variables before using them in Catspeak:

Catspeak (.meow)
Copylet result if condition { result = 1 -- assign to the previously defined 'result' variable } else { result = 2 } -- now 'result' is in scope return result

§ Dynamically Scoped Local Variablestop ^

If an variable is declared without using let, then it is interpreted as a local variable with dynamic scope. Unlike variables defined using let, dynamically scoped variables can be read from and written to outside of the scope they were defined in. This makes them useful tools when working with recursive functions:

Catspeak (.meow)
Copyis_odd = fun (n) { if n < 1 { return false } else { return !is_odd(n - 1) } }

These resemble global variables found in GML, but to avoid confusion a different name is being used. These are not GML global variables, all variables in Catspeak (whether or not they are defined using let) are constrained to the source file they are defined in.

If there exists a dynamic variable and a scoped variable with the same name, then the scoped variable takes priority:

Catspeak (.meow)
Copyplayer = "Serket" show_message(player) -- shows "Serket" if condition { let player = "Vantas" show_message(player) -- shows "Vantas" } show_message(player) -- also shows "Serket", since the variable inside -- of the if expression has gone out of scope

§ Expression Statementstop ^

Because Catspeak is an expression-oriented language, everything that is not a variable declaration is an expression and can return a value. This also includes if conditionals and while loops:

Catspeak (.meow)
Copylet result = while true { let n = irandom_range(0, 100) if n > 75 { break n } } let use_result = choose(true, false) -- coin flip show_message(if use_result { result } else { 0 })

More often than not, an expression statement will evaluate its expression and ignore the result. There are exceptions to this rule, where the result of a block will be the value of its final expression statement. For example, the value returned from the following Function Expression will be "10":

Catspeak (.meow)
Copylet get_value = fun () { let a = 2; let b = 5; a * b -- this is the last expression in the function body -- so its returned as the result of the function when called }

Since a * b evaluates to 10, and it is the last statement in the body of the function.