Atomic term processing

### 7.19 Atomic term processing

- `atom_length/2`
- `atom_concat/3`
- `sub_atom/5`
- `char_code/2`
- `lower_upper/2`
- `atom_chars/2`, `atom_codes/2`
- `number_atom/2`, `number_chars/2`, `number_codes/2`
- `name/2`
- `atom_hash/2`
- `new_atom/3`, `new_atom/2`, `new_atom/1`
- `current_atom/1`
- `atom_property/2`

These built-in predicates enable atomic terms to be processed as a sequence of characters and character codes. Facilities exist to split and join atoms, to convert a single character to and from the corresponding character code, and to convert a number to and from a list of characters and character codes.

#### 7.19.1 `atom_length/2`

Templates

  `atom_length(+atom, ?integer)`

Description

`atom_length(Atom, Length)` succeeds if `Length` unifies with the number of characters of the name of `Atom`.

Errors

`Atom` is a variable |  | `instantiation_error`
`Atom` is neither a variable nor an atom |  | `type_error(atom, Atom)`
`Length` is neither a variable nor an integer |  | `type_error(integer, Length)`
`Length` is an integer < 0 |  | `domain_error(not_less_than_zero, Length)`

Portability

ISO predicate.

#### 7.19.2 `atom_concat/3`

Templates

  `atom_concat(+atom, +atom, ?atom)
  atom_concat(?atom, ?atom, +atom)`

Description

`atom_concat(Atom1, Atom2, Atom12)` succeeds if the name of `Atom12` is the concatenation of the name of `Atom1` with the name of `Atom1`. This predicate is re-executable on backtracking (e.g. if `Atom12` is instantiated and both `Atom1` and `Atom2` are variables).

Errors

`Atom1` and `Atom12` are variables |  | `instantiation_error`
`Atom2` and `Atom12` are variables |  | `instantiation_error`
`Atom1` is neither a variable nor an atom |  | `type_error(atom, Atom1)`
`Atom2` is neither a variable nor an atom |  | `type_error(atom, Atom2)`
`Atom12` is neither a variable nor an atom |  | `type_error(atom, Atom12)`

Portability

ISO predicate.

#### 7.19.3 `sub_atom/5`

Templates

  `sub_atom(+atom, ?integer, ?integer, ?integer, ?atom)`

Description

`sub_atom(Atom, Before, Length, After, SubAtom)` succeeds if atom `Atom` can be split into three atoms, `AtomL`, `SubAtom` and `AtomR` such that `Before` is the number of characters of the name of `AtomL`, `Length` is the number of characters of the name of `SubAtom` and `After` is the number of characters of the name of `AtomR`. This predicate is re-executable on backtracking.

Errors

`Atom` is a variable |  | `instantiation_error`
`Atom` is neither a variable nor an atom |  | `type_error(atom, Atom)`
`SubAtom` is neither a variable nor an atom |  | `type_error(atom, SubAtom)`
`Before` is neither a variable nor an integer |  | `type_error(integer, Before)`
`Length` is neither a variable nor an integer |  | `type_error(integer, Length)`
`After` is neither a variable nor an integer |  | `type_error(integer, After)`
`Before` is an integer < 0 |  | `domain_error(not_less_than_zero, Before)`
`Length` is an integer < 0 |  | `domain_error(not_less_than_zero, Length)`
`After` is an integer < 0 |  | `domain_error(not_less_than_zero, After)`

Portability

ISO predicate.

#### 7.19.4 `char_code/2`

Templates

  `char_code(+character, ?character_code)
  char_code(-character, +character_code)`

Description

`char_code(Char, Code)` succeeds if the character code for the one-char atom `Char` is `Code`.

Errors

`Char` and `Code` are variables |  | `instantiation_error`
`Char` is neither a variable nor a one-char atom |  | `type_error(character, Char)`
`Code` is neither a variable nor an integer |  | `type_error(integer, Code)`
`Code` is an integer but not a character code |  | `representation_error(character_code)`

Portability

ISO predicate.

#### 7.19.5 `lower_upper/2`

Templates

  `lower_upper(+character, ?character)
  lower_upper(-character, +character)`

Description

`lower_upper(Char1, Char2)` succeeds if `Char1` and `Char2` are one-char atoms and if `Char2` is the upper conversion of `Char1`. If `Char1` (resp. `Char2`) is a character that is not a lower (resp. upper) letter then `Char2` is equal to `Char1`.

Errors

`Char1` and `Char2` are variables |  | `instantiation_error`
`Char1` is neither a variable nor a one-char atom |  | `type_error(character, Char1)`
`Char2` is neither a variable nor a one-char atom |  | `type_error(character, Char2)`

