Meta-Logical

To facilitate manipulation of terms as objects in themselves, XSB provides a number meta-logical predicates. These predicates include the standard meta-logical predicates of Prolog, along with their usual semantics. In addition are provided predicates which provide special operations on HiLog terms. For a full discussion of Prolog and HiLog terms see Section 4.1.

`var(?X)`-

Succeeds if`X`is currently uninstantiated (i.e. is still a variable); otherwise it fails.Term

`X`is uninstantiated if it has not been bound to anything, except possibly another uninstantiated variable. Note in particular, that the HiLog term X(Y,Z) is considered to be instantiated. There is no distinction between a Prolog and a HiLog variable.Examples:

| ?- var(X). yes | ?- var([X]). no | ?- var(X(Y,Z)). no | ?- var((X)). yes | ?- var((X)(Y)). no

`nonvar(?X)`-

Succeeds if`X`is currently instantiated to a non-variable term; otherwise it fails. This has exactly the opposite behaviour of`var/1`. `atom(?X)`-

Succeeds only if the`X`is currently instantiated to an atom, that is to a Prolog or HiLog non-numeric constant.Examples:

| ?- atom(HiLog). no | ?- atom(10). no | ?- atom('HiLog'). yes | ?- atom(X(a,b)). no | ?- atom(h). yes | ?- atom(+). yes | ?- atom([]). yes

`integer(?X)`-

Succeeds if`X`is currently instantiated to an integer; otherwise it fails. `real(?X)`-

Succeeds if`X`is currently instantiated to a floating point number; otherwise it fails. `float(?X)`-

Same as`real/1`. Succeeds if`X`is currently instantiated to a floating point number; otherwise it fails. This predicate is included for compatibility with earlier versions of SBProlog. `number(?X)`-

Succeeds if`X`is currently instantiated to either an integer or a floating point number (real); otherwise it fails. `atomic(?X)`-

Succeeds if`X`is currently instantiated to an atom or a number; otherwise it fails.Examples:

| ?- atomic(10). yes | ?- atomic(p). yes | ?- atomic(h). yes | ?- atomic(h(X)). no | ?- atomic("foo"). no | ?- atomic('foo'). yes | ?- atomic(X). no | ?- atomic(X((Y))). no

`compound(?X)`-

Succeeds if`X`is currently instantiated to a compound term (with arity greater that zero), i.e. to a nonvariable term that is not atomic; otherwise it fails.Examples:

| ?- compound(1). no | ?- compound(foo(1,2,3)). yes | ?- compound([foo, bar]). yes | ?- compound("foo"). yes | ?- compound('foo'). no | ?- compound(X(a,b)). yes | ?- compound((a,b)). yes

`structure(?X)`-

Same as`compound/1`. Its existence is only for compatibility with SB-Prolog version 3.1. `is_list(?X)`-

Succeeds if`X`is a*proper list*. In other words if it is either the atom`[]`or`[H|T]`where H is any Prolog or HiLog term and T is a proper list; otherwise it fails.Examples:

| ?- is_list([p(a,b,c), h(a,b)]). yes | ?- is_list([_,_]). yes | ?- is_list([a,b|X]). no | ?- is_list([a|b]). no

`is_charlist(+X)`-

Succeeds if`X`is a Prolog string,*i.e.*, a list of characters. Examples:| ?- is_charlist("abc"). yes | ?- is_charlist(abc). no

`is_charlist(+X,-Size)`-

Like above, but also returns the length of that string in the second argument, which must be a variable. `is_most_general_term(?X)`-

Succeeds if`X`is compound term with all distinct variables as arguments, or if`X`is an atom. (It fails if X is a cons node.)| ?- is_most_general_term(f(_,_,_,_)). yes | ?- is_most_general_term(abc). yes | ?- is_most_general_term(f(X,Y,Z,X)). no | ?- is_most_general_term(f(X,Y,Z,a)). no | ?- is_most_general_term([_|_]). no

`callable(?X)`-

Succeeds if`X`is currently instantiated to a term that standard predicate`call/1`could take as an argument and not give an instantiation or type error. Note that it only checks for errors of predicate`call/1`. In other words it succeeds if`X`is an atom or a compound term; otherwise it fails. Predicate`callable/1`has no associated error conditions.Examples:

| ?- callable(p). yes | ?- callable(p(1,2,3)). yes | ?- callable([_,_]). yes | ?- callable(_(a)). yes | ?- callable(3.14). no

`proper_hilog(?X)`-
*HiLog*

