How to use SWI-Prolog ./2 function?

坚强是说给别人听的谎言 提交于 2019-11-28 14:10:57

In standard Prolog, the '.' functor is the actual list term functor. Specifically, [H|T] is equivalent to '.'(H, T). If you run GNU Prolog, for example, you will get this:

| ?- write_canonical([H|T]).
'.'(_23,_24)

yes
| ?- X = .(H,T).

X = [H|T]

yes
| ?-

The is/2 operator will allow you to read the character code directly from a list consisting of a single character code. So the following works in Prolog:

| ?- X is [97].

X = 97

yes
| ?- X is .(97,[]).

X = 97

yes

Where it starts to get interesting is that, in SWI Prolog, they've introduced dictionaries that rely on the '.' as a means of designating dictionary keys. This creates a conflict with the '.' functor being used as a list functor. This is explained in the link on dictionaries. Thus, when you attempt to use the '.' functor for a list, you get something like this:

1 ?- X is [97].
X = 97.

2 ?- X is .(97, []).
ERROR: Type error: `dict' expected, found `97' (an integer)
ERROR: In:
ERROR:   [11] throw(error(type_error(dict,97),_5184))
ERROR:    [9] '$dicts':'.'(97,[],_5224) at /usr/local/lib/swipl-7.4.2/boot/dicts.pl:46
ERROR:    [8] '<meta-call>'(user:(...,...)) <foreign>
ERROR:    [7] <user>
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.

3 ?- X = .(H,T).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR:   [11] throw(error(instantiation_error,_6914))
ERROR:    [9] '$dicts':'.'(_6944,_6946,_6948) at /usr/local/lib/swipl-7.4.2/boot/dicts.pl:46
ERROR:    [8] '<meta-call>'(user:(...,...)) <foreign>
ERROR:    [7] <user>
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.

SWI has, therefore, defined another functor, [|], to serve the purpose that '.' traditionally served, which is the list functor.

4 ?- X is '[|]'(97, []).
X = 97.

5 ?- X = '[|]'(H, T).
X = [H|T].

6 ?-

Oddly, you might think then that this would happen:

7 ?- write_canonical([H|T]).
'[|]'(_, _)

However, what happens is this:

7 ?- write_canonical([H|T]).
[_|_]
true.

So to SWI Prolog, the list representation [H|T] is already the canonical representation of the list.

The arithmetic function '.'/2 maps lists holding a single character or character code (terms like [C] or '.'(C,[])) to the corresponding character code.

The particular irratic behavior that you were observing is SWI-Prolog specific. You can disable the non-standard SWI-Prolog "extensions" (like dicts) by adding the command-line argument --traditional, like so:

$ swipl --traditional
Welcome to SWI-Prolog (threaded, 64 bits, version 8.0.0) [...]

?- C = 97, V is [C].
C = 97, V = 97.

?- C = 0'a, V is [C].
C = 97, V = 97.

?- C = a, V is [C].
C = a, V = 97.

This also works with string literals:

:- set_prolog_flag(double_quotes, codes).
?- Str = "a", Str = [C], V is Str.
Str = [97], C = 97, V = 97.

:- set_prolog_flag(double_quotes, chars).
?- Str = "a", Str = [C], V is Str.
Str = [a], C = a, V = 97.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!