Skip to main content

Evaluation model

Declarations in Snapi must be defined in order, i.e. if a declaration f uses a declaration g, then the declaration g must be defined earlier in the program.

Identifers have a constant value. The value of an identifier cannot change, i.e. it is not possible to re-assign a new value to an existing identifier.

Collections have the most complex semantics (refer to the section on Lists and Collections for a discussion, including the differences between the two). Collections are lazily evaluated, i.e. only evaluated when consumed. In particular, unlike a list, the same collection may be created more than once. For instance:

let
data = Json.Read("http://example/some.json", type collection(record(age: int, height_in_cm: int))),
adults = Collection.Filter(data, r -> r.age > 18),
height_over_175_cm = Collection.Filter(data, r -> r.height_in_cm > 175)
in
{adults: adults, height_over_175_cm: height_over_175_cm}

The example above returns a single record with the fields adults and height_over_175_cm. The identifier data is defined once and used twice: to filter adults and those with height over 175 cm.

In the example above, is the JSON file read once or twice? In the case of a collection, the JSON file is typically read twice [*] (but this is not guaranteed behaviour either as discussed later).

Does this mean that using lists is better, e.g. ?

let
data = Json.Read("http://example/some.json", type list(record(age: int, height_in_cm: int))),
adults = List.Filter(data, r -> r.age > 18),
height_over_175_cm = List.Filter(data, r -> r.height_in_cm > 175)
in
{adults: adults, height_over_175_cm: height_over_175_cm}

In this example, collections are replaced by lists. Therefore, the JSON file is guaranteed to be read only once and stored onto a list. However, this may not necessarily be a good thing: for instance, the JSON file may be extremely large so the data cannot be stored and the list cannot be built. Moreover, intermediary operations on lists, such as List.Filter, build additional lists and that consumes resources.

  • [*] The earlier example with collections mentions that the file is typically read twice. That's because the engine includes certain optimizations including caching, which means that within certain scenarios the data may be read only once and then reused from short-lived internal system caches. These internal system caches attempt to cache source data as to prevent repeated reads.