Standard Library Design
The standard library has to provide basic data types like integers, floats, strings, array, lists, maps, etc. Parts of the library need to be known to the Fuzion front end to provide syntactic sugar and some even to the back end for an efficient implementation.
Mutability
The standard library should provide immutable and mutable features, while the default should be immutable.
Iterators
To iterate over a collection, one could use integer indices (as in a for loop), an iterator instance (as in a Java iterating for loop), a stream or a (lazy) list. Only a list uses immutable instances.
Collection Initialization
Fuzion should have syntactic sugar for the creation of arrays, lists and maps with pre-defined values. These values could be compile-time constants or run-time variables.
Arrays
in Java: var arr = new int[] {1, 2, 3, 4};
in Rust: let arr:[i32;4] = [1, 2, 3, 4];
in F#: let arr = [| 1; 2; 3; 4; 5; 6 |]
in Python: arr = array.array('i', [1, 2, 3, 4])
In Fuzion: using brackets []
appears syntactically close to
indexing using brackets, so this might be best. The array type could be inferred
from the elements or the target of the assignment. The result should be an
immutable array:
arr := [1, 2, 3, 4]
Lists
in Java: var l = Arrays.asList(1, 2, 4, 5);
in Rust: let l = vec![1, 2, 3, 4];
in Python: l = [1, 2, 3, 4]
in Go: l := []int{1, 2, 3, 4}
in Lua: l := {1, 2, 3, 4}
In Fuzion: If an array is one possible implementation of a list, the array syntax can be used:
l := [1, 2, 3, 4]
Maps
in Java:
import java.util.HashMap; import java.util.Map; Map<String,Integer> x = new HashMap<>(); x.put("one", 1); x.put("two", 2);
in Rust:
use std::collections::HashMap; let x: HashMap<&str, i32> = [ ("one", 1), ("two", 2), ].iter().cloned().collect();
in Python:
x = {"one" : 1, "two" : 2}
in Go:
x := map[String]int {"one": 1, "two": 2}
in Lua:
x = {one = 1, two = 2}
In Fuzion: Hash map are inherently non-deterministic with an awful worst-case performance. So, hash maps should only be used if perfect hashing is possible at compile time. Otherwise, a tree map could be used if a total order is defined for the keys. The map type should be given explicitly unless perfect hashing or a tree map is possible.
Tuple syntax could be used to declare an array that is then used to create a map.
map := tree_map_from_array [("one", 1), ("two", 2)]
Arrays
TBWLists
A list in Fuzion should be much like a list in Lisp: a list should either be empty or consists of a head element and a list tail.
Need to decide how to represent an empty list. An empty list could
either be nil
as follows
list (T type) : choice nil (node T) is node (T type, head T, tail list T) is
or a list whose head element is nil
.
list (T type, head option T, tail option (ref list T)) is
Using nil
for an empty list seems cleaner, but it should be
possible to add list-specific inner features that handle the empty list case,
e.g., a size
feature that returns 0
for an empty list:
list (T type) : choice nil (node T) is size => size 0 private size(s i32) => match list.this nil => s n node T => n.tail.size s+1 // tail recursion node (T type, head T, tail list T) is
Using the first variant with nil
being a valid empty list seems
the way to go.