在lisp中按值传递参数
Posted
技术标签:
【中文标题】在lisp中按值传递参数【英文标题】:Passing by parameters by value in lisp 【发布时间】:2017-07-14 18:22:06 【问题描述】:我遇到的问题是我无法解决 lisp 按值而不是按引用传递数组的事实。
当我研究这个问题时,其他人的问题的解决方案分为四类。
-
使用闭包
从功能上思考
使用宏
使用全局变量,即 defparameter
1 & 2) 我看不出前两种解决方案是如何使用的。也许我不明白闭包是如何工作的,也不明白如何在功能上思考。
3) 我制作了宏而不是函数,但是当函数自身递归时它们就不起作用(除非它们确实起作用而我只是没有正确编写它们)。
4) 我不喜欢全局变量的想法。
我在编写的许多函数中都遇到了这个问题。我最成功的是在函数返回时返回数组。但是当函数在数组的子序列上递归时,我就卡住了。
我想要一个通用的解决方案,我如何以不同的方式思考这些问题,不是这里提交的代码的解决方案。
如果你想参考我尝试编写的一段特定代码,这里就是。
我正在尝试用 Lisp 为 HackerRank 编写一些代码。
我需要一个 Eratosthenes 筛子(以获得素数)。
我写了以下内容,由于上述原因,它不起作用。 (我的逻辑可能也是错误的。)
;sieve-numbers is an array with :initial-element nil
;sieve-numbers represents only the odd numbers starting at 3
;i.e., (aref sieve-numbers n) represents the value 3+n+n
;when the sieve is done (aref sieve-numbers n) is nil if (+ 3 n n) is prime
;removed is the number of values in the sieve-numbers array that have been chopped off the front
(defun sieve-knock (sieve-numbers n)
"knock out the n'th value, then recurse with a sieve-numbers array that is missing the first n elements until (length sieve-numbers) < n"
(format t "sieve-knock (length sieve-numbers) ~a, n ~a~%" (length sieve-numbers) n)
(cond ((> n (length sieve-numbers)) 'done)
(t (setf (aref sieve-numbers (1- n)) t)
(format t "sieve-knock sieve-numbers ~a~%" sieve-numbers)
(sieve-knock (subseq sieve-numbers n) n))))
(defun sieve (sieve-numbers removed)
"the sieve"
(format t "sieve sieve-numbers ~a, removed ~a~%" sieve-numbers removed)
(cond
((= 0 (length sieve-numbers)) 'done)
((aref sieve-numbers 0) (sieve (subseq sieve-numbers 1) (1+ removed)))
(t ;found a prime!
(sieve-knock (subseq sieve-numbers 1) (+ 3 removed removed))
(sieve (subseq sieve-numbers 1) (1+ removed)))))
【问题讨论】:
Common Lisp 通过引用传递数组。问题是SUBSEQ
创建了一个新数组。如果您只需要传递数组的一部分,则可以使用置换数组,或者也只传递开始/结束索引。
【参考方案1】:
Lisp 使用数组的引用。将数组传递给函数时,该函数通过参数具有新的引用。传递参数时,不会以任何方式复制或更改数组。
你可以使用递归:
传递数组,不要一直复制新数组 传递索引 返回数组例子:
(defun rknock (sieve-vector pos step)
(if (>= pos (length sieve-vector))
sieve-vector
(progn
(setf (aref sieve-vector pos) t)
(rknock sieve-vector (+ pos step) step))))
但简单的基于 LOOP 的迭代似乎更容易:
(defun knock (sieve-vector start step)
(loop for pos from start below (length sieve-vector) by step
do (setf (aref sieve-vector pos) t))
sieve-vector)
【讨论】:
以上是关于在lisp中按值传递参数的主要内容,如果未能解决你的问题,请参考以下文章