gpt4 book ai didi

prolog - 在 Prolog 中定义 "let expressions"

转载 作者:行者123 更新时间:2023-12-03 16:20:11 25 4
gpt4 key购买 nike

在许多函数式编程语言中,可以使用 let 来“重新定义”局部变量。表达:

let example = 
let a = 1 in
let a = a+1 in
a + 1
我找不到用于此目的的内置 Prolog 谓词,因此我尝试定义 let以这种方式表达:
:- initialization(main).
:- set_prolog_flag(double_quotes, chars).

replace(Subterm0, Subterm, Term0, Term) :-
( Term0 == Subterm0 -> Term = Subterm
; var(Term0) -> Term = Term0
; Term0 =.. [F|Args0],
maplist(replace(Subterm0,Subterm), Args0, Args),
Term =.. [F|Args]
).

let(A,B) :-
((D,D1) = (A1 is B1,C is B1);
(D,D1) = (A1=B1,C=B1)),
subsumes_term(D,A),
D=A,
replace(A1,C,B,B2),
call((D1,B2)).

main :- let(A = 1,(
writeln(A),
let(A is A+1,(
writeln(A),
let(A is A * 2,(
writeln(A)
))
))
)).
此实现似乎不正确,因为某些变量在被替换之前已绑定(bind)。我想定义一个允许同时“重新定义”多个变量的表达式:
main :- let((A = 1, B = 2), % this will not work with the let/2 predicate that I defined
let((A=B,B=A),(
writeln(A),
writeln(B)
))
).
是否可以实现 let以允许同时重新定义多个变量的方式表达?

最佳答案

定义 let 的问题作为一个正常的谓词,你不能重新定义出现在最外面的变量 let .这是我尝试使用目标扩展的更正确版本。 (对我来说这是有道理的,因为据我所知,在类似 lisp 的语言中,let 不能定义为函数,但可以定义为宏。)

%goal_expansion(let(Decl,OriginalGoal),Goal) :- %% SWI syntax
goal_expansion(let(Decl,OriginalGoal), _M, _, Goal, []) :- %%SICStus syntax
!,
expand_let(Decl,OriginalGoal,Goal).

expand_let(X, OriginalGoal, Goal) :-
var(X),
!,
replace(X,_Y,OriginalGoal,NewGoal),
Goal=(true,NewGoal).
expand_let(X is Decl, OriginalGoal, Goal) :-
var(X),
!,
replace(X,Y,OriginalGoal,NewGoal),
Goal=(Y is Decl,NewGoal).
expand_let(X = Decl, OriginalGoal, Goal) :-
var(X),
!,
replace(X,Y,OriginalGoal,NewGoal),
Goal=(Y = Decl,NewGoal).
expand_let([],OriginalGoal, Goal) :-
!,
Goal=OriginalGoal.
expand_let([L|Ls],OriginalGoal, Goal) :-
!,
expand_let_list([L|Ls],OriginalGoal,InitGoals,NewGoal),
Goal=(InitGoals,NewGoal).
expand_let((L,Ls),OriginalGoal, Goal) :-
!,
expand_let(Ls,OriginalGoal, SecondGoal),
expand_let(L,SecondGoal, Goal).

expand_let_list([],Goal,true,Goal).
expand_let_list([L|Ls],OriginalGoal,(Init,InitGoals),NewGoal):-
(
var(L)
->
replace(L,_,OriginalGoal,SecondGoal),
Init=true
;
L=(X=Decl)
->
replace(X,Y,OriginalGoal,SecondGoal),
Init=(Y=Decl)
;
L=(X is Decl)
->
replace(X,Y,OriginalGoal,SecondGoal),
Init=(Y is Decl)
),
expand_let_list(Ls,SecondGoal,InitGoals,NewGoal).
这是重用 replace/4问题中定义的谓词。另请注意,钩子(Hook)谓词在 Prolog 版本之间有所不同。我正在使用 SICStus,它定义了 goal_expansion/5 .我快速浏览了文档,似乎 SWI-Prolog 有一个 goal_expansion/2 .
我在一个 let 中为多个声明引入了不同的语法。 : let((X1,X2),...)定义 X1 , 然后定义 X2 (所以相当于 let(X1,let(X2,...)) ),而 let([X1,X2],...)定义 X1X2同时(允许交换示例)。
以下是一些示例调用:
test1 :- let(A = 1,(
print(A),nl,
let(A is A+1,(
print(A),nl,
let(A is A + 1,(
print(A),nl
))
))
)).

test2 :- A=2,let([A=B,B=A],(print(B),nl)).

test3 :- A=1, let((
A is A * 2,
A is A * 2,
A is A * 2
),(
print(A),nl
)),print(A),nl.

test4 :- let([A=1,B=2],let([A=B,B=A],(print(A-B),nl))).

test5 :- let((
[A=1,B=2],
[A=B,B=A]
),(
print(A-B),nl
)).

关于prolog - 在 Prolog 中定义 "let expressions",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64375536/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com