Question
Is it possible to schedule a goal to be executed as soon as the length of a list is known / fixed or, as @false pointed out in the comments, a given argument becomes a [proper] list? Something along this line:
when(fixed_length(L), ... some goal ...).
When-conditions can be constructed using ?=/2
, nonvar/1
, ground/1
, ,/2
, and ;/2
only and it seems they are not very useful when looking at the whole list.
As a further detail, I'm looking for a solution that presents logical-purity if that is possible.
Motivation
I think this condition might be useful when one wants to use a predicate p(L)
to check a property for a list L
, but without using it in a generative way.
E.g. it might be the case that [for efficiency or termination reasons] one prefers to execute the following conjunction p1(L), p2(L)
in this order if L
has a fixed length (i.e. L
is a list), and in reversed order p2(L), p1(L)
otherwise (if L
is a partial list).
This might be achieved like this:
when(fixed_length(L), p1(L)), p2(L).
Update
I did implement a solution, but it lacks purity.
It would be nice if when/2
would support a condition list/1
. In the meantime, consider:
list_ltruth(L, Bool) :-
freeze(L, nvlist_ltruth(L, Bool)).
nvlist_ltruth(Xs0, Bool) :-
( Xs0 == [] -> Bool = true
; Xs0 = [_|Xs1] -> freeze(Xs1, nvist_ltruth(Xs1, Bool))
; Bool = false
).
when_list(L, Goal_0) :-
nvlist_ltruth(L, Bool),
when(nonvar(Bool),( Bool == true, Goal_0 )).
So you can combine this also with other conditions.
Maybe produce a type error, if L
is not a list.
when(nonvar(Bool), ( Bool == true -> Goal_0 ; sort([], L) ).
Above trick will only work in an ISO conforming Prolog system like SICStus or GNU that produces a type_error(list,[a|nonlist])
for sort([],[a|nonlist])
, otherwise replace it by:
when(nonvar(Bool),
( Bool == true -> Goal_0 ; throw(error(type_error(list,L), _)).
Many systems contain some implementation specific built-in like '$skip_list'
to traverse lists rapidly, you might want to use it here.