Learn Understanding Storage: let, const, @state, @param

Getting Started

Welcome to RNBO

Quickstart

RNBO Basics

Key Differences

Why We Made RNBO

Coding Resources

Fundamentals

Audio IO

Messages to rnbo~

Using Parameters

MIDI in RNBO

Messages and Ports

Polyphony and Voice Control

Audio Files in RNBO

Using Buffers

Using the FFT

Export Targets

Export Targets Overview

VST/AudioUnit
Max External Target
Raspberry Pi Target
The Web Export Target
The C++ Source Code Target

Code Export

Working with JavaScript
Working with C++

Codebox

Getting Started with Codebox

Understanding Storage: let, const, @state, @param

Building a Note Controller with Codebox

Special Topics

Sample Accurate Patching
Scala and Custom Tuning

RNBO and Max for Live

RNBO Raspberry Pi OSCQuery Runner

Metadata

Export Description

Raspberry Pi GPIO

Updating the RNBO Package

Understanding Storage in Codebox

Diving a bit deeper into state and scope in codebox. Especially useful for people relatively new to programming.

The codebox and codebox~ objects provide four different ways to declare a variable, with let, const, @state, and @param. If you're relatively new to programming in a text-based language, it might be useful to talk about each of these in turn, to help understand why each one is used.

const

The const keyword is useful for defining some value that won't change during the lifetime of your codebox. For example, you might be doing some pitch calculations relative to A440, in which case you could have a const declaration like:

const REFERENCE_PITCH = 440;

This is handy because now anywhere in your code that you want to refer to this value, you can use the name REFERENCE_PITCH rather than the literal value 440. Later, if you decide you want to use a different reference pitch, you can just change this value in one place. Variables declared with const are hoisted, meaning you can use them before they are declared.

const-hoisting.png

They're also block-scoped, which means that if you declare a const inside of a function or a block, the new definition will override the definition from the containing scope.

block-scope.png

let

The let keyword defines a mutable variable, which means you can change the value of the variable after assigning it. Often you'll want to use let for a working variable, where in the context of executing a function it's useful to hold on to some computed value.

function calculateShapeProperties(width, height) {
    let perimeter = 2 * (width + height);
    let area = width * height;
    return [ perimeter, area ];
}

Very often, you'll also see let used to declare a loop variable, especially when working with for loops.

let outputCount = in1;
for (let i = 0; i < outputCount; i++) {
    out1 = 1;
}

There are two important things to keep in mind with let. First is that since let is for working variables, these value's aren't hoisted like const variables are. This will throw an error, since the variable MY_CONST isn't defined inside the function call.

unhoisted-let.png

The other important thing to keep in mind with let is that it's only for temporary, working variables. You couldn't use let to implement a counter, for example, because the value will be reset with every call to the main body of codebox. You can think of the main body of codebox, outside of any user-defined functions, as being one big function. This function gets called whenever codebox receives a number or list at its first inlet, and once per audio sample block for codebox~. Any let variables that you use in the top level of your codebox object are local to that function. In other words, this will always print 1, no matter how many times you bang it.

bad-counter.png

For state that persists between calls to codebox, you should use the @state decorator.

@state

Use the @state decorator when you want to have a variable that stores values across repeated calls to codebox or codebox~. This is exactly the kind of variable that you would use to implement a counter.

good-counter.png

Unlike let and const, it really only makes sense to use @state at the top level of a codebox, since anything put into a @state variable will be available anywhere in the codebox object. Using @state in a user-defined function will throw an error.

@param

Last but not least, there's @param. This decorator is basically the same as @state, except it has some extra structure. First, you can set the value of @param using a set object.

param-testing.png

Next, a variable declared with @param can have a minimum and a maximum.

param-minmax.png

This can be really useful to declare a @state like variable that you can reset whenever you want.