Portability

GNU Prolog predicate.

#### 7.19.6 `atom_chars/2`, `atom_codes/2`

Templates

  `atom_chars(+atom, ?character_list)
  atom_chars(-atom, +character_list)
  atom_codes(+atom, ?character_code_list)
  atom_codes(-atom, +character_code_list)`

Description

`atom_chars(Atom, Chars)` succeeds if `Chars` is the list of one-char atoms whose names are the successive characters of the name of `Atom`.

`atom_codes(Atom, Codes)` is similar to `atom_chars/2` but deals with a list of character codes.

Errors

`Atom` is a variable and `Chars` (or `Codes`) is a partial list or a list with an element which is a variable |  | `instantiation_error`
`Atom` is neither a variable nor an atom |  | `type_error(atom, Atom)`
`Chars` is neither a list nor a partial list |  | `type_error(list, Chars)`
`Codes` is neither a list nor a partial list |  | `type_error(list, Codes)`
`Atom` is a variable and an element `E` of the list `Chars` is neither a variable nor a one-char atom |  | `type_error(character, E)`
`Atom` is a variable and an element `E` of the list `Codes` is neither a variable nor an integer |  | `type_error(integer, E)`
`Atom` is a variable and an element `E` of the list `Codes` is an integer but not a character code |  | `representation_error(character_code)`

Portability

ISO predicates. The ISO reference only causes a `type_error(list, Chars)` if `Atom` is a variable and `Chars` is neither a list nor a partial list. GNU Prolog always checks if `Chars` is a list. Similarly for `Codes`. The `type_error(integer, E)` when an element `E` of the `Codes` is not an integer is a GNU Prolog extension. This seems to be an omission in the ISO reference since this error is detected for many other built-in predicates accepting a character code (e.g. `char_code/2`, `put_code/2`).

#### 7.19.7 `number_atom/2`, `number_chars/2`, `number_codes/2`

Templates

  `number_atom(+number, ?atom)
  number_atom(-number, +atom)
  number_chars(+number, ?character_list)
  number_chars(-number, +character_list)
  number_codes(+number, ?character_code_list)
  number_codes(-number, +character_code_list)`

Description

`number_atom(Number, Atom)` succeeds if `Atom` is an atom whose name corresponds to the characters of `Number`.

`number_chars(Number, Chars)` is similar to `number_atom/2` but deals with a list of characters.

`number_codes(Number, Codes)` is similar to `number_atom/2` but deals with a list of character codes.

Errors

`Number` and `Atom` are variables |  | `instantiation_error`
`Number` is a variable and `Chars` (or `Codes`) is a partial list or a list with an element which is a variable |  | `instantiation_error`
`Number` is neither a variable nor an number |  | `type_error(number, Number)`
`Atom` is neither a variable nor an atom |  | `type_error(atom, Atom)`
`Number` is a variable and `Chars` is neither a list nor a partial list |  | `type_error(list, Chars)`
`Number` is a variable and `Codes` is neither a list nor a partial list |  | `type_error(list, Codes)`
`Number` is a variable and an element `E` of the list `Chars` is neither a variable nor a one-char atom |  | `type_error(character, E)`
`Number` is a variable and an element `E` of the list `Codes` is neither a variable nor an integer |  | `type_error(integer, E)`
`Number` is a variable and an element `E` of the list `Codes` is an integer but not a character code |  | `representation_error(character_code)`
`Number` is a variable, `Atom` (or `Chars` or `Codes`) cannot be parsed as a number and the value of the `syntax_error` Prolog flag is `error` (section 7.22.1) |  | `syntax_error(atom explaining the error)`

Portability

`number_atom/2` is a GNU Prolog predicate. `number_chars/2` and `number_codes/2` are ISO predicates.

GNU Prolog only raises an error about an element `E` of the `Chars` (or `Codes`) list when `Number` is a variable while the ISO reference always check this. This seems an error since the list itself is only checked if `Number` is a variable.

The `type_error(integer, E)` when an element `E` of the `Codes` is not an integer is a GNU Prolog extension. This seems to be an omission in the ISO reference since this error is detected for many other built-in predicates accepting a character code (e.g. `char_code/2`, `put_code/2`).

#### 7.19.8 `name/2`

Templates

  `name(+atomic, ?character_code_list)
  name(-atomic, +character_code_list)`

Description

`name(Constant, Codes)` succeeds if `Codes` is a list whose elements are the character codes corresponding to the successive characters of `Constant` (a number or an atom). However, there atoms are for which `name(Constant, Codes)` is true, but which will not be constructed if `name/2` is called with `Constant` uninstantiated, e.g. the atom `’1024’`. For this reason the use of `name/2` is discouraged and should be limited to compatibility purposes. It is preferable to use atom_codes/2 (section 7.19.6) or number_chars/2 (section 7.19.7).

