The iterator feature of Felix is one of the things I find I'm using lot!
Let's review it: here's a list iterator:
gen iterator[T] (var xs:list[T]) () : opt[T] = {
while true do
match xs with
| Cons (?h,?t) => xs = t; yield Some h;
| Empty => return None[T];
endmatch;
done
}
Combined with some parser magic we get
for elt in list(1,2,3) do .. done
Of course this is similar to
iter (fun (elt:int) = { ... }) (list(1,2,3));
but prettier, more imperative, and easily escapable,
but both bodies are callbacks (driven by the iteration).
Iterators are easy to combine in a function (call one, do
a calculation, and yield something, to make a new iterator
from an old one).
Now here's another construction:
ctor list[T] (f: (1->opt[T])) : list[T] = {
var ff = f;
fun aux (l:list[T]) = {
var x = ff();
return
match x with
| Some ?elt => aux (Cons (elt,l))
| None => rev l
endmatch
;
}
return aux Empty[T];
}
This takes an iterator, and make a list. So given ANY data structure
with an iterator IT, and ANY data structure D with a comprehenive constructor,
we can write
D IT
to make a new D. Notice that like STL iterators, the comprehension is
independent
of the source data structure : the iterator IT abstracts it away. So crudely:
var x = list (..);
var y = list ( x.iterator );
So for any set of data structures Ds for which each D in Ds has a comprension
and an iterator, for any two data structures D1, D2 we can make D1 out of a D1
by a standard formula.
What does this mean? Well it means we can throw out all the constructors
that take one data structure to produce another if we want to. For example ..
hehe ..
list (1,2,3) ...
uses a list constructor taking an array argument but we don't need it, instead:
list ( (1,2,3).iterator)
will do. Of course that's a clumsy notation ..
var x = list <<-- (1,2,3)
?? [Unix pipe would be interesting except it's overused already for match cases]
What's even more interesting is that synchronous channels are closely related
to all this.
Another interesting thing .. if that's an iterator/iter .. what's a fold?
Well actually .. a constructor for
typedef sum = int;
ctor sum (f: 1 -> opt[int] ) = {
var s = 0;
for x in f do s = s + x; done
return s;
}
var y = list (1,2,3,4);
var s = sum (y.iterator);
println$ s;
and this constructor is a comprehension for an integer
(that adds up all the integers in a stream). [It works lol!]
So does this:
var y2 = 1,2,3,4;
s = sum (y2.iterator);
println$ s;
Pretty nice, our "sum" can add up all the values of ANY data structure!
STL can do that too, rigtht?
WRONG. STL only PRETENDS to do it.
You must understand templates are syntax macros.
A vector iterator and a list iterator in STL have the same
syntactic operations on them (deref, advance), but they
have different types.
Felix iterator have a type:
1 -> opt[T]
All of them. In Felix an iterator is polymorphic in
the value type and **independent** of the container type.
BTW: producer and consumers above (iterator and comprehension)
are coroutines.
OK .. so .. we really need a nice notation!
--
john skaller
[email protected]
http://felix-lang.org
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Felix-language mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/felix-language