Source Forms

LaiRu runs Lasso code in two modes. Script mode executes a plain .lasso file top-to-bottom. Template mode copies surrounding text through and evaluates only the bracketed expressions. See the Templates page for full template details.

// script mode
local(name) = 'LaiRu'
#name + ' 0.1'

Literals

LaiRu supports the following literal forms:

LiteralTypeExample
Single-quoted stringstring'hello'
Double-quoted stringstring"world"
Backtick raw stringstring`raw \n text`
Integerinteger42, 0x1F
Decimaldecimal3.14
Booleanbooleantrue, false
Nullnullnull
Voidvoidvoid
Not a NumberdecimalNaN
Infinitydecimalinfinity

Integer literals and all integer arithmetic use arbitrary precision — there is no overflow for integers.

Comments

// single-line comment

/* multi-line
   comment */

Variables

Local variables are scoped to the enclosing method or block and are referenced with #name. Thread variables persist for the duration of the request (or script run) and are referenced with $name.

local(x) = 42
local(greeting) = 'Hello'
#greeting + ', world: ' + #x

var(counter = 1)
$counter = $counter + 1
$counter

Names are compared case-insensitively: #Name and #name refer to the same variable.

Operators

OperatorDescription
+ - * / %Arithmetic. + also concatenates strings.
== != < <= > >=Comparison, returning boolean.
&& || ! / and or notLogical operators.
>> / !>>Contains / does not contain.
..Inclusive integer range: 1 .. 5.
test ? a | bTernary conditional.
// arithmetic
2 + 3 * 4       // 14 (standard precedence)
10 % 3          // 1

// string concatenation
'Hello' + ', ' + 'world'

// comparison
5 > 3 ? 'bigger' | 'not bigger'

// range
1 .. 5          // produces the series 1, 2, 3, 4, 5

Methods

Unbound (free) methods are defined with define:

define twice(n) => #n * 2
twice(21)           // 42

define greet(name = 'LaiRu') => 'Hello, ' + #name
greet()             // 'Hello, LaiRu'
greet('Ada')        // 'Hello, Ada'

Block bodies allow multiple statements and return:

define describe(name, score = 0) => {
  return #name + ': ' + #score
}
describe('Ada', 99)

Overloading and type constraints

Multiple definitions of the same method name can coexist when they differ in arity or parameter type constraints. LaiRu selects the best match using a shared dispatch ranking: exact type beats default, fixed arity beats rest catchalls, and ambiguous same-rank candidates produce a runtime error.

define describe(value::integer) => 'int: ' + #value
define describe(value::string)  => 'str: ' + #value

describe(42)        // 'int: 42'
describe('hello')   // 'str: hello'

// keyword parameters
define find_in(input::string, -find::string, -ignoreCase::boolean = false) => {
  // implementation
}

// rest parameter
define sum_all(...values::integer)::integer => {
  with n in #values sum #n
}

Return constraints

A return type after the parameter list is checked at runtime after the body executes:

define double(n::integer)::integer => #n * 2

Control Flow

Conditionals

if(#score > 90) => {
  'excellent'
} else if(#score > 70) => {
  'good'
} else => {
  'needs work'
}

Iteration

// loop N times
loop(3) => { loop_count + ' ' }

// while loop
local(i) = 0
while({ #i < 5 }) => {
  $i = $i + 1
}

// forEach over an array
array('a', 'b', 'c')->forEach => {
  #1 + ' '
}

// iterate helper
iterate(array(10, 20, 30)) => {
  #1
}
The full Lasso control-flow library is not yet implemented. The above forms cover the most common iteration patterns. Native query expressions (see Queries) are the idiomatic way to process collections.

Member Calls

Methods on values are called with the -> operator:

'LaiRu'->uppercase        // 'LAIRU'
'  hello  '->trim         // 'hello'
array(3, 1, 2)->sort      // sorted array
42->asString              // '42'
'hello'->isA('string')    // true

See Built-ins for the full list of available member methods.