On Fri, 2006-09-08 at 10:40 +1000, skaller wrote:
> Felix now supports first class iterators, as a special
> case of generators. Here is an example:

Here's more elaborate example:
----------------------------------------
#import <flx.flxh>

union tree = TEmpty | Leaf of int | Node of tree * tree;

var example = 
  Node 
  (
    Node
    (
      Leaf 1,
      Node
      (
        Leaf 2,
        Leaf 3
      )
    )
    ,
    Node
    (
      Leaf 4,
      Leaf 5
    )
  )
;

fun sum: tree->int =
  | Leaf ?x => x
  | Node (?l,?r) => sum l + sum r
  | TEmpty => 0
;

print$ sum example; endl;

fun accumulate(it: 1-> int):int=
{
  var x = 0;
  var v = it();
  whilst v != -1 do
    x += v;
    v = it();
  done;
  return x;
}

gen visitor(x:tree) () : int =
{
  var con =
    match x with
    | Leaf ?a => { print "visiting leaf "; print a; endl; yield a;
return -1; }
    | Node (?a,?b) => 
      { 
        print "visiting node: left\n";
        var it = visitor(a);
        var v = it();
        whilst v != -1 do
          yield v;
          v = it();
        done;
        print "visiting node: right\n";
        it = visitor(b);
        v = it();
        whilst v != -1 do
          yield v;
          v = it();
        done;
        return -1;
      }
    | TEmpty => { return -1; }
    endmatch
  ;
  var r = con();
  whilst r != -1 do
    yield r;
    r = con();
  done;
  return -1;
}

var it = visitor(example);
var res = accumulate(it);
print$ res; endl;

------------------------------------
[EMAIL PROTECTED]:/work/felix/svn/felix/felix/trunk$ flx --test --force rd
15
visiting node: left
visiting node: left
visiting leaf 1
visiting node: right
visiting node: left
visiting leaf 2
visiting node: right
visiting leaf 3
visiting node: right
visiting node: left
visiting leaf 4
visiting node: right
visiting leaf 5
15
------------------------------------

This example is complicated by the fact that matches return
expressions. The expression returned in the visitor is a
generator closure. However we can't simply execute it,
because the internal state would be lost. Instead, it
has to be stored in a variable first.

Then we iterate it, yielding each value.

The example would be simpler if Felix had a procedural match.
[Add to 'todo' list]

This shows that despite generators only yielding up one level,
not deep within a recursion .. it doesn't matter!
Although the whole physical call chain is lost, we have
a list of 'stack frames' on the heap, linked top down
by the state variables 'con' and 'it', so when we 're-enter' the
top level generator, control is threaded down to where
we last left off at every level of the tree.

This is expensive compared to procedures which dispatch
directly, but there's no help for it whilst we're using
the machine stack as a way to hold function return addresses.

[Awesome! It actually works!! Lol!]

-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to