使用string_to_atom时出错:参数未充分实例化。

3

我正在使用Prolog编写URI解析器,但目前我被一个更简单的问题卡住了。我需要检查一个字符串是否包含特定字符“:”,如果有,我希望得到该字符之前的所有字符组成的字符串。

这是我的程序:

% caratteri speciali
colonCheck(S) :-
   string_to_atom([S], C),
   C = ':'.                        % S==:

headGetter([H|T], [H]) :-
   !.

% struttura uri
uri(Scheme, Userinfo, Host, Port, Path, Query, Fragment).

% parsing uri
parsed_uri(UriInput, uri(Scheme,Userinfo,Host,Port,Path,Query,Fragment)) :-
   scheme(UriInput, uri(S,Userinfo,Host,Port,Path,Query,Fragment)),
   not(headGetter(UriInput, ':')),
   !,
   string_to_atom([S], Scheme).

% controllo Scheme, in ingresso ho i dati da controllare e l'oggetto uri che 
% mi servirà per inviarlo al passaggio successivo ho trovato i due punti
scheme([H|T], uri(Scheme,Userinfo,Host,Port,Path,Query,Fragment)):-
   colonCheck(H),
   !,
   end(Scheme).
% non trovo i due punti e procedo a controllare il prossimo carattere
% (la testa dell'attuale coda)
scheme([H|T], uri(Scheme,Userinfo,Host,Port,Path,Query,Fragment)):-
   not(colonCheck(H)),
   scheme(T, uri(This, Userinfo,Host,Port,Path,Query,Fragment)),
   append([H], This, Scheme).

%fine computazione
end([S]).

给出这个结果:
?- scheme("http:", uri(A,_,_,_,_,_,_)).
A = [104, 116, 116, 112, _G1205].

我认为这部分是正确的,但现在我想将字符列表转换为字符串,因此我将最后一行更改为:

end([S]) :-
   string_to_atom([S], K).

但是我收到了这个错误信息:

错误:string_to_atom/2:参数未充分实例化

我可能漏掉了什么。你能告诉我是什么吗?


请注意,在您的“terminal”子句scheme/2end(Scheme)中,end/1规则会创建一个自由变量。如果这是您想要的,那么可以,但似乎正是这个自由变量导致了调用string_to_atom/2时出现错误。另外,最好指定您正在使用哪个Prolog,以便讨论任何可能存在的怪癖。 - hardmath
如果你使用以下代码会发生什么: end([S]) :- print(S) - NotAUser
这就是 SWI Prolog 显示自由变量 _Gnnnn 的方式。我认为如上所述,这是通过调用 end/1 来绑定你在解析 URI 时的终端情况中的 Scheme 所致。该调用成功地将一个自由变量 S 绑定到你的字符代码字符串/列表的最后一个条目中。因此,我想问一下,在字符代码字符串/列表的结尾是否真的需要这个自由变量。 - hardmath
可能你真正想要的是 end([ ]),也就是用一个空的尾部来完成列表? - hardmath
2
headGetter在Prolog中不存在,请注意! - CapelliC
显示剩余4条评论
1个回答

0
在Prolog中,字符串只是字符代码的列表,因此您可以大大简化代码:请考虑。
?- S = "http:/example.com", append(L, [0':|R], S), format('~s and ~s~n', [L,R]).

将输出

http and /example.com
S = [104, 116, 116, 112, 58, 47, 101, 120, 97|...],
L = [104, 116, 116, 112],
R = [47, 101, 120, 97, 109, 112, 108, 101, 46|...] .

colonCheck/1、headGetter/2和end/1是无用的,我认为在任何语言中都是不好的风格,特别是在声明性语言中,引入不必要的符号。

如果你需要解析结构化数据,DCG会提供更好的支持:

?- phrase((seq(L),":",seq(R)), "http:/example.com", []),format('~s and ~s~n', [L,R]).

在哪里

seq([]) --> [].
seq([C|Cs]) --> [C], seq(Cs).

将输出与上述相同,即:

http and /example.com
L = [104, 116, 116, 112],
R = [47, 101, 120, 97, 109, 112, 108, 101, 46|...] .

底线:将scheme/2替换为

scheme(Url, uri(Scheme, _Userinfo, _Host, _Port, _Path, _Query, _Fragment)) :-
    append(Scheme, [0':|_], Url).

然后你会得到

?- scheme("http:", uri(A,_,_,_,_,_,_)).
A = [104, 116, 116, 112]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接