Errors

`Constant` is a variable and `Codes` is a partial list or a list with an element which is a variable |  | `instantiation_error`
`Constant` is neither a variable nor an atomic term |  | `type_error(atomic, Constant)`
`Constant` is a variable and `Codes` is neither a list nor a partial list |  | `type_error(list, Codes)`
`Constant` is a variable and an element `E` of the list `Codes` is neither a variable nor an integer |  | `type_error(integer, E)`
`Constant` is a variable and an element `E` of the list `Codes` is an integer but not a character code |  | `representation_error(character_code)`

Portability

GNU Prolog predicate.

#### 7.19.9 `atom_hash/2`

Templates

  `atom_hash(+atom, ?integer)
  atom_hash(?atom, +integer)`

Description

`atom_hash(Atom, Hash)` succeeds if `Hash` is the internal key associated with `Atom` (an existing atom). The internal key of an atom is a unique integer ≥ 0 and < to the `max_atom` Prolog flag (section 7.22.1).

Errors

`Atom` and `Hash` are both variables |  | `instantiation_error`
`Atom` is neither a variable nor an atom |  | `type_error(atom, Atom)`
`Hash` is neither a variable nor an integer |  | `type_error(integer, Hash)`
`Hash` is an integer < 0 |  | `domain_error(not_less_than_zero, Hash)`

Portability

GNU Prolog predicate.

#### 7.19.10 `new_atom/3`, `new_atom/2`, `new_atom/1`

Templates

  `new_atom(+atom, +integer, -atom)
  new_atom(+atom, -atom)
  new_atom(-atom)`

Description

`new_atom(Prefix, Hash, Atom)` unifies `Atom` with a new atom whose name begins with the characters of the name of `Prefix` and whose internal key is `Hash` (section 7.19.9). This predicate is then a symbol generator. It is guaranteed that `Atom` does not exist before the invocation of `new_atom/3`. The characters appended to `Prefix` to form `Atom` are in: `A`-`Z` (capital letter), `a`-`z` (small letter), `0`-`9` (digit), `#`, `$`, `&`, `_`, `@`.

`new_atom/2` is similar to `new_atom/3`, but the atom generated can have any (free) internal key.

`new_atom/1` is similar to `new_atom(atom_, Atom)`, i.e. the generated atom begins with `atom_`.

Errors

`Prefix` is a variable |  | `instantiation_error`
`Hash` is a variable |  | `instantiation_error`
`Prefix` is neither a variable nor an atom |  | `type_error(atom, Prefix)`
`Hash` is neither a variable nor an integer |  | `type_error(integer, Hash)`
`Hash` is an integer < 0 |  | `domain_error(not_less_than_zero, Hash)`
`Atom` is not a variable |  | `type_error(variable, Atom)`

Portability

GNU Prolog predicate.

#### 7.19.11 `current_atom/1`

Templates

  `current_atom(?atom)`

Description

`current_atom(Atom)` succeeds if there exists an atom that unifies with `Atom`. All atoms are found except those beginning with a `’$’` (system atoms). This predicate is re-executable on backtracking.

Errors

`Atom` is neither a variable nor an atom |  | `type_error(atom, Atom)`

Portability

GNU Prolog predicate.

#### 7.19.12 `atom_property/2`

Templates

  `atom_property(?atom, ?atom_property)`

Description

`atom_property(Atom, Property)` succeeds if `current_atom(Atom)` succeeds (section 7.19.11) and if `Property` unifies with one of the properties of the atom. This predicate is re-executable on backtracking.

Atom properties:

- `length(Length)`: `Length` is the length of the name of the atom.
- `hash(Hash)`: `Hash` is the internal key of the atom (section 7.19.9).
- `prefix_op`: if there is a prefix operator currently defined with this name.
- `infix_op`: if there is an infix operator currently defined with this name.
- `postfix_op`: if there is a postfix operator currently defined with this name.
- `needs_quotes`: if the atom must be quoted to be read later.
- `needs_scan`: if the atom must be scanned when output to be read later (e.g. contains special characters that must be output with a `\` escape sequence).

Errors

`Atom` is neither a variable nor an atom |  | `type_error(atom, Atom)`
`Property` is neither a variable nor a n atom property term |  | `domain_error(atom_property, Property)`
`Property` = `length(E)` or `hash(E)` and `E` is neither a variable nor an integer |  | `type_error(integer, E)`

Portability

GNU Prolog predicate.

Copyright (C) 1999-2009 Daniel Diaz Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved. More about the copyright