在 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。您可能希望修改代码以避免不必要地调用 length
和 position
:这些函数在其列表参数的长度上是线性的。您可能想要进行的另一项更改是将 (not nil)
替换为 t
.
我有以下函数执行以下工作: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。您可能希望修改代码以避免不必要地调用 length
和 position
:这些函数在其列表参数的长度上是线性的。您可能想要进行的另一项更改是将 (not nil)
替换为 t
.