对于 length/2 如何添加人类可读的变量名
For length/2 how to add human readable variable names
如何为系统生成的变量名显示人类可读的变量名?
举个简单的例子:
?- length(Ls,N).
Ls = [],
N = 0 ;
Ls = [_5112],
N = 1 ;
Ls = [_5112, _5118],
N = 2 ;
Ls = [_5112, _5118, _5124],
N = 3
会更好
?- length(Ls,N).
Ls = [],
N = 0 ;
Ls = [a],
N = 1 ;
Ls = [a, b],
N = 2 ;
Ls = [a, b, c],
N = 3
映射
_5112 = a
_5118 = b
_5124 = c
详情
我找到的最接近的解决方案使用 read_term/2 as demonstrated in this answer 和 variable_names(Vars)
选项,但是我的问题没有使用 read_term
从控制台获取术语。
如果这是重复的,请告诉我;我找不到一个。
真正的问题是基于生成测试用例数据:
?- length(Ls,N),list_partitionedNU(Ls,Ps).
Ls = Ps, Ps = [],
N = 0 ;
Ls = [_5242],
N = 1,
Ps = [[_5242]] ;
Ls = [_5242, _5248],
N = 2,
Ps = [[_5242], [_5248]] ;
Ls = [_5242, _5248],
N = 2,
Ps = [[_5242, _5248]] ;
Ls = [_5242, _5248, _5254],
...
参见 and list_partitionedNU/2
。
回答后跟进。
基于威廉
partitions(Ps) :-
length(Ls,N),
assign(Ls),
list_partitionedNU(Ls,Ps).
?- partitions(Ps).
Ps = [] ;
Ps = [[a]] ;
Ps = [[a], [b]] ;
Ps = [[a, b]] ;
Ps = [[a], [b], [c]] ;
Ps = [[a], [b, c]] ;
Ps = [[a, b], [c]] ;
Ps = [[a, c], [b]] ;
Ps = [[a, b, c]] ;
Ps = [[a], [b], [c], [d]] ;
Ps = [[a], [b], [c, d]] ;
Ps = [[a], [b, c], [d]] ;
Ps = [[a], [b, d], [c]] ;
Ps = [[a], [b, c, d]] ;
Ps = [[a, b], [c], [d]] ;
Ps = [[a, c], [b], [d]] ;
Ps = [[a, d], [b], [c]] ;
Ps = [[a, b], [c, d]] ;
Ps = [[a, c], [b, d]] ;
Ps = [[a, d], [b, c]] ;
Ps = [[a, b, c], [d]] ;
Ps = [[a, b, d], [c]] ;
Ps = [[a, c, d], [b]] ;
Ps = [[a, b, c, d]] ;
...
基于 CapelliC 的
partitions(Ps) :-
length(Ls,N),
numbervars(Ls,0,N),
list_partitionedNU(Ls,Ps).
?- partitions(Ps).
Ps = [] ;
Ps = [[A]] ;
Ps = [[A], [B]] ;
Ps = [[A, B]] ;
Ps = [[A], [B], [C]] ;
Ps = [[A], [B, C]] ;
Ps = [[A, B], [C]] ;
Ps = [[A, C], [B]] ;
Ps = [[A, B, C]] ;
Ps = [[A], [B], [C], [D]] ;
Ps = [[A], [B], [C, D]] ;
Ps = [[A], [B, C], [D]] ;
Ps = [[A], [B, D], [C]] ;
Ps = [[A], [B, C, D]] ;
Ps = [[A, B], [C], [D]] ;
Ps = [[A, C], [B], [D]] ;
Ps = [[A, D], [B], [C]] ;
Ps = [[A, B], [C, D]] ;
Ps = [[A, C], [B, D]] ;
Ps = [[A, D], [B, C]] ;
Ps = [[A, B, C], [D]] ;
Ps = [[A, B, D], [C]] ;
Ps = [[A, C, D], [B]] ;
Ps = [[A, B, C, D]] ;
...
我们可以构造一个谓词,以递归方式将 "assigns" 值赋给函子中的变量,并使用一个累加器跟踪最新的 "name" 赋值。
例如:
assign(Term) :-
assign(Term, 97, _).
assign(X, N, N1) :-
var(X),
!,
char_code(X, N),
N1 is N+1.
assign(F, N, N1) :-
F =.. [_|A],
assign_list(A, N, N1).
assign_list([], N, N).
assign_list([H|T], N, NT) :-
assign(H, N, N1),
assign_list(T, N1, NT).
例如:
?- length(L, _), assign(L).
L = [] ;
L = [a] ;
L = [a, b] ;
L = [a, b, c] ;
L = [a, b, c, d] ;
L = [a, b, c, d, e] ;
L = [a, b, c, d, e, f] .
?- Q = [L, [_, _]], length(L, _), assign(Q).
Q = [[], [a, b]],
L = [] ;
Q = [[a], [b, c]],
L = [a] ;
Q = [[a, b], [c, d]],
L = [a, b] ;
Q = [[a, b, c], [d, e]],
L = [a, b, c] .
我们因此 "walk" 通过树并为变量赋值。通过上述实现,我们 而不是 考虑现有常量。因此,我们可能会将已经存在的值分配给变量。此外,我们只是不断递增字符代码,所以最终我们会得到符号、控制字符和字符。
然而,上述缺点可以 "solved" 通过首先检查函子并获得要跳过的常量列表。此外,当然可以改进术语生成器,例如在 z
.
之后生成 aa
@DanielLyons 指出了 term_variables/2
谓词,它可以简化 assign/1
谓词很多,例如:
assign(Term) :-
term_variables(Term, Vars),
assign_list(Vars, 97).
assign_list([], _).
assign_list([H|T], N) :-
char_code(H, N),
N1 is N+1,
assign_list(T, N1).
这当然仍然没有解决上述缺点,尽管如前所述,我们可以通过使用 char_code
以外的其他东西来获得常量名称,并首先 wak 看看对于正在使用的常量。
老歌但歌舞曲 numbervars/3 已被重温:
?- length(L,5),numbervars(L,0,N).
L = [A, B, C, D, E],
N = 5.
不确定它是否真的有用,但探索起来很不错...
?- length(L,5),numbervars(L,0'a,N).
L = [T3, U3, V3, W3, X3],
N = 102.
我们不要忘记明显的选择:不同的 Prolog 处理器。
使用 SICStus Prolog 4.5.0 (try full-featured SICStus Prolog 30 days for free):
| ?- Xs = [_C,f(_E)|_], length(Xs,N).
N = 2, Xs = [_C,f(_E)] ? ;
N = 3, Xs = [_C,f(_E),_A] ? ;
N = 4, Xs = [_C,f(_E),_A,_B] ? ;
N = 5, Xs = [_C,f(_E),_A,_B,_D] ? ;
N = 6, Xs = [_C,f(_E),_A,_B,_D,_F] ? ;
N = 7, Xs = [_C,f(_E),_A,_B,_D,_F,_G] ? ...
如何为系统生成的变量名显示人类可读的变量名?
举个简单的例子:
?- length(Ls,N).
Ls = [],
N = 0 ;
Ls = [_5112],
N = 1 ;
Ls = [_5112, _5118],
N = 2 ;
Ls = [_5112, _5118, _5124],
N = 3
会更好
?- length(Ls,N).
Ls = [],
N = 0 ;
Ls = [a],
N = 1 ;
Ls = [a, b],
N = 2 ;
Ls = [a, b, c],
N = 3
映射
_5112 = a
_5118 = b
_5124 = c
详情
我找到的最接近的解决方案使用 read_term/2 as demonstrated in this answer 和 variable_names(Vars)
选项,但是我的问题没有使用 read_term
从控制台获取术语。
如果这是重复的,请告诉我;我找不到一个。
真正的问题是基于生成测试用例数据:
?- length(Ls,N),list_partitionedNU(Ls,Ps).
Ls = Ps, Ps = [],
N = 0 ;
Ls = [_5242],
N = 1,
Ps = [[_5242]] ;
Ls = [_5242, _5248],
N = 2,
Ps = [[_5242], [_5248]] ;
Ls = [_5242, _5248],
N = 2,
Ps = [[_5242, _5248]] ;
Ls = [_5242, _5248, _5254],
...
参见 list_partitionedNU/2
。
回答后跟进。
基于威廉
partitions(Ps) :-
length(Ls,N),
assign(Ls),
list_partitionedNU(Ls,Ps).
?- partitions(Ps).
Ps = [] ;
Ps = [[a]] ;
Ps = [[a], [b]] ;
Ps = [[a, b]] ;
Ps = [[a], [b], [c]] ;
Ps = [[a], [b, c]] ;
Ps = [[a, b], [c]] ;
Ps = [[a, c], [b]] ;
Ps = [[a, b, c]] ;
Ps = [[a], [b], [c], [d]] ;
Ps = [[a], [b], [c, d]] ;
Ps = [[a], [b, c], [d]] ;
Ps = [[a], [b, d], [c]] ;
Ps = [[a], [b, c, d]] ;
Ps = [[a, b], [c], [d]] ;
Ps = [[a, c], [b], [d]] ;
Ps = [[a, d], [b], [c]] ;
Ps = [[a, b], [c, d]] ;
Ps = [[a, c], [b, d]] ;
Ps = [[a, d], [b, c]] ;
Ps = [[a, b, c], [d]] ;
Ps = [[a, b, d], [c]] ;
Ps = [[a, c, d], [b]] ;
Ps = [[a, b, c, d]] ;
...
基于 CapelliC 的
partitions(Ps) :-
length(Ls,N),
numbervars(Ls,0,N),
list_partitionedNU(Ls,Ps).
?- partitions(Ps).
Ps = [] ;
Ps = [[A]] ;
Ps = [[A], [B]] ;
Ps = [[A, B]] ;
Ps = [[A], [B], [C]] ;
Ps = [[A], [B, C]] ;
Ps = [[A, B], [C]] ;
Ps = [[A, C], [B]] ;
Ps = [[A, B, C]] ;
Ps = [[A], [B], [C], [D]] ;
Ps = [[A], [B], [C, D]] ;
Ps = [[A], [B, C], [D]] ;
Ps = [[A], [B, D], [C]] ;
Ps = [[A], [B, C, D]] ;
Ps = [[A, B], [C], [D]] ;
Ps = [[A, C], [B], [D]] ;
Ps = [[A, D], [B], [C]] ;
Ps = [[A, B], [C, D]] ;
Ps = [[A, C], [B, D]] ;
Ps = [[A, D], [B, C]] ;
Ps = [[A, B, C], [D]] ;
Ps = [[A, B, D], [C]] ;
Ps = [[A, C, D], [B]] ;
Ps = [[A, B, C, D]] ;
...
我们可以构造一个谓词,以递归方式将 "assigns" 值赋给函子中的变量,并使用一个累加器跟踪最新的 "name" 赋值。
例如:
assign(Term) :-
assign(Term, 97, _).
assign(X, N, N1) :-
var(X),
!,
char_code(X, N),
N1 is N+1.
assign(F, N, N1) :-
F =.. [_|A],
assign_list(A, N, N1).
assign_list([], N, N).
assign_list([H|T], N, NT) :-
assign(H, N, N1),
assign_list(T, N1, NT).
例如:
?- length(L, _), assign(L).
L = [] ;
L = [a] ;
L = [a, b] ;
L = [a, b, c] ;
L = [a, b, c, d] ;
L = [a, b, c, d, e] ;
L = [a, b, c, d, e, f] .
?- Q = [L, [_, _]], length(L, _), assign(Q).
Q = [[], [a, b]],
L = [] ;
Q = [[a], [b, c]],
L = [a] ;
Q = [[a, b], [c, d]],
L = [a, b] ;
Q = [[a, b, c], [d, e]],
L = [a, b, c] .
我们因此 "walk" 通过树并为变量赋值。通过上述实现,我们 而不是 考虑现有常量。因此,我们可能会将已经存在的值分配给变量。此外,我们只是不断递增字符代码,所以最终我们会得到符号、控制字符和字符。
然而,上述缺点可以 "solved" 通过首先检查函子并获得要跳过的常量列表。此外,当然可以改进术语生成器,例如在 z
.
aa
@DanielLyons 指出了 term_variables/2
谓词,它可以简化 assign/1
谓词很多,例如:
assign(Term) :-
term_variables(Term, Vars),
assign_list(Vars, 97).
assign_list([], _).
assign_list([H|T], N) :-
char_code(H, N),
N1 is N+1,
assign_list(T, N1).
这当然仍然没有解决上述缺点,尽管如前所述,我们可以通过使用 char_code
以外的其他东西来获得常量名称,并首先 wak 看看对于正在使用的常量。
老歌但歌舞曲 numbervars/3 已被重温:
?- length(L,5),numbervars(L,0,N).
L = [A, B, C, D, E],
N = 5.
不确定它是否真的有用,但探索起来很不错...
?- length(L,5),numbervars(L,0'a,N).
L = [T3, U3, V3, W3, X3],
N = 102.
我们不要忘记明显的选择:不同的 Prolog 处理器。
使用 SICStus Prolog 4.5.0 (try full-featured SICStus Prolog 30 days for free):
| ?- Xs = [_C,f(_E)|_], length(Xs,N). N = 2, Xs = [_C,f(_E)] ? ; N = 3, Xs = [_C,f(_E),_A] ? ; N = 4, Xs = [_C,f(_E),_A,_B] ? ; N = 5, Xs = [_C,f(_E),_A,_B,_D] ? ; N = 6, Xs = [_C,f(_E),_A,_B,_D,_F] ? ; N = 7, Xs = [_C,f(_E),_A,_B,_D,_F,_G] ? ...