A chain is a linear single-linked list of objects. Chains form the
common way to represent collections of objects in PCE. Chains are also
used to represent multiple-valued slots. Examples are device <-graphicals', class chain<-sub_classes‘,
etc.
PCE chains form the natural counterpart of Prolog lists. For this
reason the PCE/Prolog interface defines predicates to transform Prolog
lists to PCE chains and visa-versa. Note however that in many cases it
is not necessary to convert a PCE chain to a Prolog list; PCE defines
many operations on chains. Before you consider converting a PCE chain to
a Prolog list, first check whether it is not easier to do the job inside
PCE. Notably look at chain->member, chain->empty,. chain->for_all, chain->for_some,
chain<-find, chain<-find_all
and chain<-map.
current cell of the chain. The notion of current
was introduced a long time ago in PCE, while methods only had one
argument. Methods needing a second often used current for
this purpose.
Now that PCE methods may have any number of arguments there is little
use for current. It is advised not to use current.
|function->append
object to chain if it is not already a member of it.
?- new(@ch, chain(aap, noot, mies)). ?- send(@ch, after, noot, aap) --> yes ?- send(@ch, after, aap, mies) --> no
Fails if one of the arguments is not in the chain.
Note that chains may contain duplicates.
->after.
<-head_cell
or chain<-next_cell.
One should try to avoid using this function.
current cell with the argument.
Diagnostics: Fails without modifiying the current element if the index is out of range.
object from the chain. Fails
if there is no such object. Note that objects are compared by their
object identity; not by their contents. Hence, the following fails
because the second point is a different instance.
?- new(@ch, chain(point(6,6))). Yes ?- send(@ch, delete, point(6,6)). No
See also chain->delete_all
and chain->subtract.
->delete.
<-head
and
chain<-delete_head.
Diagnostics: Fails if the chain is empty.
Diagnostics: Fails if the chain is empty.
<-current
if code is executed with success. Fails otherwise. Arguments:
@arg1 The (current) element @arg2 1-based index of element
New code should consider using chain<-find,
which avoids the usage of chain<-current.
@arg1 Current element. @arg2 Index of the element (1-based)
The iteration stops with failure if the execution of code
fails for some element of the chain.
In the example below we print the elements of a chain on the terminal:
?- new(@ch, chain(hello, world)). ?- send(@ch, for_all, message(@pce, write_ln, @arg1)). hello world
If the safe argument is @on
(default), the elements of the chain are first copied to a local array
and existence of the objects in the elements is tested prior to
executing the code
object. This implies that the chain may be modified by the execution of
the method and new elements will not be seen. If this argument is @off
this method iterates over the chain itself. In this case it is not
allowed to modify the chain.
Defaults: By default this operation is caried-out safe
(= @on).
->for_all,
but continues the iteration even if code fails to execute for some
element. Always succeeds. Forwarded arguments:
@arg1 element @arg2 1-based index of element
<-current.
Use of chain<-current
is discouraged and new code must consider using chain->insert_before.
->move_before<-member
of the chain, value is chain->append’ed.
See also chain->insert_after.
->addvalue
is made the chain<-head
of the chain.
See also chain->move_before.
->member
or they are equal. To move an element to the start of the chain, you may
use either of:
?- ignore(send(Ch, move_before, Element, Ch?head)). ?- send(Ch, move_after, Element).
See also chain->move_after, chain->before
and chain->after.
Diagnostics: Fails silently if either argument is not a chain->member
of the chain.
|function],
unique=[bool]code is a function
object, the return status is interpreted as follows:
smaller
@arg1 must be
before @arg2
equal Both elements are equal (neither is
deleted, but their order is undefined).
Common code objects to use are the arithmetic comparison objects and messages invoking a string comparison method. Examples:
Sort a chain of integers, lowest first:
send(Chain, sort, @arg1 < @arg2).
Sort a chain of char_array objects, alphabetically lowest first:
send(Chain, sort, ?(@arg1, compare, @arg2)).
If compare code is omitted, the contents of the chain is
sorted on alphabetically on their object<-print_name.
If unique equals @on,
duplicates (i.e. pairs of objects for which
executing the comparison yields equal) will be removed.
Default is not to remove duplicates. See also chain->unique.
NOTE: When sorting with a non-function, the result of comparing two
element is a boolean and cannot express equal.
chain->sort
yields an undefined result if the chain contains two or more element for
which code->forward and
code->forward
yield the same result. This undefined behaviour can include a fatal
error.
->delete_all.->sort
and chain->add.->clear
to remove the cells.
<-_arg<-_arity
@nil Use default conversion to text. @default Use object <-print_name.Function Use this function, @arg1 is the element.
The return value is a tuple
object. The tuple<-first contains a new
chain holding all elements of the receiving string whose name start with
the given prefix. The tuple<-second
contains a new string
object holding the largest common prefix of all matches. If no element
of the chain matches prefix, this method fails. Example:
?- get(chain(gnu, foo, gnats, bar), complete_name, 'g',
tuple(Matches, string(Common))),
object(Matches, Chain).
Common = gn
Chain = chain(gnu, gnats)
Matches = @854357/chain
See also text_item->complete.
send(new(B, browser), open), send(B, members, [gnu, gnat, gnome]).
When the receiver is a subclass of chain, the resulting chain will be an instance of the same (sub)class: an instance of this subclass is created with no arguments, after which the append behaviour of class chain is used to append the elements.
Bugs: Creating copies of subclasses is ill-defined.
current cell. Use of the current
field of chains is discouraged as it makes the code non-reentrant.
->current
@arg1 Element tested @arg2 1-based index of element
@arg1 Element tested @arg2 1-based index of element
The following example finds all inverted graphicals on the graphical device Dev:
?- get(Dev?graphicals, find_all,
@arg1?inverted == @on, Inverted).
See also chain->for_all.
<-cell_value
@see chain->cell_value<-current_no
@arg1 Element tested @arg2 1-based index of the element
The example below returns a chain with names holding the names of all graphical objects on the graphical device.
graphical_names(Device, Names) :-
get(Device, graphicals, Chain),
get(Chain, map, @arg1?name, Names).
For backward compatibility only, if no argument is provided,
chain<-current
is returned and chain<-current
is moved to the next element.
See also chain<-previous, chain<-nth1, chain<-head
and chain<-tail.
<-cell_value
@see chain->cell_value->current_no<-next, chain<-nth1, chain<-head
and chain<-tail.<-size.
The object at chain<-end is not included.
Example:
?- get_object(chain(0,1,2,3), sub, 1, 2, X). X = chain(1)
See also char_array<-sub.