## 4.22 Analysing and Constructing Atoms

These predicates convert between Prolog constants and lists of character codes. The predicates atom_codes/2, number_codes/2 and name/2 behave the same when converting from a constant to a list of character codes. When converting the other way around, atom_codes/2 will generate an atom, number_codes/2 will generate a number or exception and name/2 will return a number if possible and an atom otherwise.

The ISO standard defines atom_chars/2 to describe the `broken-up' atom as a list of one-character atoms instead of a list of codes. Up to version 3.2.x, SWI-Prolog's atom_chars/2 behaved like atom_codes, compatible with Quintus and SICStus Prolog. As of 3.3.x, SWI-Prolog atom_codes/2 and atom_chars/2 are compliant to the ISO standard.

To ease the pain of all variations in the Prolog community, all SWI-Prolog predicates behave as flexible as possible. This implies the `list-side' accepts either a code-list or a char-list and the `atom-side' accepts all atomic types (atom, number and string).

[ISO]atom_codes(?Atom, ?String)
  Convert between an atom and a list of character codes. If Atom is instantiated, it will be translated into a list of character codes and the result is unified with String. If Atom is unbound and String is a list of character codes, Atom will be unified with an atom constructed from this list.
[ISO]atom_chars(?Atom, ?CharList)
  As atom_codes/2, but CharList is a list of one-character atoms rather than a list of character codes.103Up to version 3.2.x, atom_chars/2 behaved as the current atom_codes/2. The current definition is compliant with the ISO standard.

      ?- atom_chars(hello, X).

      X = [h, e, l, l, o]

[ISO]char_code(?Atom, ?Code)
  Convert between character and character code for a single character.104This is also called atom_char/2 in older versions of SWI-Prolog as well as some other Prolog implementations. The atom_char/2 predicate is available from the library `backcomp.pl`
[ISO]number_chars(?Number, ?CharList)
  Similar to atom_chars/2, but converts between a number and its representation as a list of one-character atoms. If CharList is a proper list, i.e., not unbound or a partial list, CharList is parsed according to the Prolog syntax for numbers and the resulting number is unified with Number. Otherwise, if Number is a number, Number is serialized and the result is unified with CharList.

  If CharList is parsed, it is parsed using the Prolog syntax for numbers. Following the ISO standard, it allows for leading white space (including newlines) and does not allow for trailing white space.105ISO also allows for Prolog comments in leading white space. We--and most other implementations--believe this is incorrect. We also beleive it would have been better not to allow for white space, or to allow for both leading and trailing white space. Prolog syntax-based conversion can also be achieved using format/3 and read_from_chars/2. A `syntax_error` exception is raised if CharList does not represent a valid Prolog number.

[ISO]number_codes(?Number, ?CodeList)
  As number_chars/2, but converts to a list of character codes rather than one-character atoms. In the mode (-,+), both predicates behave identically to improve handling of non-ISO source.
atom_number(?Atom, ?Number)
  Realises the popular combination of atom_codes/2 and number_codes/2 to convert between atom and number (integer or float) in one predicate, avoiding the intermediate list. Unlike the ISO number_codes/2 predicates, atom_number/2 fails silently in mode (+,-) if Atom does not represent a number.106Versions prior to 6.1.7 raised a syntax error, compliant to number_codes/2 See also atomic_list_concat/2 for assembling an atom from atoms and numbers.
name(?Atomic, ?CodeList)
  CodeList is a list of character codes representing the same text as Atomic. Each of the arguments may be a variable, but not both. When CodeList describes an integer or floating point number and Atomic is a variable, Atomic will be unified with the numeric value described by CodeList (e.g., `name(N, "300"), 400 is N + 100` succeeds). If CodeList is not a representation of a number, Atomic will be unified with the atom with the name given by the character code list. If Atomic is an atom or number, the unquoted print representation of it as a character code list is unified with CodeList.

  This predicate is part of the Edinburgh tradition. It should be considered deprecated although, given its long tradition, it is unlikely to be removed from the system. It still has some value for converting input to, depending on the syntax, a number or atom. New code should consider the ISO predicates atom_codes/2, number_codes/2 or the SWI-Prolog predicate atom_number/2.

