2024-04-28 12:30:23 +09:00
|
|
|
|
# 20240428122916 setf setq defvar defparameter の違い
|
|
|
|
|
#common_lisp #tips
|
|
|
|
|
|
2024-04-28 17:15:03 +09:00
|
|
|
|
若干ややこしいく、前提となる知識が必要だが、
|
|
|
|
|
- defvar, defparameterはダイナミックスコープの変数(スペシャル変数)を定義する。
|
|
|
|
|
- letや未定義時のsetfはレキシカルスコープの変数を定義する。
|
|
|
|
|
|
2024-04-28 13:00:24 +09:00
|
|
|
|
グローバル変数をレキシカルに作る方法は(少なくとも標準的には)無い。 上記未定義時のsetfは期待した動作をするが、推奨されていない。
|
2024-04-28 12:45:03 +09:00
|
|
|
|
|
2024-04-28 16:45:03 +09:00
|
|
|
|
cf.
|
|
|
|
|
- [[20240428125606 ダイナミックスコープ レキシカルスコープ |ダイナミックスコープ レキシカルスコープ]]
|
|
|
|
|
- [lispguide.xml](https://google.github.io/styleguide/lispguide.xml?showone=Global_variables_and_constants#Global_variables_and_constants)
|
|
|
|
|
Common Lisp does not have global lexical variables
|
2024-04-28 13:00:24 +09:00
|
|
|
|
|
2024-04-28 14:45:04 +09:00
|
|
|
|
|
|
|
|
|
|
2024-04-28 13:00:24 +09:00
|
|
|
|
- defvar: 値が定義されていなければ定義する。上書きしようとしても存在している場合はできない(というか無視される)。
|
2024-04-28 12:30:23 +09:00
|
|
|
|
- defparameter: 定義されているかに関係なく定義する。すでに定義されていたら上書きする。
|
2024-04-28 13:00:24 +09:00
|
|
|
|
- defconstant: 定数を定義する。複数回定義しようとしたり、値を変更しようとするとエラーになる。
|
2024-04-28 12:30:23 +09:00
|
|
|
|
- setf: 定義された変数を変更するために使う。定義されていない変数を変更しようとすると、新規作成され、警告が出る。
|
|
|
|
|
- setq: 使わなくてよい。 setfはsetqの上位互換。
|
|
|
|
|
|
|
|
|
|
以下sbclをslimeで動かした時の、replでの実行結果
|
|
|
|
|
```lisp
|
|
|
|
|
;; defvar
|
|
|
|
|
(defvar b 100) ; 1回目
|
|
|
|
|
b; => 100
|
|
|
|
|
(defvar b 200) ; 2回目
|
|
|
|
|
b; => 100 ; とくにwarningなども出ず、シンプルに無視された
|
|
|
|
|
|
|
|
|
|
(setf b 300) ; setfで変えられるの?
|
|
|
|
|
b ; => 300 ; 変えらえる
|
|
|
|
|
|
|
|
|
|
;; defparameter
|
|
|
|
|
(defparameter c 1) ; 1回目
|
|
|
|
|
c ; => 1
|
|
|
|
|
(defparameter c 2) ; 2回目
|
|
|
|
|
c ; => 2 ; 変わっている
|
|
|
|
|
|
|
|
|
|
(setf c 3) ; setfで変えられるの?
|
|
|
|
|
c; => 3 ; 変えられる
|
|
|
|
|
|
|
|
|
|
;; defconstant 定数を宣言
|
|
|
|
|
(defconstant d 1); 1回目
|
|
|
|
|
d ; => 1
|
|
|
|
|
(defconstant d 2); 2回目 エラー
|
|
|
|
|
;; The constant D is being redefined (from 1 to 2)
|
|
|
|
|
;; [Condition of type DEFCONSTANT-UNEQL]
|
|
|
|
|
;; See also:
|
|
|
|
|
;; Common Lisp Hyperspec, DEFCONSTANT [:macro]
|
|
|
|
|
;; SBCL Manual, Idiosyncrasies [:node]
|
|
|
|
|
(setf d 3) ; setfしてみる これもエラー
|
|
|
|
|
;; Execution of a form compiled with errors.
|
|
|
|
|
;; Form:
|
|
|
|
|
;; (SETQ D 3)
|
|
|
|
|
;; Compile-time error:
|
|
|
|
|
;; D is a constant and thus can't be set.
|
|
|
|
|
;; [Condition of type SB-INT:COMPILED-PROGRAM-ERROR]
|
|
|
|
|
;; 定義されていない値をsetf
|
|
|
|
|
(setf e 1) ; => warning
|
|
|
|
|
;; in: SETF E
|
|
|
|
|
;; (SETF E 1)
|
|
|
|
|
;;
|
|
|
|
|
;; caught WARNING:
|
|
|
|
|
;; undefined variable: COMMON-LISP-USER::E
|
|
|
|
|
;;
|
|
|
|
|
;; compilation unit finished
|
|
|
|
|
;; Undefined variable:
|
|
|
|
|
;; E
|
|
|
|
|
;; caught 1 WARNING condition
|
|
|
|
|
(setf e 2); 2回目 ;; 同様のwarningが出る
|
|
|
|
|
e ; => 2
|
2024-04-28 17:15:03 +09:00
|
|
|
|
|
2024-04-28 15:00:24 +09:00
|
|
|
|
;; defconstant強い。letでも変えられない
|
|
|
|
|
(let
|
|
|
|
|
((d 2)))
|
|
|
|
|
;; Execution of a form compiled with errors.
|
|
|
|
|
;; Form:
|
|
|
|
|
;; (LET ((D 2)))
|
|
|
|
|
;; Compile-time error:
|
|
|
|
|
;; COMMON-LISP-USER::D names a defined constant, and cannot be used in LET.
|
|
|
|
|
;; [Condition of type SB-INT:COMPILED-PROGRAM-ERROR]
|
2024-04-28 17:15:03 +09:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;; こう書いた場合もグローバルにアクセスできる?
|
|
|
|
|
;; ダイナミックスコープならできるはず
|
|
|
|
|
(defun nazo ()
|
|
|
|
|
(defvar nazo_value 10))
|
|
|
|
|
(nazo)
|
|
|
|
|
nazo_value ; => 10 できた
|
2024-04-28 12:30:23 +09:00
|
|
|
|
```
|
|
|
|
|
|
2024-04-29 12:15:03 +09:00
|
|
|
|
### その他
|
|
|
|
|
識別子に使用可能な文字は? [変数](https://wisdom.sakura.ne.jp/programming/lisp/clisp5.html) には、
|
|
|
|
|
|
|
|
|
|
>変数名には、アルファベット、数値、記号で構成される識別子を指定します。 Common Lisp の識別子は、アルファベットの大文字小文字を区別しません。 次の記号を使うこともできます。
|
|
|
|
|
> + - * / @ $ % ^ & _ = < > ~ .
|
|
|
|
|
>
|
|
|
|
|
> ただし +1 や -20 という表記は整数として認識できるため識別子にはなりません。 +$ や 1+ は識別子として認識することができます。
|
|
|
|
|
|
|
|
|
|
と書かれている。
|
2024-04-28 12:30:23 +09:00
|
|
|
|
### Refs.
|
|
|
|
|
- [Lispで変数宣言する方法 -](https://minegishirei.hatenablog.com/entry/2023/04/17/094001)
|
2024-04-28 12:45:03 +09:00
|
|
|
|
- [Lispのダイナミック・スコープとスペシャル変数 · wshito's diary](https://diary.wshito.com/comp/lisp/dynamic-scope/)
|
2024-04-28 12:30:23 +09:00
|
|
|
|
- [「対話によるCommon Lisp入門」第2話まとめノート · wshito's diary](https://diary.wshito.com/comp/lisp/cl-dialogue/2/)
|
|
|
|
|
- [lisp - What's difference between defvar, defparameter, setf and setq - Stack Overflow](https://stackoverflow.com/a/8928038)
|