15

私はついに関数型言語(emacs lisp)の学習を開始しました。これにより、関数とフロー制御などの特殊な形式が明確に区別されます。

特殊な形式が関数と区別される基本的/理論的な理由はありますか?機能を提供する言語はありますifか?

ありがとう

4

7 に答える 7

13

熱心な評価では区別が必要です。遅延評価を行う言語 (つまり、Haskell) 関数にすることができます。

Eager Evaluation: 関数の引数は関数を呼び出す前に評価され、結果のみが関数に渡されます。

遅延評価: 関数の引数は、アクセスされた場合にのみ評価されます。

于 2010-02-10T22:24:42.873 に答える
8

が通常の関数である場合、両方ifの引数 ( then形式else 形式)は関数を呼び出すに評価されます。これが関数評価の規則であるためです。すべての引数を評価して値を生成し、その値のシーケンスを次のように提供します。リストの最初のシンボルで指定された関数への引数。if

代わりに、ifあなたがしたいことは、両方ではなく、正確にthen フォームelse フォームの 1 つを評価することです。どちらか一方の評価を抑制するには、マクロまたは特別なフォームが必要です。

于 2010-02-10T22:31:49.583 に答える
3

Emacs Lisp や Common Lisp などの言語では、特殊なフォームは組み込みの言語構造です。それらには、通常の関数が呼び出す異なる評価規則があります。通常の関数呼び出しでは、すべての引数が評価されます。したがって、IF を通常の関数として記述することはできません。条件によって、どの句が評価されるかが決まります。また、通常、独自の特殊フォームを作成することはできません。Common Lisp では、特殊フォームを定義するための言語構造はありません (ただし、個々の実装では既存のものを何らかの方法で実装する必要があります。これはマクロにつながります。マクロを使用すると、構文変換を記述できます。ある式を別の式に変換します. IF をマクロとして書けるようにするには, 変換されたコードに使用できる別の条件付きフォームが必要です. Lisp は基本的な構造として条件式を提供します. Let'

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))
于 2010-02-11T12:56:08.480 に答える
1

完全を期すために: たとえば、Pico言語には特別な形式はなくif、基本的な関数ですが、Pico は Scheme に触発されており、デフォルトで熱心な評価を行っています。

スキームでは、次のように書くことができます

(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

Pico でこれを扱いやすくしているのは、「自動的に」遅延される機能引数を取る機能パラメーターを定義できることです。これは、ラムダ内でラッピングを自分で行う必要がないことを意味します。したがって、Pico は熱心な評価を行いますが、必要に応じて遅延評価を行い、特別なフォームの必要性を回避します。

したがって、関数パラメーターを使用したスキーム構文では、ブール値を次のようにエンコードできます。

(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定義できます。notwhilefor

于 2010-02-11T12:20:29.360 に答える
1

簡単な答え: いいえ。

詳細な回答: (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]> 
于 2010-02-11T09:36:18.660 に答える
0

Scala ではif、名前による呼び出し引数を使用して、正しい副作用評価でモデル化することができます。

def If[A](cond : Boolean, truePart : => A, falsePart : => A) = if (cond) truePart else falsePart

これらの機能は、多くの新しい制御構造をモデル化するためにも使用できます。

于 2010-02-11T16:00:53.583 に答える
0

IF は、ラムダ計算や Algol のように、名前による呼び出しのセマンティクス (遅延評価) を持つ関数型言語の関数である可能性があります。実際、それは、コンピューティングの同等の基盤としてのチューリング マシンとラムダ計算の関係の中心にあると思います。ただし、副作用 (変数への代入など) を持つ言語では、物事がいつ起こるかが重要であるため、あまり役に立ちませ

于 2010-03-15T18:20:17.907 に答える