Succeeds if`X`is a proper HiLog term; otherwise it fails.Examples: (In this example and the rest of the examples of this section we assume that

`h`is the only parameter symbol that has been declared a HiLog symbol).| ?- proper_hilog(X). no | ?- proper_hilog(foo(a,f(b),[A])). no | ?- proper_hilog(X(a,b,c)). yes | ?- proper_hilog(3.6(2,4)). yes | ?- proper_hilog(h). no | ?- proper_hilog([a, [d, e, X(a)], c]). yes | ?- proper_hilog(a(a(X(a)))). yes

`functor(?Term, ?Functor, ?Arity)`-

Succeeds if the*functor*of the Prolog term`Term`is`Functor`and the*arity*(number of arguments) of`Term`is`Arity`.`Functor`can be used in either the following two ways:- If
`Term`is initially instantiated, then- If
`Term`is a compound term,`Functor`and`Arity`are unified with the name and arity of its principal functor, respectively. - If
`Term`is an atom or a number,`Functor`is unified with`Term`, and`Arity`is unified with 0.

- If
- If
`Term`is initially uninstantiated, then either both`Functor`and`Arity`must be instantiated, or`Functor`is instantiated to a number, and- If
`Arity`is an integer in the range 1..255, then`Term`becomes instantiated to*the most general Prolog term*having the specified`Functor`and`Arity`as principal functor and number of arguments, respectively. The variables appearing as arguments of`Term`are all distinct. - If
`Arity`is 0, then`Functor`must be either an atom or a number and it is unified with`Term`. - If
`Arity`is anything else, then`functor/3`aborts.

- If

Exceptions:

`domain_error``Functor`is instantiated to a compound term.`instantiation_error`- Both
`Term`, and either`Functor`, or`Arity`are uninstantiated.

Examples:

| ?- functor(p(f(a),b,t), F, A). F = p A = 3 | ?- functor(T, foo, 3). T = foo(_595708,_595712,_595716) | ?- functor(T, 1.3, A). T = 1.3 A = 0 | ?- functor(foo, F, 0). F = foo | ?- functor("foo", F, A). F = . A = 2 | ?- functor([], [], A). A = 0 | ?- functor([2,3,4], F, A). F = . A = 2 | ?- functor(a+b, F, A). F = + A = 2 | ?- functor(f(a,b,c), F, A). F = f A = 3 | ?- functor(X(a,b,c), F, A). F = apply A = 4 | ?- functor(map(P)(a,b), F, A). F = apply A = 3 | ?- functor(T, foo(a), 1). ++Error: Wrong type in argument 2 of functor/3 Aborting... | ?- functor(T, F, 3). ++Error: Uninstantiated argument 2 of functor/3 Aborting... | ?- functor(T, foo, A). ++Error: Uninstantiated argument 3 of functor/3 Aborting...

- If
`hilog_functor(?Term, ?F, ?Arity)`-
*HiLog*

The XSB standard predicate`hilog_functor/3`succeeds- when
`Term`is a Prolog term and the principal function symbol (*functor*) of`Term`is`F`and the*arity*(number of arguments) of`Term`is`Arity`, or - when
`Term`is a HiLog term, having*name*`F`and the number of arguments`F`is applied to, in the HiLog term, is`Arity`.

`functor/3`, while the second is the extension of`functor/3`to handle HiLog terms. Like the Prolog's`functor/3`predicate,`hilog_functor/3`can be used in either of the following two ways:- If
`Term`is initially instantiated, then- If
`Term`is a Prolog compound term,`F`and`Arity`are unified with the name and arity of its principal functor, respectively. - If
`Term`is an atom or a number,`F`is unified with`Term`, and`Arity`is unified with 0. - If
`Term`is any other HiLog term,`F`and`Arity`are unified with the name and the number of arguments that`F`is applied to. Note that in this case`F`may still be uninstantiated.

- If
- If
`Term`is initially uninstantiated, then at least`Arity`must be instantiated, and- If
`Arity`is an integer in the range 1..255, then`Term`becomes instantiated to*the most general Prolog or HiLog term*having the specified`F`and`Arity`as name and number of arguments`F`is applied to, respectively. The variables appearing as arguments are all unique. - If
`Arity`is 0, then`F`must be a Prolog or HiLog constant, and it is unified with`Term`. Note that in this case`F`cannot be a compound term. - If
`Arity`is anything else, then`hilog_functor/3`aborts.

- If

`hilog_functor/3`either decomposes a given HiLog term into its*name*and*arity*, or given an arity --and possibly a name-- constructs the corresponding HiLog term creating new uninstantiated variables for its arguments. As happens with`functor/3`all constants can be their own principal function symbols.Examples:

| ?- hilog_functor(f(a,b,c), F, A). F = f A = 3 | ?- hilog_functor(X(a,b,c), F, A). X = _595836 F = _595836 A = 3 | ?- hilog_functor(map(P)(a,b), F, A). P = _595828 F = map(_595828) A = 2 | ?- hilog_functor(T, p, 2). T = p(_595708,_595712) | ?- hilog_functor(T, h, 2). T = apply(h,_595712,_595716) | ?- hilog_functor(T, X, 3). T = apply(_595592,_595736,_595740,_595744) X = _595592 | ?- hilog_functor(T, p(f(a)), 2). T = apply(p(f(a)),_595792,_595796) | ?- hilog_functor(T, h(p(a))(L1,L2), 1). T = apply(apply(apply(h,p(a)),_595984,_595776),_596128) L1 = _595984 L2 = _595776 | ?- hilog_functor(T, a+b, 3). T = apply(a+b,_595820,_595824,_595828)

- when
`arg(+Index, +Term, ?Argument)`-

Unifies`Argument`with the argument of`Term`, where the index is taken to start at . Initially,`Index`must be instantiated to any integer and`Term`to any non-variable Prolog or HiLog term. The arguments of the`Term`are numbered from 1 upwards. An atomic term has arguments. If the initial conditions are not satisfied or is out of range, the call quietly fails.Examples:

| ?- arg(2, p(a,b), A). A = b | ?- arg(2, h(a,b), A). A = a | ?- arg(0, foo, A). no | ?- arg(2, [a,b,c], A). A = [b,c] | ?- arg(2, "HiLog", A). A = [105,108,111,103] | ?- arg(2, a+b+c, A). A = c | ?- arg(3, X(a,b,c), A). X = _595820 A = b | ?- arg(2, map(f)(a,b), A). A = a | ?- arg(1, map(f)(a,b), A). A = map(f) | ?- arg(1, (a+b)(foo,bar), A). A = a+b

`arg0(+Index, +Term, ?Argument)`-

Unifies`Argument`with the argument of`Term`if`Index`0, or with the functor of`Term`if`Index`= 0. `hilog_arg(+Index, +Term, ?Argument)`-
*HiLog*

If`Term`is a Prolog term, it has the same behaviour as`arg/3`, but if`Term`is a proper HiLog term,`hilog_arg/3`unifies`Argument`with the argument of the Prolog representation of`Term`. Semantically,`Argument`is the argument to which the*HiLog functor*of`Term`is applied. The arguments of the`Term`are numbered from 1 upwards. An atomic term is taken to have arguments.Initially,

`Index`must be instantiated to a positive integer and`Term`to any non-variable Prolog or HiLog term. If the initial conditions are not satisfied or is out of range, the call quietly fails. Note that like`arg/3`this predicate does not succeed for`Index`=0.Examples:

| ?- hilog_arg(2, p(a,b), A). A = b | ?- hilog_arg(2, h(a,b), A). A = b | ?- hilog_arg(3, X(a,b,c), A). X = _595820 A = c | ?- hilog_arg(1, map(f)(a,b), A). A = a | ?- hilog_arg(2, map(f)(a,b), A). A = b | ?- hilog_arg(1, (a+b)(foo,bar), A). A = foo | ?- hilog_arg(1, apply(foo), A). A = foo | ?- hilog_arg(1, apply(foo,bar), A). A = bar

Note the difference between the last two examples. The difference is due to the fact that

`apply/1`is a Prolog term, while`apply/2`is a proper HiLog term. `?Term =.. [?Functor |?ArgList]`-

Succeeds when`Term`is any (Prolog or) HiLog term,`Functor`is its Prolog functor and`ArgList`is the list of its arguments. The use of`=../2`(pronounced*univ*) although convenient, can nearly always be avoided. Whenever efficiency is critical, it is advisable to use the predicates`functor/3`and`arg/3`, since`=../2`is implemented by calls to these predicates. The behaviour of`=../2`is as follows:- If initially
`Term`is uninstantiated, then the list in the second argument of`=../2`must be instantiated either to a*proper list*(list of determinate length) whose head is an atom, or to a list of length 1 whose head is a number. - If the arguments of
`=../2`are both uninstantiated, or if either of them is not what is expected,`=../2`aborts, producing an appropriate error message.

Examples:

