## 4.20 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, compatible with Quintus and SICStus Prolog, like atom_codes. 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' accept 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, if 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, it will 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 codes54Up-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.55This 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. Fails with a `syntax_error` if Number is unbound and CharList does not describe a number. Following the ISO standard, it allows for leading white space (including newlines) and does not allow for trailing white space.56ISO 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 be achieved using format/3 and read_from_chars/2.
[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. Calling in mode +,- to convert numbers represented as atoms is often good style. Converting numbers to atoms, which in turn are assembled into larger units before communication them to the outside world is bad style. Consider using streams or with_output_to/2 to reduce the number of expensive intermediate atoms.
name(?AtomOrInt, ?String)
  String is a list of character codes representing the same text as Atom. Each of the arguments may be a variable, but not both. When String is bound to an character code list describing an integer and Atom is a variable Atom will be unified with the integer value described by String (e.g., ``name(N, "300"), 400 is N + 100`' succeeds). New code should consider using the ISO predicates atom_codes/2 or number_codes/2.57Unfortunately, the ISO predicates provide no neat way to check that a string can be interpreted as a number. The most sensible way is to use catch/3 to catch the exception from number_codes/2, however this is both slow and cumbersome.
term_to_atom(?Term, ?Atom)
  True if Atom describes a term that unifies with Term. When Atom is instantiated Atom is converted and then 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 and with_output_to/2.
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.
[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 3-th 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 atoms, integers or floating point numbers. Succeeds if Atom can be unified with the concatenated elements of List.
[commons]atomic_list_concat(+List, +Separator, ?Atom)
  Creates an atom just like atomic_list_concat/2, but inserts Separator between each pair of atoms. 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.

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

      L = [gnu, gnat]

[ISO]atom_length(+Atom, -Length)
  True if Atom is an atom of Length characters long. This predicate also works for strings (see section 4.22). If the prolog flag iso is not set, it also accepts integers and floats, expressing the number of characters output when given to write/1 as well as code-lists and character-lists, expressing the length of the list.bugNote that `[]` is both an atom an empty code/character list. The predicate atom_length/2 returns 2 for this atom.
atom_prefix(+Atom, +Prefix)
  True if Atom starts with the characters from Prefix. Its behaviour is equivalent to `?- sub_atom(Atom, 0, _, _, Prefix)`. Depreciated.
[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 very flexible predicate that can do search, prefix- and suffix-matching, etc.