一般的なLISPのブール値のリストをどのように削減しますか?
-
13-10-2019 - |
質問
値のリストを考えると、すべての要素がゼロではない場合は、リストをtに削減したいと思います。これは私にエラーを与えます:
(apply #'and (get-some-list))
これもそうです:
(reduce #'and (get-some-list))
これは私が思いついた最高のものです:
[11]> (defun my-and (x y) (and x y))
MY-AND
[12]> (reduce #'my-and '(T T T T T))
T
[13]> (reduce #'my-and '(T T T T NIL))
NIL
なぜ「#」と「無効なのですか?一般的なLISPでこれを行うためのより慣用的な方法はありますか?
解決
#'and
なぜなら無効だから and
機能ではなくマクロです。
Lambdaを使用して、名前付き関数を定義する必要があります。
(reduce (lambda (x y) (and x y)) (get-some-list) :initial-value t)
似たようなショートカットはありません #'
けれど。
または、使用することもできます every
識別機能を述語として。
他のヒント
すべての関数を使用できます。
(every #'identity '(T T T T T)) -> T
と
(every #'identity '(T T T T NIL)) -> NIL
おそらく最も効率的な方法は、ループを使用することです。
(loop for element in '(T T T T nil) always element) -> NIL
利点は、リスト要素上の関数呼び出しが必要であることです。
#'
式の読み取り中に関数に拡大する読み取りマクロです。それで #'and
IS(関数と)。
機能について説明します: http://www.lispworks.com/documentation/hyperspec/body/s_fn.htm
関数は関数名またはLambda式を取り、対応する関数オブジェクトを返します。
ここで定義されています: http://www.lispworks.com/documentation/hyperspec/body/m_and.htm
それはそれを言っており、機能ではなくマクロです。結果は、機能が機能しないため、(関数と)機能しないことです。機能が必要であり、対応する関数オブジェクトを返すマクロではありません。 SEPP2Kが彼の答えで説明しているように、Lambdaを使用して関数を作成し、マクロとその関数内を使用できます。マクロは値として合格することはできず、後でFuncallを介して呼び出されるか、適用します。これは機能でのみ機能します。
このソリューションは次のように書かれています
(reduce (lambda (x y) (and x y)) (get-some-list))
ラムダは拡張するマクロです (lambda (...) ...)
の中へ (function (lambda (...) ...))
.
上記は本当に:
(reduce (function (lambda (x y) (and x y))) (get-some-list))
と書くことができます
(reduce #'(lambda (x y) (and x y)) (get-some-list))
一般的なLISPは、値と関数の名前空間の間に違いをもたらすため、機能が必要です。値による引数として関数を渡す必要がある削減。したがって、関数名空間から関数を取得する必要があります。これは関数の目的です。関数オブジェクトを渡すときはいつでも、関数名空間からそれを取得する必要があります。
たとえば、ローカル関数の場合:
(flet ((my-and (x y) (and x y)))
#'my-and)
(関数(Lambda ...))に拡大する利便性マクロとしてのLambdaは、共通のLISPの設計中に追加されました。
通常の関数でのみ「シャープクオート」記号を使用できます。
Note that only ordinary functions can be quoted with #’. It is an error to
quote a macro function or special function this way, or to quote a symbol with
#’ if that symbol does not name a function.
> #’if
Error: IF is not an ordinary function.