Iterable
In Shim, an “iterable” is a value that has an .iter() method that returns an
iterator. Lists, Ranges, and Dicts
are a few of the built-in iterables. Structs can also define their own iterators.
An “iterator” is a value with a .next() method that returns a value. When the
iterator has no more values to return it should return StopIteration.
Typically you would use an iterator in a for loop.
let lst = [0, 1, 2]
for item in lst {
print(item)
}Press the play button to execute
You can see how that unrolls by calling .iter and .next explicitly
let lst = [0, 1, 2] let iter = lst.iter() print(iter.next()) print(iter.next()) print(iter.next()) print(iter.next())
Press the play button to execute
Builtin Iterables
These builtin types are iterable:
- Lists - Yields each item in the list in order
- Dicts - Yields each key in the dict in insertion order. Use
.values()to get just the values or.items()to get key-value pairs. - Sets - Yields each value in the set in insertion order
- Strings - Yields each character in the string
- Ranges - Yields each value in the range (not including the end point)
List Example
for item in ["foo", None, 42] {
print(item)
}Press the play button to execute
Dict Example
let d = {"foo": "bar", 42: true}
for key in d {
print(key)
}
for value in d.values() {
print(value)
}
for key, value in d.items() {
print("\(key): \(value)")
}Press the play button to execute
Set Example
let s = {"foo", "bar", 42, true}
for value in s {
print(value)
}Press the play button to execute
String Example
let s = "Hello!"
for c in s {
print(c)
}Press the play button to execute
Range Example
for x in 1..5 {
print(x)
}Press the play button to execute
Builtin Functions
There are a number of builtin functions that operate on iterables:
- map(iter, fn) - Returns a List of items where each item yielded by
iteris transformed by the provided function - filter(iter) - Returns a List of truthy items yielded by the iterable
- filter(iter, pred) - Returns a List of items where the function
predreturns a truthy value - average(iter) - Returns the sum of the items in the iterable, divided by the count (or 0 if empty)
- enumerate(iter) - Returns a List of tuples where the first item is the index and the second item is the value
Map Example
fn double(x) {
x * 2
}
print(map([1, 2, 3], double))Press the play button to execute
Filter Example
fn is_big(x) {
x > 5
}
print(filter([0, 5, 10, 15, 20]))
print(filter([0, 5, 10, 15, 20], is_big))Press the play button to execute
Average Example
print(average([])) print(average([0, 1, 2]))
Press the play button to execute
Enumerate Example
let instruments = ["trumpet", "flute", "piano"]
for idx, instrument in enumerate(instruments) {
print("\(idx): \(instrument)")
}Press the play button to execute
Custom Iterators
Structs can define their own iteration methods. Here we define an iterable struct
(a struct that has an .iter() method) that returns an iterator (a struct that
has a .next() method).
struct CountDownIterator {
num
fn next(self) {
let ret = if self.num >= 0 {
self.num
} else {
StopIteration
}
self.num -= 1
ret
}
}
struct CountDown {
fn iter(self) {
CountDownIterator(5)
}
}
for item in CountDown() {
print(item)
}Press the play button to execute
Shim provides a convenient builtin Iterator to make this a bit cleaner so that
you don’t need to define a new iterator object separate from your iterable struct.
struct CountDown {
fn iter(self) {
let num = 5
Iterator(fn() {
let ret = if num >= 0 {
num
} else {
StopIteration
}
num -= 1
ret
})
}
}
for item in CountDown() {
print(item)
}Press the play button to execute