序言:效率
Prolog: efficiency
序言中有没有办法缩短以下内容:
rule(prop, [1/2,2/2]).
rule(prop, [1/3,2/3,3/3]).
rule(prop, [1/4,2/4,3/4,4/4]).
rule(prop, [1/5,2/5,3/5,4/5,5/5]).
rule(prop, [1/6,2/6,3/6,4/6,5/6,6/6]).
rule(prop, [1/7,2/7,3/7,4/7,5/7,6/7,7/7]).
下面的代码不一定"shorter" 6 种不同规则的情况,但它更具可扩展性,这可能是您真正的意思。
您可以将其分解如下。一、生成一个列表的规则:
list_props(N, N, [N/N]).
list_props(X, N, [X/N|T]) :-
X >= 1,
X < N,
X1 is X + 1,
list_props(X1, N, T).
当您调用它时,它会生成一个从第一个参数到最后一个参数的比例列表,最后一个参数是分母。例如:
| ?- list_props(1, 4, L).
L = [1/4,2/4,3/4,4/4] ? a
| ?-
请注意,您可以使用 integer(N)
和条件强制 N
为 >= 1 的整数,但我很简短,在上面没有这样做。
您可以在顶级谓词中使用它:
rule(prop, L) :-
between(2, 7, X),
list_props(1, X, L).
产生:
| ?- rule(prop, L).
L = [1/2,2/2] ? ;
L = [1/3,2/3,3/3] ? ;
L = [1/4,2/4,3/4,4/4] ? ;
L = [1/5,2/5,3/5,4/5,5/5] ? ;
L = [1/6,2/6,3/6,4/6,5/6,6/6] ? ;
L = [1/7,2/7,3/7,4/7,5/7,6/7,7/7] ? ;
(2 ms) no
| ?-
TL;DR: 为什么不委派处理递归的责任——并且把它也做对呢?
这个答案跟进了@lurker 在 上的回答。我们没有涵盖整个问题,而是专注于展示如何定义像 list_props/3
这样的谓词,以便将所有递归委托给经过验证的真实 Prolog 谓词
length/2
, numlist/2
and maplist/3
:
:- use_module(library(between), [numlist/2]).
:- use_module(library(lists), [maplist/3]).
自定义万能meta-predicate maplist/3
我们定义:
denom_num_expr(B, A, A/B).
示例查询使用 sicstus-prolog 4.3.2:
| ?- length(_Ds, N), numlist(N, _Ds), maplist(denom_num_expr(N), _Ds, Qs).
N = 1, Qs = [1/1] ? ;
N = 2, Qs = [1/2,2/2] ? ;
N = 3, Qs = [1/3,2/3,3/3] ? ;
N = 4, Qs = [1/4,2/4,3/4,4/4] ? ;
N = 5, Qs = [1/5,2/5,3/5,4/5,5/5] ? ;
N = 6, Qs = [1/6,2/6,3/6,4/6,5/6,6/6] ? ;
N = 7, Qs = [1/7,2/7,3/7,4/7,5/7,6/7,7/7] ? ;
N = 8, Qs = [1/8,2/8,3/8,4/8,5/8,6/8,7/8,8/8] ? ;
N = 9, Qs = [1/9,2/9,3/9,4/9,5/9,6/9,7/9,8/9,9/9] ? ...
序言中有没有办法缩短以下内容:
rule(prop, [1/2,2/2]).
rule(prop, [1/3,2/3,3/3]).
rule(prop, [1/4,2/4,3/4,4/4]).
rule(prop, [1/5,2/5,3/5,4/5,5/5]).
rule(prop, [1/6,2/6,3/6,4/6,5/6,6/6]).
rule(prop, [1/7,2/7,3/7,4/7,5/7,6/7,7/7]).
下面的代码不一定"shorter" 6 种不同规则的情况,但它更具可扩展性,这可能是您真正的意思。
您可以将其分解如下。一、生成一个列表的规则:
list_props(N, N, [N/N]).
list_props(X, N, [X/N|T]) :-
X >= 1,
X < N,
X1 is X + 1,
list_props(X1, N, T).
当您调用它时,它会生成一个从第一个参数到最后一个参数的比例列表,最后一个参数是分母。例如:
| ?- list_props(1, 4, L).
L = [1/4,2/4,3/4,4/4] ? a
| ?-
请注意,您可以使用 integer(N)
和条件强制 N
为 >= 1 的整数,但我很简短,在上面没有这样做。
您可以在顶级谓词中使用它:
rule(prop, L) :-
between(2, 7, X),
list_props(1, X, L).
产生:
| ?- rule(prop, L).
L = [1/2,2/2] ? ;
L = [1/3,2/3,3/3] ? ;
L = [1/4,2/4,3/4,4/4] ? ;
L = [1/5,2/5,3/5,4/5,5/5] ? ;
L = [1/6,2/6,3/6,4/6,5/6,6/6] ? ;
L = [1/7,2/7,3/7,4/7,5/7,6/7,7/7] ? ;
(2 ms) no
| ?-
TL;DR: 为什么不委派处理递归的责任——并且把它也做对呢?
这个答案跟进了@lurker 在 list_props/3
这样的谓词,以便将所有递归委托给经过验证的真实 Prolog 谓词
length/2
, numlist/2
and maplist/3
:
:- use_module(library(between), [numlist/2]). :- use_module(library(lists), [maplist/3]).
自定义万能meta-predicate maplist/3
我们定义:
denom_num_expr(B, A, A/B).
示例查询使用 sicstus-prolog 4.3.2:
| ?- length(_Ds, N), numlist(N, _Ds), maplist(denom_num_expr(N), _Ds, Qs). N = 1, Qs = [1/1] ? ; N = 2, Qs = [1/2,2/2] ? ; N = 3, Qs = [1/3,2/3,3/3] ? ; N = 4, Qs = [1/4,2/4,3/4,4/4] ? ; N = 5, Qs = [1/5,2/5,3/5,4/5,5/5] ? ; N = 6, Qs = [1/6,2/6,3/6,4/6,5/6,6/6] ? ; N = 7, Qs = [1/7,2/7,3/7,4/7,5/7,6/7,7/7] ? ; N = 8, Qs = [1/8,2/8,3/8,4/8,5/8,6/8,7/8,8/8] ? ; N = 9, Qs = [1/9,2/9,3/9,4/9,5/9,6/9,7/9,8/9,9/9] ? ...