我想声明一个列表列表,如下所示:
%% example 1
Xs = [
[[A],[[A]]],
[[A],[[A],[A]]],
[[A],[[A],[A],[A]]]
].这里,符号A指的是每个列表中的相同变量。执行maplist(writeln,xs)将产生以下输出:
[[_G1],[[_G1]]]
[[_G1],[[_G1],[_G1]]]
[[_G1],[[_G1],[_G1],[_G1]]]我想在每个列表中使用相同的符号A,但每个列表的变量都是不同的,以给出以下输出:
[[_G1],[[_G1]]]
[[_G2],[[_G2],[_G2]]]
[[_G3],[[_G3],[_G3],[_G3]]]我做这项工作的唯一方法是为每个列表赋予它自己的唯一变量,如下所示:
%% example 2
Xs = [
[[A1],[[A1]]],
[[A2],[[A2],[A2]]],
[[A3],[[A3],[A3],[A3]]]
].是否有任何Prolog语法,以便不需要按照示例2对每个变量进行编号?我尝试在列表周围添加括号,如下所示:
Xs = [
([[A],[[A]]]),
([[A],[[A],[A]]]),
([[A],[[A],[A],[A]]])
].但这给出了与示例1相同的输出。
发布于 2014-11-10 14:47:31
你可以这样做:
首先,使用不同的变量创建所需的列表结构:
?- maplist(length, Lists, [2,3,4]).
Lists = [[X1, X2], [X3, X4, X5], [X6, X7, X8, X9]].然后,使用以下附加定义:
same_element(Ls) :- maplist(=([_]), Ls).您可以将同一子列表中的变量统一为相同的术语:
?- maplist(same_element, [[X1, X2], [X3, X4, X5], [X6, X7, X8, X9]]).
X1 = X2, X2 = [_G1141],
X3 = X4, X4 = X5, X5 = [_G1149],
X6 = X7, X7 = X8, X8 = X9, X9 = [_G1157].在组合中:
?- maplist(length, Lists, [2,3,4]),
maplist(same_element, Lists),
maplist(writeln, Lists).让步:
[[_G1079],[_G1079]]
[[_G1087],[_G1087],[_G1087]]
[[_G1095],[_G1095],[_G1095],[_G1095]]现在,使用以下Emacs定义:
(defun nice-variables (start end)
(interactive "r")
(goto-char start)
(let ((n 1)
(variables nil)
(m (make-marker)))
(set-marker m end)
(while (and (<= (point) (marker-position m))
(re-search-forward "_G" (marker-position m) t))
(let* ((from (point))
(len (skip-chars-forward "0-9"))
(str (buffer-substring-no-properties from (+ from len)))
(num (assoc str variables)))
(delete-backward-char (+ len 2))
(if num
(insert (format "X%d" (cdr num)))
(setq variables (cons (cons str n) variables))
(insert (format "X%d" n))
(setq n (1+ n)))))))和区域上的M-x nice-variables RET,你会得到:
[[X1],[X1]]
[[X2],[X2],[X2]]
[[X3],[X3],[X3],[X3]]因此,你可以通过统一你想要的变量来动态地生成你想要的结构,或者复制和粘贴上面的输出,并直接在你的程序中使用它,只需稍作修改。
发布于 2014-11-10 14:52:48
Prolog中的变量名的作用域跨越谓词定义中的单个子句或顶级查询。所以,这是:
?- List = [A, A, A].表示具有三倍相同变量A的列表。如果你把它放到一个谓词中,比如说放在一个文件my_lists.pl中(我没有像你一样嵌套列表,只是为了简单起见):
my_list([A, A]).
my_list([A, A, A]).
my_list([A, A, A, A]).这三个子句中的A现在不在相同的词法作用域中,所以如果您参考这个谓词,然后使用例如findall/3收集所有可能的my_list(L)实例化,您将得到您想要的结果:
?- [my_lists].
true.
?- findall(L, my_list(L), Ls).
Ls = [[_G1945, _G1945],
[_G1933, _G1933, _G1933],
[_G1918, _G1918, _G1918, _G1918]].这接近你要找的东西了吗?您试图实现的目标是什么?
发布于 2014-11-10 18:01:58
如果您想写出变量并为它们指定一个精确的名称,则需要写选项variable_names/1。This answer解释了如何。或者,您可以使用遗留谓词numbervars/3,它将不同的变量与术语'$VAR'(N)统一起来,然后使用writeq/1或写选项numbervars(true)。
但这两种方法在您指定的情况下都不起作用。实际上,您的查询完全是幸运的
?- Xs = [[[A],[A]],[[A],[A],[A]],[[A],[A],[A],[A]]], maplist(writeln,Xs).为不同的列表生成了相同的变量。更糟糕的是,完全相同的目标编写完全相同的列表,可能会为不同的调用产生不同的变量名:
p(N) :-
length(_,N),
length(K,1),
writeq(K),
garbage_collect,
writeq(K).对于p(100),SICStus编写[_776][_46],SWI编写[_G517][_G3]。简而言之,你在大好的一天抓住了Prolog。这并不奇怪,因为标准只要求名称的“实现依赖”值,但有一些限制:它以下划线开头,其余字符对于不同的变量是不同的,对于相同写入目标中的相同变量也是相同的。以下是有关这方面的ISO/IEC 13211-1:1995:
使用write_term/3输出术语Term时(8.14.2)
所采取的动作由以下规则定义: a)如果Term是一个变量,则字符序列表示-
发送该变量即为输出。序列开始
带_(下划线),其余字符为
依赖于实现。相同的字符序列
中每次出现特定变量时都会使用
Term。每个字符序列使用不同的字符序列
Term.中的不同变量
这样做的原因是,全局一致的变量命名将在实现中产生大量开销。
总而言之:如果您想对同一个变量使用不同的变量名,那么可以将variable_names/1与不同的参数一起使用。如果您希望变量实际上是不同的,那么可以使用不同的名称,或者相应地使用copy_term/2。
https://stackoverflow.com/questions/26837502
复制相似问题