| ?- X - 1 =.. L. X = _595692 L = [-,_595692,1] | ?- p(a,b,c) =.. L. L = [p,a,b,c] | ?- h(a,b,c) =.. L. L = [apply,h,a,b,c] | ?- map(p)(a,b) =.. L. L = [apply,map(p),a,b] | ?- T =.. [foo]. T = foo | ?- T =.. [3|X]. T = 3 X = [] | ?- T =.. [apply,X,a,b]. T = apply(X,a,b) | ?- T =.. [1,2]. ++Error: Wrong type(s) in argument 2 of =../2 Aborting... | ?- T =.. [a+b,2]. ++Error: Wrong type(s) in argument 2 of =../2 Aborting.. | ?- X =.. [foo|Y]. ++Error: Argument 2 of =../2 is not a proper list Aborting...

Exceptions:

`instantiation_error`- Argument 2 of
`=../2`is not a proper list. `type_error`- Head of argument 2 of
`=../2`is not an atom or number.

- If initially
`?Term ^ =.. [?F |?ArgList]`-
*HiLog*

When`Term`is a Prolog term, this predicate behaves exactly like the Prolog`=../2`. However when`Term`is a proper HiLog term,`^`

=../2`F`to its HiLog functor and`ArgList`to the list of the arguments to which this HiLog functor is applied. Like`=../2`, the use of`^`

=../2`hilog_functor/3`and`hilog_arg/3`. The behaviour of`^`

=../2- If initially
`Term`is uninstantiated, then the list in the second argument of`^`

=../2*proper list*(list of determinate length) whose head can be any Prolog or HiLog term. - If the arguments of
`^`

=../2`^`

=../2

| ?- p(a,b,c) ^=.. L. L = [p,a,b,c] | ?- h(a,b,c) ^=.. L. L = [h,a,b,c] | ?- map(p)(a,b) ^=.. L. L = [map(p),a,b] | ?- T ^=.. [X,a,b]. T = apply(X,a,b) | ?- T ^=.. [2,2]. T = apply(2,2) | ?- T ^=.. [a+b,2]. T = apply(a+b,2) | ?- T ^=.. [3|X]. ++Error: Argument 2 of ^=../2 is not a proper list Aborting...

Exceptions:

`instantiation_error`- Argument 2 of
`^`

=../2

- If initially
`copy_term(+Term, -Copy)`-

Makes a`Copy`of`Term`in which all variables have been replaced by brand new variables which occur nowhere else. It can be very handy when writing (meta-)interpreters for logic-based languages. The version of`copy_term/2`provided is*space efficient*in the sense that it never copies ground terms. Predicate`copy_term/2`has no associated errors or exceptions.Examples:

| ?- copy_term(X, Y). X = _598948 Y = _598904 | ?- copy_term(f(a,X), Y). X = _598892 Y = f(a,_599112)

`name(?Constant, ?CharList)`-

The standard predicate`name/2`performs the conversion between a constant and its character list representation. If`Constant`is supplied (and is any atom or number),`CharList`is unified with a list of ASCII codes representing the*``name''*of the constant. In that case,`CharList`is exactly the list of ASCII character codes that appear in the printed representation of`Constant`. If on the other hand`Constant`is a variable, then`CharList`must be a proper list of ASCII character codes. In that case,`name/2`will convert a list of ASCII characters that can represent a number to a number rather than to a character string. As a consequence of this, there are some atoms (for example`'18'`

) which cannot be constructed by using`name/2`. If conversion to an atom is preferred in these cases, the standard predicate`atom_codes/2`should be used instead. The syntax for numbers that is accepted by`name/2`is exactly the one which`read/1`accepts. Predicate`name/2`is provided for backwards compatibility. It is advisable that new programs use the predicates`atom_codes/2`and`number_codes/2`described below.In Version 2.2 predicate

`name/2`is not yet implemented for converting from a real number to its character list representation, and if the representation of a real is provided as`CharList`, it will be converted to an atom.If both of the arguments of

`name/2`are uninstantiated or`CharList`is not a proper list of ASCII characters,`name/2`will abort and an error message will be sent to the standard error stream.Examples:

| ?- name('Foo', L). L = [70,111,111] | ?- name([], L). L = [91,93] | ?- name(431, L). L = [52,51,49] | ?- name(X, [102,111,111]). X = foo | ?- name(X, []). X = '' | ?- name(X, "Foo"). X = 'Foo' | ?- name(X, [52,51,49]). X = 431 | ?- name(X, [45,48,50,49,51]), integer(X). X = -213 | ?- name(3.14, L). ++Error: Predicate name/2 for reals is not implemented yet Aborting...

