package debruijn func IsViable(e *Expression) (*Abstraction, Expression, bool) { if e == nil { return nil, nil, false } else if app, appOk := (*e).(*Application); !appOk { return nil, nil, false } else if fn, fnOk := app.abstraction.(*Abstraction); !fnOk { return nil, nil, false } else { return fn, app.argument, true } } func ReduceAll(e *Expression, step func()) { it := NewIterator(e) for !it.Done() { if fn, arg, ok := IsViable(it.Current()); !ok { it.Next() } else { it.Swap(Substitute(fn.body, arg)) step() if _, _, ok := IsViable(it.Parent()); ok { it.Back() } } } }