在lisp中按值传递参数

Spi*_*dad 0 lisp parameters common-lisp pass-by-value

我遇到的问题是我无法解决lisp按值而不是通过引用传递数组的事实.

当我研究这个问题时,其他人的问题的解决方案分为四类.

  1. 使用一个闭包
  2. 从功能上思考
  3. 使用宏
  4. 使用全局变量,即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)))))
Run Code Online (Sandbox Code Playgroud)

Rai*_*wig 5

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))))
Run Code Online (Sandbox Code Playgroud)

但简单的基于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)
Run Code Online (Sandbox Code Playgroud)