问题
I can't get this Prolog DCG code working:
String1=" ",string_codes(String1,Codes),phrase(spaces(Output),Codes).
spaces(XXs) -->
[X], {X=32}, spaces(Xs),
{char_code(Ch,X), atom_concat(Ch,Xs,XXs)}, !. %%Space
spaces([]) --> [].
回答1:
I solved this by changing [] in the base case to ''.
spaces(XXs) -->
[X], {X=32}, spaces(Xs),
{char_code(Ch,X), atom_concat(Ch,Xs,XXs)}, !. %% Space
spaces('') --> [].
String1 = " ",
Codes = [32, 32, 32],
Output = ' '.
回答2:
I feel like an improved solution would probably be something like this:
spaces(Spaces) --> " ", spaces(S0), { atom_concat(' ', S0, Spaces) }.
spaces('') --> [].
There's no real need to ask what the char is for code 32, you know it's a space. Also, [X], {X=32}
from your answer is better as [32]
, which is still better as " "
.
回答3:
If you are doing DCG and using SWI-Prolog there is a library of often used predicates and DCG clauses in dcgbasics. This can be used in code with
:- use_module(library(dcg/basics)).
To list the code for the predicates use listing/1, e.g.
?- listing(dcg_basics:_).
The library has a DCG clause blanks//0
that does what you want, e.g.
?- listing(dcg_basics:blanks).
blanks(A, B) :-
blank(A, C),
!,
D=C,
blanks(D, B).
blanks(A, A).
true.
?- listing(dcg_basics:blank).
blank([C|A], B) :-
nonvar(C),
code_type(C, space),
B=A.
true.
which as DCG is
blank -->
[C],
{
nonvar(C),
code_type(C,space)
}.
blanks -->
blank, !, blanks.
blanks --> [].
NB
The library version uses character codes
and not characters
.
?- string_codes("",Codes),phrase(blanks,Codes,Rest).
Codes = Rest, Rest = [].
?- string_codes(" ",Codes),phrase(blanks,Codes,Rest).
Codes = [32],
Rest = [].
?- string_codes(" ",Codes),phrase(blanks,Codes,Rest).
Codes = [32, 32],
Rest = [].
?- string_codes(" ",Codes),phrase(blanks,Codes,Rest).
Codes = [32, 32, 32],
Rest = [].
来源:https://stackoverflow.com/questions/54374105/i-cant-get-my-prolog-dcg-working-with-atom-concat