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 skal...@users.sourceforge.net 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 Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language