The let and defer keywords declare an expression variable. An expression variable is defined by an expression, which is assigned once (either immedietaly or deferred), making it read-only, but the variable's value dynamically changes according to this expression. It essentialy works like a zero-argument function.
The basic syntax is:
let <type> <name> = <expression>;
let float circleRadius = 0.5*circleDiameter;
Alternatively, an expression variable may be forward-declared by the defer keyword, and its value expression specified at a later point. In that case, the syntax of both declarations is respectively:
defer <type> <name>; let <name> = <expression>;
This may be useful in certain scenarios, such as for backwards propagation of image dimensions. Consider the following example:
defer ivec2 outputDimensions; image IntermediateImage = glsl(processInput, outputDimensions) : hidden(true); image OutputImage = glsl(finalize<IntermediateImage>, 640, 480) : resizable(true); let outputDimensions = sizeof(OutputImage);
It may be desirable to allow the intermediate image to change dimensions as the output image's dimensions change, but without this mechanism, it wouldn't be possible to achieve, since objects may only be referenced after their declarations.