I’m getting stymied by a task that I’d find simple in other languages, but I just don’t know what the best way is to implement it in Prolog. Specifically, I want to perform several processing steps on a stream of data, each of which may or may not change the cardinality of the dataset, and which may or may not be deterministic, and I’d like them to operate without having to hold the entire stream (or, worse, multiple copies of the stream) in memory. Basically, I want to do the following:
process_stream(List0, Processed) :- transformation1(List0, List1), % no cut transformation2(List1, List2), % no cut transformation3(List2, Processed).
only, without storing the whole list in between. If all the streams had the same cardinality, I could just do:
process_stream([H0|T0], [HP|TP]) :- transform1(H0, H1), transform2(H1, H2), transform3(H2, HP), process_stream(T0, TP). process_stream(, ).
but that only works if the lists remain in lockstep, and each can process a single element at a time, without context.
In, say, Python or C#, I could just use generators/iterators, with each transformer consuming the elements it needs before yielding whatever values it can produce to its output. I’ve glanced at
library(lazy_lists), but that really seems geared only towards deterministic processes, and especially those that can opportunistically pull in a whole block of data at once. Basically, for reading from file/network. And honestly, constraint programming in general seems pretty ill-suited to this, because unless you are dealing with a det/semidet source and you use extra-logical storage for stream blocks, it only ever works in post-hoc mode. Basically, if you had this definition for
transform2(foo, bar). transform2(apple, banana). transform2(bear, eel).
and you called it with a delayed/attributed variable in the first argument that would eventually resolve to ‘bear’, Prolog would have no choice but to try unifying it with foo, calling the unification hook, failing to unify
foo = bear, undo the
H1 = foo unification, try it again with
H1 = apple, and so on. Not precisely the most practical or efficient way to go about things.
So, how do I do this in Prolog? And, to extend it a little, how do I do it with DCGs, which are even more limited in their calling convention?