5

私は完全な Lisp 初心者なので、優しくしてください。

[un-]宣言されていない自由変数というCLの考えに頭を悩ませています。私は次のように考えます:

(defun test ()
    (setq foo 17)
)

変数 foo を宣言し、それを 17 に設定する関数を定義します。ただし、代わりに

;Compiler warnings :
;  In TEST: Undeclared free variable FOO

私の実際の例はもう少し大きくなります。私のコード(スニペット)は次のようになります:

(defun p8 ()
    ;;; [some other stuff, snip]

    (loop for x from 0 to (- (length str) str-len) do
        (setq last (+ x str-len))           ; get the last char of substring
        (setq subs (subseq str x last))     ; get the substring
        (setq prod (prod-string subs))      ; get the product of that substring
        (if (> prod max)                    ; if it's bigger than current max, save it
            (setq max prod)
            (setq max-str subs)
        )
    )

;;; [More stuff, snip]
)

そしてそれは私に与えます:

;Compiler warnings for "/path/to/Lisp/projectEuler/p6-10.lisp":
;   In P8: Undeclared free variable LAST (2 references)
;Compiler warnings for "/Volumes/TwoBig/AllYourBits-Olie/WasOnDownBelowTheOcean/zIncoming/Lisp/projectEuler/p6-10.lisp" :
;   In P8: Undeclared free variable PROD (3 references)
;Compiler warnings for "/Volumes/TwoBig/AllYourBits-Olie/WasOnDownBelowTheOcean/zIncoming/Lisp/projectEuler/p6-10.lisp" :
;   In P8: Undeclared free variable SUBS (3 references)
;Compiler warnings for "/Volumes/TwoBig/AllYourBits-Olie/WasOnDownBelowTheOcean/zIncoming/Lisp/projectEuler/p6-10.lisp" :
;   In P8: Undeclared free variable =

はい、はい、私はあまりにも多くの中間変数を使用していることに気付きましたが、CL の世界で人気があるように、すべてを最小限の型付き文字に圧縮することに夢中になる前に、何が起こっているのかを理解しようとしています。

それで、とにかく...誰かが次のことを説明できますか:

  • Lispはどのような条件で変数を「宣言」しますか?
  • (...)上記の変数のスコープは、setqステートメントの囲み以外ですか?! (... (setq ...) ...)(つまり、変数が有効であり、 の外側の括弧 1 レベルからすべてのスコープが設定されていることを期待しますsetq。いいえ?
  • Undeclared free variableメッセージを誤解していますか?
  • あなたが提供したい他のヒントは、ここで何が起こっているのかをよりよく理解するのに役立ちます.

注: 私は、C、Java、Javascript、Obj-C、および関連する手続き型言語の専門家です。関数型プログラミングは違うと思います。今のところ、私は構文に取り組んでいます。

ありがとう!

PSそれが問題であればdefun p8、テキストファイル(TextMate)にあり、私はそれを実行していClozure CLます。うまくいけば、それは問題ではありません!

4

3 に答える 3

10

Lisp では、変数はdefparameterorを使用して宣言できますdefvar

(defparameter var1 5)
(defvar var2 42)

これにより、グローバル (動的) 変数が生成されます。

との違いは、defvar既存の変数を再初期化しないことです。defparameterdefvar

ローカル (レキシカル) 変数は、 or (変数を順番に初期化する)などを使用して導入されます。letlet*

宣言されていない自由変数とは、使用されているコンテキストでバインドされていない変数を使用した (ここではsetq-ed) ことを意味します。その後、宣言される可能性がありますが、おそらくグローバル (動的) 変数として宣言されます。この結果、宣言されていない変数を複数の関数で同じ名前で使用すると、すべての関数で同じ変数を参照することになります。

コードは次のように記述できます。

(loop for x from 0 to (- (length str) str-len) do
    (let* ((last (+ x str-len))         ; get the last char of substring
           (subs (subseq str x last))   ; get the substring
           (prod (prod-string subs)))   ; get the product of that substring
      (if (> prod max)                    ; if it's bigger than current max, save it
          (setq max prod)
          (setq max-str subs))))

ループの変数バインディング プロパティを使用して、次のように記述することもできます。

(loop for x from 0 to (- (length str) str-len)
      for last = (+ x str-len)
      for subs = (subseq str x last)
      for prod = (prod-string subs)
      when (> prod max) do
          (setq max prod)
          (setq max-str subs))
于 2013-07-13T07:02:09.237 に答える
5

Lisp では、変数宣言はさまざまな方法で実行できます。最も注目すべきものは次のとおりです。

  • と を使用してグローバル (適切にはspecialと呼ばれます) 変数を宣言defparameterします。defvar
  • 、、、、およびその他のバインディング形式でletローカル変数を宣言するlet*multiple-value-binddestructuring-bind
  • 関数の引数として

CLtL2など、多くの場所でその範囲について読むことができます。

setq/setfは変数宣言演算子ではなく、その名前が示すように変数変更演算子です。

PS。対話モードでは、一部の実装では DWIM アプローチを使用し、宣言されていない変数を設定しようとすると、舞台裏で変数を特別なものとして宣言しますが、これは純粋に便宜上のものです。

于 2013-07-13T07:01:35.570 に答える
4

Common Lisp HyperSpec (基本的には HTML 形式の Common Lisp 標準) は次のように述べています。

http://www.lispworks.com/documentation/HyperSpec/Body/s_setq.htm

変数に値を割り当てます。

したがってSETQ、変数に値を割り当てるだけです。それらを宣言しません。

変数の定義はDEFVAR、 、DEFPARAMETER、 ...でグローバルに行われます。

(defparameter *this-is-a-global-dynamic-variable* 'yep)

変数の定義はDEFUNLETLET*LOOP、およびその他多数でローカルに行われます。

(defun foo (v1 v2)
  ...)

(let ((v1 10)
      (v2 20))
  ...)

(loop for v1 in '(10 30 10 20)
      do ...)

これは基本的な Lisp であり、紹介を読むと役立ちます。私がお勧めします:

http://www.cs.cmu.edu/~dst/LispBook/

上記の本は無料でダウンロードできます。

さらに、上記の Common Lisp Hyperspec は、Common Lisp の定義を提供し、さまざまな機能 (DEFUN、LOOP、DEFPARAMETER、...) を詳細に説明しています。

于 2013-07-13T07:02:18.877 に答える