2013-12-16 2 views
2

단어 (이 경우 "저장")를 인식하고 단어/기호 "끝"이 오기 전까지 다음 단어 저장을 시작하는 조건자를 만들고 싶습니다.자연 언어 처리/명령 (프롤로그)

그것은 다음과 같이 작동합니다은 :

?- save. 
one 
two 
end 
true. 

저장하기위한 조건 :

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

문제가있다 내가 할 수있는 것을 :

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

과는 I는 다음과 같이 시작 원하는만큼 단어를 추가하십시오. 그러나 "끝"으로 명령을 중단하려면 프로그램이 실패하고 실제로 단어가 있습니다. 구원받지 못했습니다.

술어의 어떤 부분이 잘못 되었습니까? 나는 약간의 도움에 매우 만족할 것이다. 미리 감사드립니다.

+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을 호출합니다. 이 모든 일은 사용자로부터 단어를 읽는 것입니다 (마침표로 끝나야합니다). 단어 "저장"이 아니라는 것을 알 수 있습니다. 불행히도, 끝 부분에 마침표가없는 전체 줄을 읽는 것은 Prolog에서 다소 중요하지 않은 작업이므로 내 솔루션에 코드 더미가 있습니다.
  2. read/0은 아무것도 호출하지 않습니다.
  3. X -> save(X) 구문은 거의 확실하게 원하지 않습니다. 이것은 술어에서 X의 첫 x 째 _ 생이며, 값을 가지기 전에 조건부로 테스트하는 것이 좋지는 않을 것입니다.
  4. end --> 'end'.은 DCG 규칙이지만 어느 곳에서나 phrase/2을 사용하지 않으며 차이점 목록과 함께 end/2을 직접 사용하지 않습니다.
  5. assert/1으로 들어가는 것은 정말 나쁜 습관입니다. ISO 조건부 asserta/1assertz/1은 이식 가능할뿐만 아니라 사실 데이터베이스에 미치는 영향에 대해 독자에게 더 잘 알립니다.
  6. 마찬가지로 listitem/1에 대한 dynamic 선언이 없으므로 이식성이 향상되고 가독성이 향상됩니다.
+0

좋은 대답 (+1)이지만'read_line_to_codes'와'atom_codes'가 필요없이'read' 계열의 술어로 더 깨끗해 졌다고 느낍니다. –

+0

사용자는 마침표가있는 행을 끝내야합니까? 그것은 요구 사항을 변경합니다. –

+0

예, 그렇습니다. 저는 그러한 것들이 돌에 놓여 있음을 정말로 의심합니다 .... @CapelliC –

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. 
관련 문제