Exceptions:

`instantiation_error`- Both arguments are uninstantiated, or argument 2 of
`name/2`contains a variable or is not a proper list. `type_error``Constant`is not a variable, an atom or a number.`range_error``CharList`is not a list of ASCII characters.`implementation_error``Constant`is a real number (conversion from a real to its character list representation is not implemented yet).

`atom_codes(?Atom, ?CharCodeList)`-

The standard predicate`atom_codes/2`performs the conversion between an atom and its character list representation. If`Atom`is supplied (and is an atom),`CharList`is unified with a list of ASCII codes representing the*``name''*of that atom. In that case,`CharList`is exactly the list of ASCII character codes that appear in the printed representation of`Atom`. If on the other hand`Atom`is a variable, then`CharList`must be a proper list of ASCII character codes. In that case,`Atom`is instantiated to an atom containing exactly those characters, even if the characters look like the printed representation of a number.If both of the arguments of

`atom_codes/2`are uninstantiated or`CharList`is not a proper list of ASCII characters,`atom_codes/2`aborts, and an error message will be sent to the standard error stream.Examples:

| ?- atom_codes('Foo', L). L = [70,111,111] | ?- atom_codes([], L). L = [91,93] | ?- atom_codes(X, [102,111,111]). X = foo | ?- atom_codes(X, []). X = '' | ?- atom_codes(X, "Foo"). X = 'Foo' | ?- atom_codes(X, [52,51,49]). X = '431' | ?- atom_codes(X, [52,51,49]), integer(X). no | ?- atom_codes(X, [52,Y,49]). ! Instantiation error in argument 2 of atom_codes/2 ! Aborting... | ?- atom_codes(431, L). ! Type error: in argument 1 of atom_codes/2 ! atom expected, but something else found ! Aborting... | ?- atom_codes(X, [52,300,49]). ! Range error: in argument 2 of atom_codes/2 ! ASCII code expected, but 300 found ! Aborting...

Exceptions:

`instantiation_error`- Both arguments are uninstantiated, or argument 2 is not a proper list, or it contains a variable.
`type_error``Atom`is not a variable or an atom.`range_error``CharList`is not a list of ASCII characters.

`atom_chars(?Number, ?CharAtomList)`-

Like`atom_codes`

, but the list returned (or input) is a list of characters*as atoms*rather than ASCII codes. For instance,`atom_chars(abc,X)`

binds`X`to the list`[a,b,c]`instead of`[97,98,99]`. `number_codes(?Number, ?CharCodeList)`-

The standard predicate`number_codes/2`performs the conversion between a number and its character list representation. If`Number`is supplied (and is a number),`CharList`is unified with a list of ASCII codes comprising the printed representation of that`Number`. If on the other hand`Number`is a variable, then`CharList`must be a proper list of ASCII character codes that corresponds to the correct syntax of a number (either integer or float) In that case,`Number`is instantiated to that number, otherwise`number_codes/2`will simply fail.If both of the arguments of

`number_codes/2`are uninstantiated or`CharList`is not a proper list of ASCII characters,`number_codes/2`aborts, and an error message will be sent to the standard error stream.Examples:

| ?- number_codes(123, L). L = [49,50,51]; | ?- number_codes(N, [49,50,51]), integer(N). N = 123 | ?- number_codes(31.4e+10, L). L = [51,46,49,51,57,57,57,55,69,43,49,48] | ?- number_codes(N, "314e+8"). N = 3.14e+10 | ?- number_codes(foo, L). ! Type error: in argument 1 of number_codes/2 ! number expected, but something else found ! Aborting...

Exceptions:

`instantiation_error`- Both arguments are uninstantiated, or argument 2 is not a proper list, or it contains a variable.
`type_error``Number`is not a variable or a number.`range_error``CharList`is not a list of ASCII characters.

`number_chars(?Number, ?CharAtomList)`-

Like`number_codes`

, but the list returned (or input) is a list of characters*as atoms*rather than ASCII codes. For instance,`number_chars(123,X)`

binds`X`to the list`['1','2','3']`instead of`[49,50,51]`. `number_digits(?Number, ?DigitList)`-

Like`number_chars`

, but the list returned (or input) is a list of digits*as numbers*rather than ASCII codes (for floats, the atom '.', '+' or '-', and 'e' will also be present in the list). For instance,`number_digits(123,X)`

binds`X`to the list`[1,2,3]`instead of`['1','2','3']`, and`number_digits(123.45,X)`

binds`X`to`[1,.,2,3,4,5,0,0,e,+,0,2]`.