鉴于数据库中的以下事实:
foo(a, 3).
foo(b, 2).
foo(c, 4).
foo(d, 3).
foo(e, 2).
foo(f, 6).
foo(g, 3).
foo(h, 2).
Run Code Online (Sandbox Code Playgroud)
我想收集所有具有最小第二个参数的第一个参数,加上第二个参数的值.第一次尝试:
find_min_1(Min, As) :-
setof(B-A, foo(A, B), [Min-_|_]),
findall(A, foo(A, Min), As).
?- find_min_1(Min, As).
Min = 2,
As = [b, e, h].
Run Code Online (Sandbox Code Playgroud)
而不是setof/3,我可以使用aggregate/3:
find_min_2(Min, As) :-
aggregate(min(B), A^foo(A, B), Min),
findall(A, foo(A, Min), As).
?- find_min_2(Min, As).
Min = 2,
As = [b, e, h].
Run Code Online (Sandbox Code Playgroud)
NB
如果我正在寻找最小数字,这只会给出相同的结果.如果涉及算术表达式,结果可能会有所不同.如果涉及非数字,aggregate(min(...), ...)将抛出错误!
或者,我可以使用完整的键排序列表:
find_min_3(Min, As) :-
setof(B-A, foo(A, …Run Code Online (Sandbox Code Playgroud) 为了计算两个相同长度的列表之间的汉明距离,我使用foldl(hamm, A, B, 0, R).这个定义hamm/4:
hamm(A, A, V, V) :- !.
hamm(A, B, V0, V1) :- A \= B, V1 is V0 + 1.
Run Code Online (Sandbox Code Playgroud)
第一条规则中的切入可以防止不必要的回溯.但是,第二条规则的写法可能不同:
hamm2(A, A, V, V) :- !.
hamm2(_, _, V0, V1) :- V1 is V0 + 1.
Run Code Online (Sandbox Code Playgroud)
并且对于A和B都被接地的查询hamm2/4仍然是正确的foldl/5.
那么有一个很好的理由更喜欢一个而不是另一个吗?或者有理由按规定保留规则或切换它们吗?
我知道查询
hamm(a, B, 0, 1).
Run Code Online (Sandbox Code Playgroud)
是假的,而
hamm2(a, B, 0, 1).
Run Code Online (Sandbox Code Playgroud)
是的,但我无法确定哪一个更有意义...
使用SWI-Prolog(多线程,64位,版本7.3.5),我们一步一步地进行:
限定DCG非终结a//1在模块dcgAux(发音: " 二SEE-吴 "):
:- module(dcgAux,[a//1]). a(0) --> []. a(s(N)) --> [a], a(N).
运行以下查询 - 使用phrase/2和apply:foldl/4:
?- use_module([library(apply),dcgAux]). true. ?- phrase( foldl( a,[s(0),s(s(0))]),[a,a,a]). true. ?- phrase( foldl(dcgAux:a,[s(0),s(s(0))]),[a,a,a]). true. ?- phrase(apply:foldl(dcgAux:a,[s(0),s(s(0))]),[a,a,a]). true. ?- phrase(apply:foldl( a,[s(0),s(s(0))]),[a,a,a]). ERROR: apply:foldl_/4: Undefined procedure: apply:a/3
Нет!相当惊讶 - 而不是一个好的.我们是否遗漏了一些未知的未知数?
为了摆脱上述恼人的行为,我们必须首先找出导致它的原因:
?- import_module(apply,M), M=user. false. ?- phrase(apply:foldl(a,[s(0),s(s(0))]),[a,a,a]). ERROR: apply:foldl_/4: Undefined procedure: apply:a/3 ?- add_import_module(apply,user,end). true. ?- import_module(apply,M), M=user. …
我们可以将高阶映射谓词定义为:
map([], [], F).
map([A|As], [B|Bs], F) :-
call(F, A, B),
map(As, Bs, F).
Run Code Online (Sandbox Code Playgroud)
同样,我们可以将fold (left)定义为:
fold([], Acc, Acc, _F).
fold([A|As], B, Acc1, F) :-
call(F, Acc1, A, Acc2),
fold(As, B, Acc2, F).
Run Code Online (Sandbox Code Playgroud)
reduce(左)的正确定义是什么?我们可以这样定义吗?
reduce([A|As], Bs, F) :-
fold(As, Bs, A, F).
Run Code Online (Sandbox Code Playgroud)
并减少(右)如下?
reduceback([], Ident, F) :-
identity(F, Ident).
reduceback([A|As], B, F) :-
reduceback(As, C, F),
call(F, C, A, B).
Run Code Online (Sandbox Code Playgroud)
这些正确吗?
是否可以在 中使用参数化谓词mapList?
例如,我想执行以下操作:按列表迭代,对于每个偶数元素(列表仅包含数字)将此元素映射到某个值(该值由谓词的参数设置)。
示例查询:
?- mapList(p(red, blue), [1,2,3,4], [red, blue, red, blue]).
true.
?- mapList(p(green, blue), [1,2,3,4], [green, blue, green, blue]).
true.
Run Code Online (Sandbox Code Playgroud) ?- assertz(:- module(foo1, [f/1])).
true.
?- foo1:assertz(f(1)).
true.
?- foo1:f(1).
true.
?- foo2:f(1).
Correct to: "foo1:f(1)"? no
ERROR: Undefined procedure: foo2:f/1
ERROR: In:
ERROR: [8] foo2:f(1)
ERROR: [7] <user>
Run Code Online (Sandbox Code Playgroud)
我感觉合理。但是然后(从头开始)......
?- assertz(:- module(foo1, [f/1])).
true.
?- assertz(f(1)).
true.
?- foo1:f(1).
true.
?- foo2:f(1).
true. # Wait, what? foo2 doesn't appear in my program. Should fail?
?- frobnoz:f(1).
true. # Also odd!
Run Code Online (Sandbox Code Playgroud)
但是之后...
?- foo2:assertz(f(1)).
true.
?- foo2:f(1).
true.
?- frobnoz:f(1).
ERROR: Undefined procedure: frobnoz:f/1
Run Code Online (Sandbox Code Playgroud)
如何F取得加入到foo2时候我不提foo2。为什么frobnoz:f …
我通常能够通过 maplist 找出 Lambda 的一些用法,但通常很难在 prolog 中使用 lambda。这可能是因为它与其他语言不同,因为统一。
这是症结之一:如何应用声明的 Lambda 表达式?铁
LAM = \X^R^(....)
Run Code Online (Sandbox Code Playgroud)
(奇怪,= 和 \ 之间必须有空格)
你好吗 :
\(LAM)(abc,R)
Run Code Online (Sandbox Code Playgroud)
我想做的另一件事是像 FACT 一样存储 Lambda 表达式,以便我可以查询它,但也可以像 lambda 函数一样使用它,以便我可以稍后进行绑定......我可以认为它错了..
move = \Obj^From^To(move(Obj,From,To))
Run Code Online (Sandbox Code Playgroud)
实例化:
?- \(move)(ball,ground,table).
Run Code Online (Sandbox Code Playgroud)
或部分:
?- L2 = \(move)(ball).
?- L3 = \(L2)(table,floor)
Run Code Online (Sandbox Code Playgroud)
询问 :
?- move(ball,F,T).
Run Code Online (Sandbox Code Playgroud) 所述MAPLIST / 3谓词具有以下形式
maplist(:Goal, ?List1, ?List2)
Run Code Online (Sandbox Code Playgroud)
然而,非常相似的函数findall/3具有以下形式
findall(+Template, :Goal, -Bag)
Run Code Online (Sandbox Code Playgroud)
它不仅有一个目标,还有一个模板。我发现这个模板在很多地方都非常有用,并开始想知道为什么 maplist/3 没有一个。
为什么 maplist/3 没有模板参数而 findall/3 有?这些谓词之间的显着区别是什么?
我想用maplist/3实现的目标可以是跟随伪代码:
maplist(
lambda X: Z/Y=X, to_lower(Z,LC), char_code(L,LC), return L/Y,
['A'/42, 'B'/500],
Res).
Res = ['a'/42, 'b'/500]
Run Code Online (Sandbox Code Playgroud)
我知道可以写例如
maplist(plus(1), [1,2,3,4], Res).
Res = [2,3,4,5].
Run Code Online (Sandbox Code Playgroud)
所以我可以将伪代码定义lambda X: Z/Y=X, to_lower(Z,LC), char_code(L,LC), return L/Y为普通谓词,并在maplist中使用此谓词...
但是,我很好奇是否可以在不创建全新谓词的情况下执行此操作?
我想这样做的原因是因为我觉得阅读更自然,而不是在代码中跳转来找到谓词
在 sicstus prolog 中,有一个谓词:
maplist(:Pred, +List)
Run Code Online (Sandbox Code Playgroud)
Pred应该只采用一个参数 -List元素。如何通过定义第一个参数的 2 参数谓词?在其他语言中,它会被写成:
maplist(pred.bind(SomeValue), List)
Run Code Online (Sandbox Code Playgroud) boolean(true).
boolean(false).
formula_0(P, Q):- (P; Q), \+ P.
solution_for_formula(P, Q, Formula):-
maplist(boolean, [P, Q]), call([Formula, P, Q]).
Run Code Online (Sandbox Code Playgroud)
对我之前的问题的跟进。为什么这行不通?(如果我call([Formula, P, Q])用formula_0(P, Q)它替换它有效。)
我正在使用 SWI-prolog,我正在尝试创建一个辅助函数,该函数将映射到一个列表并将每个元素与给定的整数相乘。我的目的是创建一个对应于 Haskell 函数的谓词multByN x n = x * n并在这个意义上使用它:
map (multByN 3) [1,2,3] 这会将所有元素乘以 3 并产生 [3,6,9]
我在 Prolog 中搜索了相应的谓词,maplist/2但发现我只能使用它来检查列表中每个元素的布尔条件是否成立,而不是实际返回一个新的、处理过的列表。我了解这是如何工作的:
isEven(X) :- 0 is X mod 2
maplist(isEven, [2,4,6])给true.
但是,我不明白人们会如何将maplist(multByN(3), [1,2,3])某些变量与[3,6,9]. 由于我无法弄清楚这一点,因此我尝试实现我自己的映射函数,将谓词映射multByN到列表,我得到了一些看起来正确的东西,但事实并非如此。我有这个:
multByN(X, N, Y) :- Y is N*X.
mapFunc(_, [], L) :-
write(L), nl.
mapFunc(N, [H|T], L) :-
multByN(H, N, Z),
mapFunc(N, T, [Z|L]).
Run Code Online (Sandbox Code Playgroud)
使用这个谓词我得到:
?- mapFunc(3, [1,2,3], X).
[9,6,3|_1746]
true ;
Run Code Online (Sandbox Code Playgroud)
在这里,我实际上是在打印最终列表以查看它的样子,但是我们可以看到查询实际上并没有说,X = …
meta-predicate ×12
prolog ×11
lambda ×2
module ×2
aggregates ×1
backtracking ×1
list ×1
mapping ×1
prolog-setof ×1
swi-prolog ×1