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

时间:2015-11-01 07:43:22

标签: lambda lisp

我有以下功能执行以下工作:如果region-map有两个节点作为邻居,则返回矩阵约束:

(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。:对第二个问题的回答也是第一个回答,因此在一个帖子中有两个问题。

1 个答案:

答案 0 :(得分:2)

你正在填写一个矩阵;两个级别的循环是一种自然的方式。 您可以使用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