特殊な形式ではなく、適切な機能をすることができた場合
-
19-09-2019 - |
質問
場合、私は最終的に関数型言語を学び始めた(EmacsはLISP)、それが機能して、このようなフロー制御などの特殊な形の間の明示的な区別を、たとえばます。
なぜ特別な形式は関数とは区別される基本的な/理論的な理由はありますか?すべての言語は、機能if
を提供していますか?
おかげ
解決
先行評価と区別は、遅延評価(すなわちハスケル)で言語を必要とされます。関数にすることもできます。
先行評価:関数の引数が評価され、のの関数を呼び出して、結果だけが関数に渡されます。
の前に。遅延評価:関数の引数があれば評価され、それらがアクセスされた場合にのみ、
。他のヒント
if
の引数の両方、その後、通常の関数であった場合-the は、フォームと他のフォームの-would の両方のが評価され、の前にの、if
関数を呼び出すことがありますので、 機能評価するのルール:評価のすべての引数値を生成するために、リスト内の最初の記号で指定された機能の引数として値の配列を提供します。
その代わり、if
で何がやりたいことは正確に一つのの後、を形成し、の他のフォームのではなく、両方の評価です。どちらか一方の評価を抑制するために、あなたは、どちらかのマクロまたは<のhref =「http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_s.htm#special_form」のrel = "nofollowをnoreferrer必要「>特別なフォームでます。
のEmacs LispとCommon Lispのような言語では、特別なフォームが内蔵されている言語構造。彼らは、通常の関数呼び出し異なる評価規則を持っています。通常の関数呼び出しのために、すべての引数が評価されます。だから、あなたは、通常の関数としてIFを書き込むことはできません - 条件が評価されますどの句を決定します。また、通常、あなたはあなた自身の特別なフォームを作成することができません - Common Lispの中で特別な形式を定義するための言語構造が存在しない(個々の実装は、何らかの形で、既存のものを実装している必要がありますが、これはマクロにつながるのマクロを使用すると、構文の変換を書くことができます。それはまた別の一つに一つの式を変換します。マクロとして、あなたは変換コードを使用することができ、他の条件のフォームを、持っている必要がある場合は書くことができるようにするために。Lispは、基本的な構築物として条件文を提供します。のは、CONDは、このような基本的な構造であると仮定しましょう、あなたはCONDの使用にIFを拡大することができます。
Common LispではマクロとしてMY-IFます:
(defmacro my-if (condition true-clause false-clause)
`(cond (,condition ,true-clause)
(t ,false-clause)))
だから、
(my-if (foo-p) 'one 'two)
タグに拡大します
(cond ((foo-p) 'one)
(t 'two))
は、完全を期すため:例えばピコの言語には、特別な形式が存在しない、とif
ですプリミティブの関数のピコは、スキームに触発され、デフォルトで先行評価を持っている間ます。
(define (true t f)
(t))
(define (false t f)
(f))
(define (function_if c t e)
(c t e))
し、
(function_if true (lambda () 'true) (lambda () 'false))
==> true
ピコで、この管理しやすくなり何が定義できるということです。の機能パラメータの「自動的に」遅れで表示されていた機能の引数を取ること。これは、あなたがラムダの内側に自分でラッピングを行う必要がないことを意味します。ピコは、したがって、先行評価を持っていますが、オンデマンドで遅延評価を持つ、特殊な形式の必要性をバイパスします。
だから、機能的パラメータを持つSchemeの構文で、あなたのようにブールをエンコードすることができます:
(define (true (t) (f))
(t))
(define (false (t) (f))
(f))
なった場合は、次に機能します:
(define (function_if c (t) (e))
(c (t) (e)))
と
(function_if true 'true 'false)
==> true
別の例として、関数and
の定義は(define (and p (q)) (p (q) false))
ある。
同様に、あなたはブールの上記のエンコーディングを使用して、関数として... or
、not
、while
、for
を定義することができます。
短い答え:いいえ。
ロング(ER)の答え:(IF ...)あなたは、引数の評価順序を制御することが必要です。 Lispは、熱心な言語であることは関数内でこれを行うことはできません。
回避策:マクロでそれを行う:
(defmacro _if (cnd true false)
(let ( (gcond (gensym))
(gresp (gensym)))
`(let ( (,gcond ,cnd) ;`#quotes
(,gresp nil))
(and ,gcond (setf ,gresp (multiple-value-list ,true)))
(and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
(values-list ,gresp))))
例
[dsm@localhost:~]$ clisp -q
[1]> (defmacro _if (cnd true false)
(let ( (gcond (gensym))
(gresp (gensym)))
`(let ( (,gcond ,cnd) ;`#quotes
(,gresp nil))
(and ,gcond (setf ,gresp (multiple-value-list ,true)))
(and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
(values-list ,gresp))))
_IF
[2]> (_if (= 1 1) (+ 2 3) "bar")
5
[3]> (_if (= 1 2) (+ 2 3) "bar")
"bar"
[4]>
スカラ座では、コール・バイ・名引数を使用して、正しい副作用の評価をif
をモデル化することが可能です。
def If[A](cond : Boolean, truePart : => A, falsePart : => A) = if (cond) truePart else falsePart
これらの機能は新しい制御構造の多くをモデル化するために使用することができ、同様を。
IFは、ラムダ計算やアルゴルのように、コール・バイ・名セマンティクス(遅延評価)を持つ関数型言語での関数である可能性があります。ある実際に、私はチューリング機械とラムダとの間の関係の中心で、考えますコンピューティングのための同等の基礎として計算する。これは、のときの事が重要である起こります。
しかし、(変数への代入のような)副作用を持つ言語では、多くの使用ではありません