term_to_atom(?Term, ?Atom)
  True if Atom describes a term that unifies with Term. When Atom is instantiated, Atom is parsed and the result unified with Term. If Atom has no valid syntax, a `syntax_error` exception is raised. Otherwise Term is ``written'' on Atom using write_term/2 with the option `quoted(true)`. See also format/3, with_output_to/2 and term_string/2.
[deprecated]atom_to_term(+Atom, -Term, -Bindings)
  Use Atom as input to read_term/2 using the option `variable_names` and return the read term in Term and the variable bindings in Bindings. Bindings is a list of Name = Var couples, thus providing access to the actual variable names. See also read_term/2. If Atom has no valid syntax, a `syntax_error` exception is raised. New code should use read_term_from_atom/3.
[ISO]atom_concat(?Atom1, ?Atom2, ?Atom3)
  Atom3 forms the concatenation of Atom1 and Atom2. At least two of the arguments must be instantiated to atoms. This predicate also allows for the mode (-,-,+), non-deterministically splitting the 3rd argument into two parts (as append/3 does for lists). SWI-Prolog allows for atomic arguments. Portable code must use atomic_concat/3 if non-atom arguments are involved.
atomic_concat(+Atomic1, +Atomic2, -Atom)
  Atom represents the text after converting Atomic1 and Atomic2 to text and concatenating the result:

      ?- atomic_concat(name, 42, X).
      X = name42.

[commons]atomic_list_concat(+List, -Atom)
  List is a list of strings, atoms, integers or floating point numbers. Succeeds if Atom can be unified with the concatenated elements of List. Equivalent to `atomic_list_concat(List, '', Atom)`.
[commons]atomic_list_concat(+List, +Separator, -Atom)
  Creates an atom just like atomic_list_concat/2, but inserts Separator between each pair of inputs. For example:

      ?- atomic_list_concat([gnu, gnat], ', ', A).

      A = 'gnu, gnat'

  The SWI-Prolog version of this predicate can also be used to split atoms by instantiating Separator and Atom as shown below. We kept this functionality to simplify porting old SWI-Prolog code where this predicate was called concat_atom/3. When used in mode (-,+,+), Separator must be a non-empty atom. See also split_string/4.

      ?- atomic_list_concat(L, -, 'gnu-gnat').

      L = [gnu, gnat]

[ISO]atom_length(+Atom, -Length)
  True if Atom is an atom of Length characters. The SWI-Prolog version accepts all atomic types, as well as code-lists and character-lists. New code should avoid this feature and use write_length/3 to get the number of characters that would be written if the argument was handed to write_term/3.
[deprecated]atom_prefix(+Atom, +Prefix)
  True if Atom starts with the characters from Prefix. Its behaviour is equivalent to `?- sub_atom(Atom, 0, _, _, Prefix)`. Deprecated.
[ISO]sub_atom(+Atom, ?Before, ?Len, ?After, ?Sub)
  ISO predicate for breaking atoms. It maintains the following relation: Sub is a sub-atom of Atom that starts at Before, has Len characters, and Atom contains After characters after the match.

      ?- sub_atom(abc, 1, 1, A, S).

      A = 1, S = b

  The implementation minimises non-determinism and creation of atoms. This is a flexible predicate that can do search, prefix- and suffix-matching, etc.

[semidet]sub_atom_icasechk(+Haystack, ?Start, +Needle)
  True when Needle is a sub atom of Haystack starting at Start. The match is `half case insensitive', i.e., uppercase letters in Needle only match themselves, while lowercase letters in Needle match case insensitively. Start is the first 0-based offset inside Haystack where Needle matches.107This predicate replaces $apropos_match/2, used by the help system, while extending it with locating the (first) match and performing case insensitive prefix matching. We are still not happy with the name and interface.