## 4.29 Built-in list operations

Most list operations are defined in the library `library(lists)` described in section A.12. Some that are implemented with more low-level primitives are built-in and described here.

is_list(+Term)
  True if Term is bound to the empty list (`[]`) or a term with functor ```.``' and arity 2 and the second argument is a list.86In versions before 5.0.1, is_list/1 just checked for `[]` or `[_|_]` and proper_list/1 had the role of the current is_list/1. The current definition conforms to the de facto standard. Assuming proper coding standards, there should only be very few cases where a quick-and-dirty is_list/1 is a good choice. Richard O'Keefe pointed at this issue. This predicate acts as if defined by the definition below on acyclic terms. The implementation fails safely if Term represents a cyclic list.

      is_list(X) :-
              var(X), !,
              fail.
      is_list([]).
      is_list([_|T]) :-
              is_list(T).

[]memberchk(?Elem, +List)
  True when Elem is an element of List. This `chk' variant of member/2 is semi deterministic and typically used to test membership of a list. Raises a `type` error if scanning List encounters a non-list. Note that memberchk/2 does not perform a full list typecheck. For example, `memberchk(a, [a|b])` succeeds without error and memberchk/2 loops on a cyclic list if Elem is not a member of List.
[ISO]length(?List, ?Int)
  True if Int represents the number of elements in List. This predicate is a true relation and can be used to find the length of a list or produce a list (holding variables) of length Int. The predicate is non-deterministic, producing lists of increasing length if List is a partial list and Int is unbound. It raises errors if

  - Int is bound to a non-integer.
  - Int is a negative integer.
  - List is neither a list nor a partial list. This error condition includes cyclic lists.87ISO demands failure here. We think an error is more appropriate.

  This predicate fails if the tail of List is equivalent to Int (e.g., `length(L,L)`).88This is logically correct. An exception would be more appropriate, but to our best knowledge, current practice in Prolog does not describe a suitable candidate exception term.

[ISO]sort(+List, -Sorted)
  True if Sorted can be unified with a list holding the elements of List, sorted to the standard order of terms (see section 4.7). Duplicates are removed. The implementation is in C, using natural merge sort.89Contributed by Richard O'Keefe. The sort/2 predicate can sort a cyclic list, returning a non-cyclic version with the same elements.
msort(+List, -Sorted)
  Equivalent to sort/2, but does not remove duplicates. Raises a `type_error` if List is a cyclic list or not a list.
[ISO]keysort(+List, -Sorted)
  Sort a list of pairs. List must be a list of `Key-Value` pairs, terms whose principal functor is (-)/2. List is sorted on Key according to the standard order of terms (see section 4.7.1). Duplicates are not removed. Sorting is stable with regard to the order of the Values, i.e., the order of multiple elements that have the same Key is not changed.

  The keysort/2 predicate is often used together with library `library(pairs)`. It can be used to sort lists on different or multiple criteria. For example, the following predicates sorts a list of atoms according to their length, maintaining the initial order for atoms that have the same length.

      :- use_module(library(pairs)).

      sort_atoms_by_length(Atoms, ByLength) :-
              map_list_to_pairs(atom_length, Atoms, Pairs),
              keysort(Pairs, Sorted),
              pairs_values(Sorted, ByLength).

predsort(+Pred, +List, -Sorted)
  Sorts similar to sort/2, but determines the order of two terms by calling Pred(-Delta, +E1, +E2) . This call must unify Delta with one of ``<``, ``>`` or ``=``. If the built-in predicate compare/3 is used, the result is the same as sort/2. See also keysort/2.