自然语言处理/命令(prolog)

时间:2013-12-16 03:03:53

标签: command prolog nlp

我想创建一个谓词,它识别一个单词(在本例中为“save”)并开始保存下一个单词,直到符号/单词“end”出现。

它应该像这样工作:

?- save.
one
two
end
true.

保存的谓词:

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

然后我就这样开始了:

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

问题是,我可以添加尽可能多的单词,但如果我想用“结束”停止命令,程序就会失败,实际上这些单词还没有被保存。

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

2 个答案:

答案 0 :(得分: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,这是一个系统谓词。所有这一切都是从用户读取一个单词(以句点结束!)并注意它不是单词“save”。不幸的是,在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声明,这会提高可移植性并提高可读性。

答案 1 :(得分: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.