16

Practical Common Lispの本の第3章には、SQLのようなselect関数とwhere関数の例があります。これを簡略化したものを次に示します。

(defun where (x) 
   #'(lambda (item)
     (> item x)))

そしてそれはこのように使用されます:

(remove-if-not (where 2) (list 1 2 3 4))

この本の前半で、#'シーケンスは、評価を必要とする変数ではなく、関数名が後に続くことを示すために使用されると説明されています。なぜここで必要なのかわかりません。where私はそれなしで関数を実装しようとしました、そしてそれは同様に働きました:

(defun where (x) 
   (lambda (item)
     (> item x)))

私はそれをグーグルで検索してみましたが、ご想像のとおり、このような一連の文字では、あまり有益な検索ではありませんでした。そして、私はこのことの名前を知りません。上記のコードで必要になる特別な理由はありますか?

4

2 に答える 2

14

これは、標準のマクロ文字「シャープ」の後に「シングル クォーテーション」が続くハイパースペックの正確なページです。

簡単にするために、このリーダー マクロを展開して、次のフォームを(function <form>)s 式で囲みます。これにより、フォームが呼び出し可能であることをパーサーに効果的に伝えます。

lambdaは既に含まれているコードを生成するマクロですが、(function <form>)歴史的に一貫性を保つために、シャープ + クォートを使用してリーダー マクロから取得される代替形式もよく使用されます。

ここでは、コモンリスプでラムダ式を書く(別のStackOverflowの質問)で、特定のケースを詳細にカバーしています(lambda <form>)

于 2012-12-24T13:42:22.877 に答える
6

注:*print-pretty*NILこれらの例です。

(defun where (x) 
  #'(lambda (item)
      (> item x)))

上記の関数whereでは、無名関数を作成し、それをクロージャー (関数と の変数バインディングX) として返しています。値として返すので、 と書く必要があります(FUNCTION (LAMBDA ...))#'(lambda ...)は短い記法ですが、同じ結果になります - リーダーマクロを使用し#'ます:

CL-USER 74 > (read-from-string "#'(lambda (foo) (1+ foo))")
(FUNCTION (LAMBDA (FOO) (1+ FOO)))

次のように書くこともできます。

(defun where (x) 
  (lambda (item)
    (> item x)))

Common Lisp の定義中に、上記のコードを記述できるように追加されました。形も同じです(function (lambda ...))。Common Lisp ではLAMBDAマクロであり、マクロに展開されます。

CL-USER 75 > '(lambda (foo) (1+ foo))
(LAMBDA (FOO) (1+ FOO))

CL-USER 76 > (macroexpand '(lambda (foo) (1+ foo)))
(FUNCTION (LAMBDA (FOO) (1+ FOO)))
T

はマクロLAMBDAであり、評価者がそれを のように見ると(lambda ...)、フォームをフォームに展開し、(function (lambda ...))評価されます。

FUNCTIONは特別な形式であり、評価者がそれを見ると関数オブジェクトを返します - その場合(function (lambda (foo) (1+ foo)))、無名関数をオブジェクトとして返します:

CL-USER 77 > (function (lambda (foo) (1+ foo)))
#<anonymous interpreted function 406000761C>

つまり、これが(function (lambda ...))関数オブジェクトを取得するための実際の s-expression 表記であり、#'(lambda ...)(リーダー マクロを介して) または(lambda ...)(マクロを介して) どちらも Lisp ソース コードの短い表記であることがわかります。プログラマーが長い形式を使用するのは珍しいことです。ほとんど (99.999%) は、ソース コードで短い表記の 1 つを使用します。

ところで: エバリュエーターがfunctionこのような関数の名前を囲んでいるのを見た場合(function sin)、関数バインディングを検索し、対応する関数オブジェクトを返します。

CL-USER 78 > (function sin)
#<Function SIN 4110083C6C>
于 2012-12-24T14:50:28.607 に答える