BRiX
Advanced Computing Environment
Hosted by SourceForge
brix-os project page

Previous: Conditionals ----- Up: Contents ----- Next: Shadow Extensions

Loops and Iterators

show notes
Features that need to be added to the page or ideas that haven't been thought out.
  • each usage of WHILE and UNTIL loops increment a poor quality counter for the source code. WHILE loops with static true conditions and UNTIL loops with static false conditions receive an additional quality penalty.
  • allow a list of counter expressions after the condition. these would be equivalent to the third expression in for loops and executed at the end of each iteration of the body.
    	WHILE (condition; counter_expression1; counter_expression2...) body
    a for loop could be done with
    	LET i = 0 -> WHILE (i < 10; i++) (echo i '\n')
  • error category exceptions thrown by the WHILE/UNTIL condition will be handled as a false condition. condition value can be ignored if exceptions are thrown. (while ignore line = read() ...) the end_of_file_error would be a false condition.
  • the EACH index variable could contain three slots (position, first? and last?) to provide more information and require less tracking within the body.
  • rename REDUCE to FOLD?
  • SORT extension?
    	SORT collection WITH (a,b) -> a < b
    `ascending and `descending flags on the collection for simple sorts
    	SORT `ascending collection;
    WITH could be used with an index to select a sub-element to sort the collection by
    	SORT `ascending collection WITH 0
    Would also need a flag to force the sort on the original collection instead of cloning it.
  • all looping extensions register a loop environment and may add callbacks for use by BREAK and CONTINUE.
  • when a looping extension exits it will create a loop_exit_state variable containing two fields: exit and value. the exit field is true if the loop finished normally but false if BREAK was used. the BREAK extension will have an optional value parameter that is stored in the loop_exit_state.value field. the variable is unset whenever a new looping extension begins and set when it exits.
  • BREAK could also be used to exit multiple loops by passing it more than one value. NULLs can be used for each value if there is nothing important to return. The first value is the inner loop and the last value is the outer most loop.
    	BREAK (null, null)
    if this is implemented then loop_exit_state would need to be a list of one or more exit/value pairs. the first element would always be the outer most loop (the last one exited).
  • loop_exit_state could have another field containing the number of loop iterations

Conditional Loops
The WHILE and UNTIL extensions loop while a condition is or is not true. The optional comma is not allowed when the entire condition is wrapped in parentheses or when body is a block expression.

WHILE condition , body
UNTIL condition , body
  • condition -- boolean expression
  • , -- optional syntax to separate condition and body
  • body -- single or block expression
	n := 10
	while n, (echo n-- '\n') // display 10 to 1
	until n == 10, (echo n++ '\n') // display 0 to 9

The DO extension executes a body of code at least once and when followed by WHILE or UNTIL it will continue to execute the body while the condition is or is not true.

DO body WHILE condition
DO body UNTIL condition
  • body -- single or block expression
  • WHILE/UNTIL -- required syntax
  • condition -- boolean expression
	n := 10
	do (echo n-- '\n') while n // display 10 to 1
	do (echo n++ '\n') until n == 10 // display 0 to 9

Collection Loops
The EACH extension is used for iterating over collection types with the current element assigned to a variable. Multiple collections may be used along with an element variable for each collection. The element variables are unset when the loop exits. Mutable elements are only available for mutable collections. The number of iterations is dependant on the smallest collection. Unquoted keys can be used on the element variables to create a variable for accessing the index.

EACH `reversed collections WITH `mutable elements -> body
  • `reversed -- optional flag to iterate the collection in reverse order
  • collections -- unwrapped list of collection objects
  • WITH -- required syntax
  • `mutable -- optional flag to make element variable mutable
  • elements -- unwrapped list of undeclared variable names to reference elements from
  • -> -- required syntax
  • body -- single or block expression
	each 1..5 with e -> (echo e) // display 12345
	each 1..5, 'a'..'e' with n,c -> (echo n c '\n') // display 1a to 5e
	each 'a'..'e' with n::c -> (echo n+1 c '\n') // display 1a to 5e

The MAP extension is similar to the EACH extension except that it creates a new collection of values returned by the mapped expression. Multiple collections and element variables are supported just as with EACH. By default the MAP extension creates a virtual collection object that contains the details of the mapping but nothing is evaluated until the collection is iterated. The optional storage type forces it to evaluate the collection to a real collection storage object. The RETURN extension is redeclared inside the body to end each iteration and pass the result to MAP. The "with element -> body" component is optional when merely applying the collection to a storage type but the extension must be terminated when it is omitted.

MAP `reversed collections TO type WITH elements -> body
  • `reversed -- optional flag to iterate the collection in reverse order
  • collections -- unwrapped list of collection objects
  • TO -- required syntax if storage type is given
  • type -- optional storage type
  • WITH -- required syntax
  • elements -- unwrapped list of undeclared variable names to reference elements from
  • -> -- optional syntax
  • body -- single or block expression, must return a value
	result_array = map 1..5 to Array with e -> e+1 // array of 2..6
	result = map 1..5 with e -> e+1 // lazy collection of 2..6

	result = select (name, phone) from contacts; // lazy collection of contacts
	contacts_list = map result to List; // maps the lazy collection to a list

The FILTER extension does lazy evaluation on each element and returns a virtual collection with each element where the body returned true. The RETURN extension is redeclared inside the body to end each iteration and pass the result to FILTER. Only one collection and one element variable are allowed.

FILTER `reversed collection WITH element -> body
  • `reversed -- optional flag to iterate the collection in reverse order
  • collection -- collection object
  • WITH -- required syntax
  • element -- undeclared variable name to reference elements from body -- single or block expression, must return a boolean value
	result = filter 1..6 with e -> zero? e%2 // lazy collection of 2, 4 and 6

The REDUCE extension assigns the first element to the result variable and the second element to the element variable and executes body. After the first iteration the result of the body is stored in result and the next element is assigned to the element variable. If an initial value is given then result is initialized with it and element begins with the first element. The final result is returned from the extension. The RETURN extension is redeclared inside the body to end each iteration and pass the result to REDUCE. Only one collection and one element variable are allowed.

REDUCE `reversed collection WITH (result::initial, element) -> body
  • `reversed -- flag to iterate the collection in reverse order
  • collection -- collection object
  • WITH -- required syntax
  • result -- undeclared variable name to assign temporary result
  • initial -- optional initial value for result
  • element -- undeclared variable name to reference elements from
  • -> -- optional syntax
  • body -- single or block expression, must return a value
	sum = reduce 1..5 with (a,b) -> a+b // returns 15
	sum = reduce 1..5 with (a::10, b) -> a+b // returns 25

Bounded Loops
The REPEAT extension can be used to execute an expression a fixed number of times. The optional comma is not allowed when the body is a block expression.

REPEAT count , body
  • count -- fixed count
  • , -- optional syntax to separate count and body
  • body -- single or block expression
	repeat 10 (echo ' ') // display 10 spaces

Loop Control
The BREAK extension exits from the current loop and the CONTINUE extension jumps to the next iteration of the current loop.

BREAK

CONTINUE
	while 1 {
	  if foo break
	  if bar continue
	  ...
	}

Previous: Conditionals ----- Up: Contents ----- Next: Shadow Extensions