Otter Documentation

Strings & Values

OtterScript Banner

Values -- i.e. the desired states, settings, and values of the things that need to be configured on servers -- are a first-class concept in OtterScript, and are represented through a literal expression. There are three types of literal expressions:

  • Map expression - represents a map, such as %( name: value, name2: value2 )
  • Vector expression - represents a list/vector, such as @( value1, value2, value3 )
  • Scalar expression - all other literal expressions

The formal grammar describes exactly how map and vector expressions should be formated and where they may be used.

Automatic Variable Expansion

All statements persist their contained data and values as a string, and it's only during execution of the statement that the expression is evaluated. It's during this evaluation that variables values are expanded.

When a literal expression is evaluated, any contained scalar variable expressions (e.g. $SomeVariable) are replaced with the corresponding value, using the following method:

  • If the expression represents a function (e.g. $SomeFunc()), then a variable function with that name is invoked using the specified parameters
  • Otherwise, a value is located in this priority
    1. Runtime variable
    2. Configuration variable
    3. Variable function
    4. Raft variable

When a function is invoked, the parameters are evaluated prior to execution; for example, $PathCombine($a,$b) will first resolve $a and $b before invoking PathCombine

Indexed List or Map Expansion

Because map and list expressions represent multiple values, they cannot be automatically expanded into a single value (i.e. a string). You can, however, use an indexing expression to identify a single value to expand within a map or a list. This works a lot like arrays or property indexers in other programming languages.

OtterScript supports both bracket-based indexing and dot-based indexing, and lists indexes are 0-based integers. For example:

  • @MyList[3] - will expand to the forth item in the list, or an error if @MyList doesn't have at least four items
  • @(1,2,3)[zero] - will result in a runtime error, because zero is not an non-negative integer
  • @(MyList)[$i] - will expand to whatever $i expands to, or a runtime error if $i is not a positive integer
  • %MyMap[hdars] - will expand to the value with a key of hdars, or result in a runtime error if that value doesn't exist or is not a scalar value
  • %Config.Sys.Drive - will expand to the Drive-keyed value in the Sys-keyed map within the Config map

Escaping Expansion

The grave apostrophe (`) serves as an escape character. The following can be escaped:

  • Variable Type Indicators -`$, `@, `%
  • Quotes - ``, `", `'
  • Delimiters - depending on context, one of `(, `,, `;, `:, or `{
  • Whitespace - `n, `t, `r

If any other character follows the grave apostrophe, then it will not be considered an escape character. This will also raise a warning during compilation.

Additional Expansion

The $Eval(«arg») variable function will perform an additional variable expansion using the method described above for «arg».

Avoid Expansion Altogether

Sometimes, it's desirable to avoid expansion all together, without needing to escape using the grave apostrophe. Some languages perform this with an additional decorator on a string literal, such as the @ before a string in C#.

We're considering adding this using a /literal decorator at the end of a quoted or swim string. For example, "Not $escaped"/literal.

If you have any interest in this, please let us know so we can prioritize it.

String literal syntaxes

To help contain values without worrying about escaping, OtterScript offers several syntaxes for string literals:

Implicit any characters except newlines and the expected delimiter (which can be a comma, right-parenthesis, right-brance, or semi-colon, depending on context); surrounding whitespace is always trimmed
Quoted any characters surrounded by a pair of single-or double-quotes; these cannot contain a newline character, and escaping sequences (such as \n\t) are not used
Swim any characters surrounded by two identical fish sentinels; these are a pair of greater-than characters containing zero to five non-greater-than characters (>>, >--=>, >==8>); although not required, it’s advised to make your fish sentinels look like fish as much as possible, as otters love fish

Following are some example strings:

this is just an implicit string
"Quote string, with double quotes."
'A "quoted" string with single quotes.'
An "implicit" string because it doesn't start with a quote
>> this is a swim string
that can span multiple
lines, and contain "any' thing, except the 
closing fish >>
>==8>
this is a more fish-looking sentinel; note that it
can this can contain >>, >--=>, or even a shark (>==|:>) 
because the surrounding fish have ==8 inside
>==8>

Notes and Best Practices

Note that variable expansion gives the appearance of assigning variables to operation paramters; this is not the case. It simply is a literal expression that will utilize variable expansion at runtime. As such, there is no need for things like string concatenation: just put the variables next to each other in the desired manner (e.g. http://${host}/${path}), and they will be evaluated at runtime as expected.

In general, describing your configuration with implicit strings will makes them easier to read and follow. We recommend using implicit strings when possible, quoted strings when you require a delimiter or non-trimmed whitespace, and fish strings when creating files or doing script-embedded operations.