List Comprehension Syntax
Let's create arguably one of the most useful constructs when working with iterable structures: list comprehensions. This can be done thanks to Ryna's syntax definition features.
What is list comprehension?
List comprehensions are a syntax option in some languages that allow the programmer to transform the values of a list or even filter them without having to create an explicit for loop and a temporary variable. In this case, we will not deal with filtering the list.
Creating the syntax
The syntax for list comprehensions then to be something like this:
[expr for elem in container]
This is problematic for us because Ryna is a strongly typed language. We will have to adapt it like this:
[expr for elem: ElemType in container]
This can be expressed in NDL like this:
"["
[s] Arg(<expr>, map) [s] // Map expression
"for" [s] Arg(<ident>, it) [s] ":" [s] Arg(<type>, type) [s] // Element
"in" [s] Arg(<expr>, container) [s] // Container
"]"
Note that you need Arg
s to mark the variables that we will use inside the body.
Generating the body
Internally, a list comprehension is just a for loop with a transformation function. There are multiple ways to do this, but this is one of them (again, note that we have to escape the for's closing brace):
syntax list_comprehension from [...] {
let res = arr<$type>();
let func = ($it: $type) -> $type $map;
for _it_ in $container {
res.push(func(*_it_));
\}
return move(res);
}
Example
Making use of an Array
initialization syntax, you can build the following code:
let array = [i * 2 for i: Int in <Int>[1, 2, 3, 4, 5]]; // [2, 4, 6, 8, 10]
This would compile to:
let array = do {
let res = arr<Int>();
let func = (i: Int) -> Int i * 2;
for _it_ in <Int>[1, 2, 3, 4, 5] {
res.push(func(*_it_));
}
return *res;
};
In this example <Int>[1, 2, 3, 4, 5]
would also be recursively compiled into a new expression based on a lambda expression, but
the exact compilation is not important.