2020年1月9日木曜日

lispのconsセルによるポインタ



lispのconsセルによるポインタ

sirocco の書いてもすぐに忘れるメモ
Common Lisp でハノイの塔を解いてみる。
https://sirocco.hatenadiary.org/entry/20100823/1282563554
関数の中で
(defun hanoi (n from to via))
....
.. (pop (cadr from))...
...
としていてなぜ 関数の外のfromに該当する変数が変わるのか疑問に
思ったので調べた。


以下参照サイトと参照文

nobUnagaの日記
http://nobunaga.hatenablog.jp/entry/2016/08/11/163150
defunの変数は値渡し
 defunで渡される引数は値渡し
(ポインタじゃなくて,参照している値が渡される).
だから,当然だけど変数を引数で渡して,defunの中でその変数を更新するよ
うなことは間違い.
ポインタ (consセル)を指している変数を渡すと,それはそのポインタのアド
レスを渡していることになるから,その先の変数を変更できる.


(関数の)
値渡しと参照渡しの違いを理解する
https://magazine.rubyist.net/articles/0032/0032-CallByValueAndCallByReference.html
値渡し (call by value) とは、変数の値をコピーする渡し方で
値渡しでは、変数の値が引数にコピーされるため、次のような性質があります。
    引数 a と b を変更しても、それが変数 x と y には反映されない。

参照渡し (call by reference) とは、変数のメモリ番地を渡す渡し方です。
これにより、あたかも変数が共有されたような状態になります。

このような仕組みのため、参照渡しでは次のような性質があります。
引数 a や b を使って、変数 x や y の値を変更できる
(a や b を変更すると、x や y も変更される)。
このおかげで、あたかも x と a が、また y と b が、同じ変数を共有してい
るように見えます。


以下実行結果
;グローバル変数かわらない
(defparameter x 0)
(defun hoge (x)
  (setf x 1))
(hoge x)
x

;グローバル変数変わる
(defparameter ls '(1 2))
(defun foo (ls)
  (setf (car ls) 0))
(foo ls)
ls

;グローバル変数変わる
(defparameter ls '(1 2))
(defun foo (ls)
  (setf  (cdr ls) 0))
(foo ls)
ls

;グローバル変数変わる
(setq ls '(1 2))
(defun foo (ls)
  (setf  (cdr ls) 0))
(foo ls)
ls

;グローバル変数かわらない
(defparameter ls '(1 2))
(defun foo (ls)
  (setf ls (car ls)))
(foo ls)
ls
~                                                                                  
~                                                                                  
~                    

0 件のコメント:

コメントを投稿

About

参加ユーザー

連絡フォーム

名前

メール *

メッセージ *

ページ

Featured Posts