我知道这一点var/1,nonvar/1并且!/0是不纯的基元,但它们的使用是否会使每个使用它们的程序都不纯净?
我写了下面的谓词plus/3,表现得好像是纯粹的,或者至少是我声称的那样.谓词是示范性的,不是为了提高效率.
% nat(X) is true if X is a natural number
nat(0).
nat(X):- nonvar(X), !, X > 0.
nat(X):- nat(X1), X is X1 + 1.
% plus(A, B, C) is true if A,B and C are natural numbers and A+B=C
plus(A, B, C):-
nat(A),
(nonvar(C), C < A, !, false ; true),
plus_(B, A, C).
plus_(A, B, C):-
nat(A),
(nonvar(C), C < A, !, false ; true),
C1 is …Run Code Online (Sandbox Code Playgroud) 这个问题
我有一个与逻辑纯度有关的问题.
这个节目是纯粹的吗?
when(ground(X), X > 2).
Run Code Online (Sandbox Code Playgroud)
关于上下文的一些[ir]相关细节
我正在尝试编写具有良好终止属性的纯谓词.例如,我想编写一个list_length/2描述列表与其长度之间关系的谓词.我想实现与内置谓词相同的终止行为length/2.
我的问题试图找出以下谓词是否纯粹:
list_length([], 0).
list_length([_|Tail], N):-
when(ground(N), (N > 0, N1 is N - 1)),
when(ground(N1), N is N1 + 1),
list_length(Tail, N1).
Run Code Online (Sandbox Code Playgroud)
我可以用clpfd实现我的目标......
:- use_module(library(clpfd)).
:- set_prolog_flag(clpfd_monotonic, true).
list_length([], 0).
list_length([_|Tail], N):-
?(N) #> 0,
?(N1) #= ?(N) - 1,
list_length(Tail, N1).
Run Code Online (Sandbox Code Playgroud)
......或者我可以使用var/1,nonvar/1并且!/0,后来是很难证明谓词是纯粹的.
list_length([],0).
list_length([_|Tail], N):-
nonvar(N), !,
N > 0,
N1 is N - 1,
list_length(Tail, …Run Code Online (Sandbox Code Playgroud) 我正在为日期和时间构建解析器和生成器.在普通的编程语言中,这些将分开编写.在Prolog + CLP(FD)中我可以编写1个谓词同时执行这两个操作:-)
在我的用例中,解析多个数字并将其转换为整数或根据给定的整数生成多个数字通常是有意义的.
我的问题是,clpfd:run_propagator/2在实例化个别数字时不会调用,尽管我的声明使用了clpfd:init_propagator/2.有没有办法做到这一点,还是我在定义中犯了错误clpfd_digits/2?
在SWI-Prolog中实施的代码:
:- use_module(library(apply)).
:- use_module(library(clpfd)).
:- multifile(clpfd:run_propagator/2).
day(D) --> {clpfd_digits(D, [D1,D2])}, digit(D1), digit(D2).
digit(D) --> [C], {code_type(C, digit(D))}.
clpfd_digits(N, Ds):-
clpfd:make_propagator(clpfd_digits(N, Ds), Prop),
clpfd:init_propagator(N, Prop),
clpfd:init_propagator(Ds, Prop),
forall(
member(D, Ds),
clpfd:init_propagator(D, Prop)
),
clpfd:trigger_once(Prop).
clpfd:run_propagator(clpfd_digits(N, Ds), MState):-
( maplist(is_digit0, Ds)
-> clpfd:kill(MState),
digits_to_nonneg(Ds, N)
; integer(N)
-> clpfd:kill(MState),
nonneg_to_digits(N, Ds)
; true
).
digits_to_nonneg([], 0):- !.
digits_to_nonneg(Ds, N):-
maplist(char_weight, Chars, Ds),
number_chars(N, Chars).
char_weight(Char, D):-
char_type(Char, digit(D)).
nonneg_to_digits(0, []):- …Run Code Online (Sandbox Code Playgroud) 假设我想表示这样的整数:integer:Sign:[FirstDigit,SecondDigit,...].例如,42表示为integer:positive:[4,2].
我需要一个谓词,它根据这个表示生成整数的值,反之亦然.
这是我想出的:
integer_value_('integer':Sign:[H],E) :-
H in 0..9,
(
Sign = 'positive',
E #= H
;
Sign = 'negative',
E #= -H
).
integer_value_('integer':Sign:[H,I|T],E) :-
H in 0..9,
length([I|T],L),
(
Sign = 'positive',
E #= F + H * 10^L
;
Sign = 'negative',
E #= F - H * 10^L
),
integer_value_('integer':Sign:[I|T],F).
Run Code Online (Sandbox Code Playgroud)
这按预期工作.然而,它具有接受诸如integer:positive:[0,1]在列表开头的前导零之类的事情的不幸特性.当我使用integer_value_(I,J), label([J]).以下列举所有可能的整数时,这尤其成问题:带有前导零的那些也会出现.
然后,我试图通过integer_value_仅使用除第一个数字之外的所有数据来解决这个问题,并使用integer_value第一个数字(请记住,我们需要容纳0表示只包含0的列表):
integer_value('integer':Sign:[H],E) :-
abs(E) #< 10,
abs(E) #> -1,
integer_value_('integer':Sign:[H],E).
integer_value('integer':Sign:[H,I|T],E) :-
H …Run Code Online (Sandbox Code Playgroud)