首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在prolog中限制变量作用域

在prolog中限制变量作用域
EN

Stack Overflow用户
提问于 2014-11-10 13:45:11
回答 3查看 1.8K关注 0票数 1

我想声明一个列表列表,如下所示:

代码语言:javascript
运行
复制
%% example 1
Xs = [
  [[A],[[A]]], 
  [[A],[[A],[A]]], 
  [[A],[[A],[A],[A]]]
].

这里,符号A指的是每个列表中的相同变量。执行maplist(writeln,xs)将产生以下输出:

代码语言:javascript
运行
复制
[[_G1],[[_G1]]]
[[_G1],[[_G1],[_G1]]]
[[_G1],[[_G1],[_G1],[_G1]]]

我想在每个列表中使用相同的符号A,但每个列表的变量都是不同的,以给出以下输出:

代码语言:javascript
运行
复制
[[_G1],[[_G1]]]
[[_G2],[[_G2],[_G2]]]
[[_G3],[[_G3],[_G3],[_G3]]]

我做这项工作的唯一方法是为每个列表赋予它自己的唯一变量,如下所示:

代码语言:javascript
运行
复制
%% example 2
Xs = [
  [[A1],[[A1]]], 
  [[A2],[[A2],[A2]]], 
  [[A3],[[A3],[A3],[A3]]]
].

是否有任何Prolog语法,以便不需要按照示例2对每个变量进行编号?我尝试在列表周围添加括号,如下所示:

代码语言:javascript
运行
复制
Xs = [
  ([[A],[[A]]]), 
  ([[A],[[A],[A]]]), 
  ([[A],[[A],[A],[A]]])
].

但这给出了与示例1相同的输出。

EN

回答 3

Stack Overflow用户

发布于 2014-11-10 14:47:31

你可以这样做:

首先,使用不同的变量创建所需的列表结构:

代码语言:javascript
运行
复制
?- maplist(length, Lists, [2,3,4]).
Lists = [[X1, X2], [X3, X4, X5], [X6, X7, X8, X9]].

然后,使用以下附加定义:

代码语言:javascript
运行
复制
same_element(Ls) :- maplist(=([_]), Ls).

您可以将同一子列表中的变量统一为相同的术语:

代码语言:javascript
运行
复制
?- 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].

在组合中:

代码语言:javascript
运行
复制
?- maplist(length, Lists, [2,3,4]),
   maplist(same_element, Lists),
   maplist(writeln, Lists).

让步:

代码语言:javascript
运行
复制
[[_G1079],[_G1079]]
[[_G1087],[_G1087],[_G1087]]
[[_G1095],[_G1095],[_G1095],[_G1095]]

现在,使用以下Emacs定义:

代码语言:javascript
运行
复制
(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,你会得到:

代码语言:javascript
运行
复制
[[X1],[X1]]
[[X2],[X2],[X2]]
[[X3],[X3],[X3],[X3]]

因此,你可以通过统一你想要的变量来动态地生成你想要的结构,或者复制和粘贴上面的输出,并直接在你的程序中使用它,只需稍作修改。

票数 2
EN

Stack Overflow用户

发布于 2014-11-10 14:52:48

Prolog中的变量名的作用域跨越谓词定义中的单个子句或顶级查询。所以,这是:

代码语言:javascript
运行
复制
?- List = [A, A, A].

表示具有三倍相同变量A的列表。如果你把它放到一个谓词中,比如说放在一个文件my_lists.pl中(我没有像你一样嵌套列表,只是为了简单起见):

代码语言:javascript
运行
复制
my_list([A, A]).
my_list([A, A, A]).
my_list([A, A, A, A]).

这三个子句中的A现在不在相同的词法作用域中,所以如果您参考这个谓词,然后使用例如findall/3收集所有可能的my_list(L)实例化,您将得到您想要的结果:

代码语言:javascript
运行
复制
?- [my_lists].
true.

?- findall(L, my_list(L), Ls).
Ls = [[_G1945, _G1945],
      [_G1933, _G1933, _G1933],
      [_G1918, _G1918, _G1918, _G1918]].

这接近你要找的东西了吗?您试图实现的目标是什么?

票数 2
EN

Stack Overflow用户

发布于 2014-11-10 18:01:58

如果您想写出变量并为它们指定一个精确的名称,则需要写选项variable_names/1This answer解释了如何。或者,您可以使用遗留谓词numbervars/3,它将不同的变量与术语'$VAR'(N)统一起来,然后使用writeq/1或写选项numbervars(true)

但这两种方法在您指定的情况下都不起作用。实际上,您的查询完全是幸运的

代码语言:javascript
运行
复制
 ?- Xs = [[[A],[A]],[[A],[A],[A]],[[A],[A],[A],[A]]], maplist(writeln,Xs).

为不同的列表生成了相同的变量。更糟糕的是,完全相同的目标编写完全相同的列表,可能会为不同的调用产生不同的变量名:

代码语言:javascript
运行
复制
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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26837502

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档