在 lambda 函数内访问范围变量或实现相同 lisp 的替代方法

accessing in scope variables inside lambda function or alternative way to achieve the same lisp

我有以下函数执行以下工作:returns 如果区域地图有两个节点作为邻居,则矩阵约束:

(defun map-coloring-constraint (region-map)
  (let* ((node-list (list-regions region-map))
         (constraints (make-array (list (length node-list) (length node-list)))))
    (loop for (node-a . value) in region-map
      do (loop for node-b in (car value)   
           do (setf (aref constraints  
                          (position node-a node-list)  ;calculating multiple times
                          (position node-b node-list))
                    (not nil))))
    constraints)) 

用法如下,可以大致了解region-map的结构:

Break 1 [146]> *australia* 
((SA (WA NT Q NSW V)) (WA (NT SA)) (NT (Q SA WA)) (Q (NSW SA NT)) (NSW (V SA Q)) (V (SA NSW)) (T))
Break 1 [146]> (map-coloring-constraint *australia*)
#2A((NIL T T T T T NIL)
    (T NIL T NIL NIL NIL NIL)
    (T T NIL T NIL NIL NIL)
    (T NIL T NIL T NIL NIL)
    (T NIL NIL T NIL T NIL)
    (T NIL NIL NIL T NIL NIL)
    (NIL NIL NIL NIL NIL NIL NIL))

有没有更好的写法避免内循环

另一个问题: 我在作用域中有一个变量 a(这是一个列表)和一个列表 b。我想在此范围内对 b 的每个元素应用一个 lambda 函数。这可以通过 mapcar 来实现。问题是我需要在 lambda 函数中访问变量 a 。我怎样才能做到这一点。

P.S.: 第二个问题的答案也是第一个问题的答案,因此两个问题合二为一 post.

您正在填充一个矩阵;两级循环是一种自然的方法。 您也许可以使用 row-major-aref 避免内部循环,但我不明白您为什么要这样做。

至于第二个问题,真的不清楚:如果你试图从外部作用域访问一个变量,那就很简单了:

(let ((a 2))
  (mapcar (lambda (x) (expt x a))
          '(1 2 3)))
==> (1 4 9)

如果你想从内部作用域访问一个变量,那是不可能的:

(let ((a 2))
  (mapcar (lambda (x) (expt x a))
          '(1 2 3))
  ;; `x` does not exist anymore, it cannot be accessed
)

PS。您可能希望修改代码以避免不必要地调用 lengthposition:这些函数在其列表参数的长度上是线性的。您可能想要进行的另一项更改是将 (not nil) 替换为 t.