동적 절 관리
동적 절 관리
동적(dynamic) 프로시저의 절을 추가·제거·검사하는 술어들을 설명해요.
본문
소개
정적 및 동적 프로시저: 프로시저는 동적이거나 정적이에요. 모든 내장 술어는 정적이에요. 사용자 정의 프로시저는 그 정의 앞에 dynamic/1 지시자(7.1.2절)가 있지 않으면 기본적으로 정적이에요. 존재하지 않는 프로시저에 절을 추가하면 동적 프로시저가 만들어져요. 동적 프로시저의 절은 변경할 수 있어요(예: asserta/1 사용), 정적 프로시저의 절은 변경할 수 없어요.
비공개 및 공개 프로시저: 각 프로시저는 공개(public)이거나 비공개(private)예요. 동적 프로시저는 항상 공개예요. 모든 내장 술어는 비공개이며, 정적 사용자 정의 프로시저는 그 정의 앞에 public/1 지시자(7.1.3절)가 있지 않으면 기본적으로 비공개예요. 동적 선언이 존재하면 public 선언을 추가할 필요가 없어요. 동적 프로시저는 공개이기 때문이에요. 공개 프로시저의 절은 검사할 수 있어요(예: clause/2 사용), 비공개 프로시저의 절은 검사할 수 없어요.
논리적 데이터베이스 갱신 관점: 목표를 실행한 결과로 발생하는 데이터베이스의 어떤 변경(예: 하위 목표가 assertz/1 또는 retract/1의 호출일 때)은 이후의 활성화에만 영향을 줘요. 그 변경은 현재 실행 중인 어떤 활성화에도 영향을 주지 않아요. 따라서 목표 실행 중 데이터베이스는 동결되고, 술어를 정의하는 절의 목록은 그 실행 순간에 고정돼요.
asserta/1, assertz/1
Templates
asserta(+clause)
assertz(+clause)
Description
asserta(Clause)는 먼저 항 Clause를 절로 변환한 다음 현재 내부 데이터베이스에 추가해요. 관련 술어는 동적(8.7.1절)이거나 정의되지 않아야 하며, 절은 술어의 첫 번째 절 앞에 삽입돼요. 술어가 정의되지 않았다면 동적 프로시저로 생성돼요.
assertz(Clause)는 관련 술어의 모든 기존 절 끝에 절이 추가된다는 점만 제외하면 asserta/1처럼 동작해요.
항 Clause를 절 Clause1로 변환:
Clause의 머리와 본문을 추출:Clause = (Head :- Body)또는Clause = Head이고Body = true.Head는 callable 항이어야 함(그렇지 않으면 변환 실패).Body를 본문 절(즉 목표)Body1로 변환.- 변환된 절
Clause1 = (Head :- Body1).
항 T를 목표로 변환:
- T가 변수이면
call(T)항으로 대체. - T가 제어 구조(
','/2,;/2,->/2)이면 제어 구조의 각 인자를 재귀적으로 목표로 변환. - T가 callable 항이면 그대로 유지.
- 그렇지 않으면 변환 실패(T가 변수도 callable 항도 아님).
Errors
Head가 변수 -instantiation_errorHead가 변수도 callable 항도 아님 -type_error(callable, Head)Body를 목표로 변환할 수 없음 -type_error(callable, Body)Head의 술어 표시자Pred가 정적 프로시저의 것임 -permission_error(modify, static_procedure, Pred)
Portability: ISO 술어.
retract/1
Templates
retract(+clause)
Description
retract(Clause)는 Clause와 통일되는 데이터베이스의 첫 번째 절을 지워요. 관련 술어는 동적 프로시저(8.7.1절)여야 해요. 프로시저의 모든 절을 제거해도 프로시저 정의는 지워지지 않아요. 이를 달성하려면 abolish/1(8.7.6절)을 사용해요. retract/1는 백트래킹 시 재실행 가능해요.
Errors
Head가 변수 -instantiation_errorHead가 변수도 callable 항도 아님 -type_error(callable, Head)Head의 술어 표시자Pred가 정적 프로시저의 것임 -permission_error(modify, static_procedure, Pred)
Portability: ISO 술어. ISO 참조에서 permission_error와 연관된 연산은 access이지만 GNU Prolog에서는 modify예요. asserta/1(retract/1과 취지가 비슷한)의 경우 연산도 modify이므로 이것은 ISO 참조의 오류로 보여요.
retractall/1
Templates
retractall(+head)
Description
retractall(Head)는 머리가 Head와 통일되는 모든 절을 지워요. 관련 술어는 동적 프로시저(8.7.1절)여야 해요. 프로시저 정의는 제거되지 않으므로 current_predicate/1(8.8.1절)로 찾을 수 있어요. 프로시저를 제거하려면 abolish/1을 사용해야 해요(8.7.6절).
Errors
Head가 변수 -instantiation_errorHead가 callable 항이 아님 -type_error(callable, Head)Head의 술어 표시자Pred가 정적 프로시저의 것임 -permission_error(modify, static_procedure, Pred)
Portability: ISO 술어.
clause/2
Templates
clause(+head, ?callable_term)
Description
clause(Head, Body)는 데이터베이스에 Head :- Body와 통일되는 절이 있으면 성공해요. 해당 술어는 공개 프로시저(8.7.1절)여야 해요. 절은 첫 번째부터 마지막까지 전달돼요. 이 술어는 백트래킹 시 재실행 가능해요.
Errors
Head가 변수 -instantiation_errorHead가 변수도 callable 항도 아님 -type_error(callable, Head)Head의 술어 표시자Pred가 비공개 프로시저의 것임 -permission_error(access, private_procedure, Pred)Body가 변수도 callable 항도 아님 -type_error(callable, Body)
Portability: ISO 술어.
abolish/1
Templates
abolish(+predicate_indicator)
Description
abolish(Pred)는 술어 표시자가 Pred인 프로시저를 데이터베이스에서 제거해요. 관련 술어는 동적 프로시저(8.7.1절)여야 해요.
Errors
Pred가 변수 -instantiation_errorPred가Name/Arity항이고Name또는Arity가 변수 -instantiation_errorPred가 변수도 술어 표시자도 아님 -type_error(predicate_indicator, Pred)Pred가Name/Arity항이고Arity가 변수도 정수도 아님 -type_error(integer, Arity)Pred가Name/Arity항이고Name이 변수도 원자도 아님 -type_error(atom, Name)Pred가Name/Arity항이고Arity가 정수 < 0 -domain_error(not_less_than_zero, Arity)Pred가Name/Arity항이고Arity가max_arity플래그(8.22.1절)보다 큰 정수 -representation_error(max_arity)- 술어 표시자
Pred가 정적 프로시저의 것임 -permission_error(modify, static_procedure, Pred)
Portability: ISO 술어.