This module builds a lazy list from a predicate that fetches a slice of this list. In addition it provides interactors (slice constructors) for several common use cases for lazy lists, such as reading objects of several sizes from files (characters, lines, terms), reading messages from message queues and reading answers from engines.
Lazy lists are lists that end in a constraint. Trying to unify the constraint forces the next slice of the list to be fetched and added to the list.
The typical use case for lazy lists is to run a DCG grammar on it. For example, an agent may be listening on a socket and turn the line-based message protocol into a list using the fragment below.
..., tcp_open(Socket, Read, Write), lazy_list(lazy_read_lines(Read, [as(codes)]), List), phrase(action, List).
Typically, the iterator works on a globally allocated object that is not always subject to garbage collection. In such cases, the skeleton usage follows the pattern below:
setup_call_cleanup( <open resource>(R), ( lazy_list(<iterator>(R), List), process_list(List) ), <close resource>(R))
This is rather unfortunately, but there is no way we can act on the fact that List is no further accessed. In some cases, e.g., message queues or engines, the resource is subject to (atom) garbage collection.
call(Next, List, Tail)
, where
the difference list List\Tail produces the next slice of the
list. If the end of the input is reached, List must be a
proper list and Tail must be []
.
call(Next, State0, State1, Head)
The example below uses this predicate to define a lazy list holding the Fibonacci numbers. Our state keeps the two previous Fibonacci numbers.
fibonacci_numbers(L) :- lazy_list(fib, state(-,-), L). fib(state(-,-), state(0,-), 0) :- !. fib(state(0,-), state(1,0), 1) :- !. fib(state(P,Q), state(F,P), F) :- F is P+Q.
The above can be used to retrieve the Nth Fibonacci number. As fib/2 provides no access to the complete list of Fibonacci numbers, this can be used to generate large Fibonacci numbers.
fib(N, F) :- fibonacci_numbers(L), nth1(N, L, F).
atom
, string
, codes
or chars
. Default is string
.A thread can listen to its own message queue using
thread_self(Me), lazy_list(lazy_message_queue(Me, []), List), phrase(action(List)).
The following predicates are exported from this file while their implementation is defined in imported modules or non-module files loaded by this module.