Skip to main content David Edelstein's Blog

🦙
🦙

my implementation of findall/3

Published: 2011-10-04
dave@edelsteinautomotive.com
David Edelstein

I need to actually test this with an interpreter. I think this should work OK though. HoldNext contains the tail of a list we are building by tacking on Binding with each successful run of Code. Then we rebind whats in HoldNext to be the new tail. Finally, if Code fails, we set the var in HoldNext to [] to terminate the list.

The use of nb_setarg/3 is very important to save us from backtracking unwinding our difference list. Without testing this, my only question is if Binding needs to be term_copied before tacking it onto the difference list.

findall(Bindings, Code, ListOut) :-
   HoldNext=hold(ListOut), %store the tail of the difference list here
   (  Code,
      arg(1, HoldNext, Nxt), %var containing the hole to write to
      Nxt=[Bindings|NewNxt],
      nb_setarg(1,HoldNext, NewNxt),
      fail
   ;  arg(1, HoldNext, Nxt),
      Nxt=[]
   ).