2013-12-16 134 views
2

我想创建一个谓词,它识别一个单词(在这种情况下:“保存”)并开始保存下一个单词,直到符号/单词“end”到来。自然语言处理/命令(序言)

它应该是这样的:

?- save. 
one 
two 
end 
true. 

保存谓词:

save(X) :- assert(listitem(X)). 

,然后我就开始这样的:

save :- read(save). 
read:- X -> save(X). 
end --> 'end'. 

的问题是,我可以根据需要添加尽可能多的单词,但是如果我想用“结束”来停止命令,则程序失败,实际上单词有没有被保存。

谓词的哪部分是错误的?我很乐意提供一些帮助。 提前谢谢!

+0

,如果你想输入单词 “结束” 你会做什么?你如何去告诉它除了结束“结束”? – 2013-12-16 07:40:20

回答

3

这是一些非常混乱的代码。这里是你想要的东西:

:- dynamic listitem/1. 

readline(Line) :- 
    % this is an SWI extension, but it's very handy 
    read_line_to_codes(user, Codes), 
    atom_codes(Line, Codes). 

save :- 
    readline(X), 
    (X \= end -> (assertz(listitem(X)), save) 
      ; true). 

赔率是好的,在什么地方你没带的代码,你失踪是; true的效果有:当你发现end,你就完蛋了,但不是你失败了。但这里有很多问题。

  1. save/0调用read/1,这是一个系统谓词。所有这一切都是从用户那里读取一个字(以一段时间结束!),并注意它不是“保存”一词。不幸的是,在最后没有句点的情况下阅读整行文本在Prolog中是一个不太重要的任务,因此在我的解决方案中有一堆代码。
  2. read/0不被任何东西调用。
  3. 语法X -> save(X)几乎肯定不是你想要的。这是谓词中第一次出现X,因此在它有价值之前有条件地测试它可能并不是很好。
  4. end --> 'end'.是一个DCG规则,但您没有在任何地方使用phrase/2来调用它(您也不是直接使用end/2与差异列表)。
  5. assert/1是一个非常不好的习惯。 ISO预测文件asserta/1assertz/1不仅便于携带,而且还可以让读者更好地了解对事实数据库的影响。
  6. 同样,您没有dynamic声明listitem/1,这将提高可移植性并提高可读性。
+0

一个很好的答案(+1),但是我有一种感觉,它比'read'谓词家族更清洁,不需要'read_line_to_codes'和'atom_codes'。 – 2013-12-16 07:38:56

+0

用户不需要用句点结束句子吗?这将改变需求。 –

+0

是的,但我真的怀疑那些石头是否成立......类似于@CapelliC – 2013-12-16 15:00:58

1

我会使用'状态机'的方法:它很简单!

:- dynamic listitem/1. 

loop(Mode) :- read(W), loop(Mode, W). 

loop(_, stop). 
loop(skip, save) :- loop(save). 
loop(skip, _) :- loop(skip). 
loop(save, W) :- assertz(listitem(W)), loop(save). 

测试:

1 ?- loop(skip). 
|: asd. 
|: save. 
|: ok. 
|: ok1. 
|: stop. 
true 
. 

2 ?- listing(listitem). 
:- dynamic stackoverflow:listitem/1. 

stackoverflow:listitem(ok). 
stackoverflow:listitem(ok1). 

true.