私は Lisp を学んでいて、Lisp の関数から変更された入力引数を返さなければなりません。
次の簡単な例を考えてみましょう:
(defun swap (l1 l2)
(let ((temp))
(setf temp l1)
(setf l1 l2)
(setf l2 temp)))
(setf a (list 1 2 3))
(setf b (list 7 8 9))
(swap a b)
(print a)
(print b)
変数への参照を関数に渡す方法がわからないため、機能しません。それはLispでも可能ですか?この関数はどのように解決できますか?
アップデート
;;; doesn't change original
(defun foo1 (x)
(setf x (list 0 0 0)))
;;; but this does
(defun foo4 (x)
(setf (car x) 0)
(setf (cdr x) (list 0 0)))
変数を変更できるように参照渡ししたかった理由は、3 つの入力引数を持つ関数があり、その関数がそれらすべてを変更する必要がある場合、参照によって変更する方がエレガントだと思うからです。 3 つの変数のリストを返し、それらで元の変数を上書きします。
;;; more elegant function
(defun foo (x y z)
;;... some work ...
;; Lets PRETEND this does work
(setf x new-x)
(setf y new-y)
(setf z new-z))
; after this, a,b,c will have new values
(foo a b c)
;;; less elegant function
(defun foo (x y z)
;; ... some work ...
(list new-x new-y new-z))
; after this, I still will have to manually set a,b,c
(setf temp (foo a b c))
(setf a (nth 0 tmp))
(setf b (nth 1 tmp))
(setf c (nth 2 tmp))
私がこれを達成しようとしている理由を説明すると、ハノイの塔の宿題があるからです。「ディスク」を挿入および削除するために、3つのリストをstacks
使用し、それらに対してpop
and関数を使用することを考えていました。push
関数を定義(move n source target temp)
しましたが、変更を加えて再帰的に呼び出していn-1
ます。問題は、再帰関数で Ipop
またはpush
スタックを実行すると、外部のスタックに影響を与えないことです。move
関数が移動後にスタックを返すようにしたい場合n
、新しいスタックのリストを実際に返す必要があります (そのエレガントでない関数) 参照によってそれらを編集するのではなく (そのよりエレガントな関数)
関数型言語の適切な方法は何ですか?