Overview

Lasso 9 has a built-in query-expression syntax that reads like structured English. LaiRu 0.1 implements a first-pass slice covering the most common clauses and actions. Simple single-source select queries with only where / let / skip / take stream lazily through the source; ordering, grouping, multiple sources, and aggregate actions use a materialized row path.

Basic select

with n in array(1, 2, 3, 4, 5)
  where #n > 2
  select #n * #n
// result: array(9, 16, 25)

Integer ranges

Use the to … by form to generate an integer series inline:

with num in 2 to 10 by 2
select #num
// result: array(2, 4, 6, 8, 10)

with i in 1 to 5
select #i + ': item'

Clauses

ClauseDescription
with x in sourceDefine one or more iteration sources.
where conditionFilter rows; only matching rows proceed.
let x = exprBind a derived value for use in later clauses.
skip nSkip the first n rows.
take nLimit to the first n rows.
order by exprSort ascending. Append descending to reverse.
group by exprGroup rows by a key expression.

Actions

ActionReturns
select exprArray of projected values.
do exprEvaluates for side effects; returns void.
sum exprNumeric sum of the expression over all rows.
average exprArithmetic mean.
min exprMinimum value.
max exprMaximum value.

Ordering and multiple clauses

with p in array('Charlie', 'Ada', 'Bob')
  order by #p ascending
  select #p
// result: array('Ada', 'Bob', 'Charlie')

with n in 1 to 20
  where #n % 2 == 0
  let sq = #n * #n
  order by #sq descending
  take 3
  select #sq
// result: array(400, 324, 256)

Aggregate actions

with n in 1 to 100
sum #n
// 5050

with item in array(3, 1, 4, 1, 5, 9)
max #item
// 9

Multiple sources (join)

with a in array(1, 2, 3)
with b in array('x', 'y')
select #a->asString + #b
// 9 combinations: '1x', '1y', '2x', '2y', '3x', '3y'

Group by

with word in array('apple', 'ant', 'banana', 'blueberry', 'cherry')
  group by #word->left(1)
  select #group_key + ': ' + #group_count->asString

Grouped results expose group_key, group_count, and group_values inside the select action.

Sources: maps and custom objects

Maps iterate as first / second pairs. Custom objects that expose a zero-argument asSequence, asArray, or each member can also be used as query sources.

with pair in map(-a=1, -b=2, -c=3)
select #pair->first + '=' + #pair->second->asString
// array('a=1', 'b=2', 'c=3')

Helper forms

The query() helper and forEach member use the same internal sequence adapter:

// query() helper
query(array(1, 2, 3, 4), -where={ #1 > 2 }, -select={ #1 * 10 })
// array(30, 40)

// forEach with a capture block
array('a', 'b', 'c')->forEach => {
  #1 + '-'
}

// string character iteration
'LaiRu'->forEachCharacter => {^ #1 ^}
Not yet implemented: public lazy sequence objects, full eacher/queriable protocol, and exact historical grouping semantics. These are on the roadmap.