Variable names are never confused for keywords in the langur scripting language, as they are qualified with a dot or underscore, such as .var or _var. Technically, _var is a shortcut for ._var. System variable names begin with an underscore and user-defined variable names do not.

Variable names may use ASCII letters, numbers, and underscores, and may start with a number. A single underscore is the no-op token, not a variable.

system variables

system variable description
_rev the langur revision number string, such as 1.7.3
_env a hash of environment variables with keys and values as strings
_args an array of strings of the arguments following the script name
_script the name and path of the script being executed

declarations and assignments

Immutable declarations use a val token and mutable declarations use a var token.

You should use immutable declarations for most things.

An immutable declaration must be combined with an assignment.

Mutable declaration without assignment will set the variable implicitly (to something such as null).

val .x = 123 immutable declaration and assignment
var .y = 123 mutable declaration and assignment
var .z mutable declaration without explicit assignment
.y = 789 assignment to mutable variable (previously declared)

See the operators page about combination operators.

multi-variable assignment/declaration

In statement context, you can assign multiple items from the right to the same number of items on the left. This can be used with val and var declarations.

The result of a multi-variable assignment is the last value on the right.

# swap values .x, .y = .y, .x

0.10 updated the parser to not use parentheses for multiple variable names. Prior to 0.10, you would use something like the following.

# swap values (.x, .y) = (.y, .x)

decoupling assignment/declaration

If you assign a single item from the right to multiple items on the left, it is assumed to be a decoupling assignment. This only works if the value on the right can be indexed numerically.

Use the no-op (underscore) to skip an index.

A decoupling assignment returns a Boolean indicating whether the values could be assigned or not (whether there were enough or not). It will succeed if the number of items on the left is the same or less than the number of items from the right.

# using the fact that submatch() returns an empty array for no match... if val .alias, .name = submatch($re/^(\.idregex;)\\s*;\\s*(\.idregex;)/, .row) { # success (2 or more values in array returned from submatch function) # use .alias and .name here ... }

Prior to 0.10, would use something like the following instead (parentheses around multiple variable names).

if val (.alias, .name) = submatch(...) { ... }

If decoupling assignment fails (without throwing an exception) on a declaration, the declared variables will be null.

expansion on decoupling assignment

As of 0.12.2, you can use expansion on the last variable on decoupling assignment. Upon success, the last variable will be set to an array of 0 or more elements.

if val .x, .y, ... .z = .somearray { /* do something */ } # .z takes all remaining values

variable scope

Langur 0.9 limits declaration scope to statements and to the tests of if expressions. The following may create variable scope.

  1. script level
  2. functions
  3. generic curly braces { } (scope blocks)
  4. loops
  5. catch blocks (but not the implicit try section)
  6. the optional else section of a catch block
  7. if expressions
  8. given expressions

Not all use of curly braces indicates a new scope.

Function scope does not allow reassignment of variables from their enclosing scope, so that functions are pure in this way. Other scopes may reassign variables that are mutable.

In some earlier versions (prior to 0.9), the following may also create variable scope.

  1. function calls
  2. arrays
  3. hashes
  4. index expressions
  5. string interpolation