2

次のことをするとどうなりますか?

(define ((func x) y)
    (if (zero? y)
        ((func x) 1)
        12))

私はこれができることを理解しています:

(define curried (func 5))

そして今、私はカレーを使うことができます。私が興味を持っているのは、関数の定義です。ラインはありますか

((func x) 1)

xを引数として新しいラムダを作成し、それを1で呼び出しますか?それとも、それよりも賢く、既存のものを再利用するだけですか。(たとえば、私がそうする場合(curried 0)、その((func x) 1)行は次のようになります(curried 1)-PLAIスキームはこれを行いますか?)

4

3 に答える 3

8

スキーム標準では、次のように指定されています。

(define (f x) 42) is short for (define f (lambda (x) 42)) .

自然な (非標準の) 一般化は、次のことを意味します。

(define ((f x) y) (list x y)) is short for (define (f x) (lambda (y) (list x y)))
                which is short for (define f (lambda (x) (lambda (y) (list x y))))

それをテストするために、DrScheme の例を試してみましょう。

DrScheme へようこそ、バージョン 4.1.3.3-svn5dec2008 [3m]。言語: モジュール; メモリ制限: 384 メガバイト。

(定義 ((fx) y) (リスト xy)) (f 1)

((f 1) 2) (1 2)

一時的な値に名前を付けると、何が起こるかを簡単に確認できます。

(定義 h (f 1)) (h 2) (1 2) (h 3) (1 3)

DrSchemeには「PLAIスキーム」が実装されているので、このショートカット表記を継承していると思います。

于 2008-12-11T15:01:35.797 に答える
2

私がスキームを扱ってからかなり時間が経ちましたが、この記事が役に立つかもしれません。ラムダ式の暗黙的なカリー化された定義を可能にする 2 つのマクロ c-lambda と c-define の実装について説明します。

于 2008-12-10T20:03:51.910 に答える
0

soegaard の答えは正しいです。これは伝統的な展開です。しかし、drscheme はスマートです。

次のコードは、実行時に同等であることがわかりました。

元のソース:

(define ((substitute lv value) e)
  (cond [(LogicVar? e)
     (type-case LogicVar e
       [lv-any (id) (if (symbol=? id (lv-any-id lv))
                value
                e)]
       [lv-cons (f r) 
            (lv-cons ((substitute lv value) f)
                 ((substitute lv value) r))])]
    [(cons? e)
     (cons ((substitute lv value) (car e))
           ((substitute lv value) (cdr e)))]
    [else e]))

最適化の試み:

(define (substitute lv value)
  (local ([define inner
        (lambda (e)
          (cond [(LogicVar? e)
             (type-case LogicVar e
               [lv-any (id) (if (symbol=? id (lv-any-id lv))
                    value
                    e)]
               [lv-cons (f r) 
                (lv-cons (inner f)
                     (inner r))])]
            [(cons? e)
             (cons (inner (car e))
               (inner (cdr e)))]
            [else e]))])
    inner))

この関数を頻繁に (1 回だけでなく複数回) 使用するコードは、両方のバージョンで 1800 ミリ秒で実行されます。さらに興味深いことに、このバージョン (何が起こっているかを視覚化したもの):

(define (substitute lv value)
  (local ([define inner
        (lambda (e)
          (cond [(LogicVar? e)
             (type-case LogicVar e
               [lv-any (id) (if (symbol=? id (lv-any-id lv))
                    value
                    e)]
               [lv-cons (f r) 
                (lv-cons ((substitute lv value) f)
                     ((substitute lv value) r))])]
            [(cons? e)
             (cons ((substitute lv value) (car e))
               ((substitute lv value) (cdr e)))]
            [else e]))])
    inner))

2000 ミリ秒で実行されます。したがって、substitute 内での replace の呼び出しがそれぞれラムダを作成していた場合、確実に速度が低下しますが、ショートカット表記の場合はそうではないようです。

于 2008-12-11T17:46:42.203 に答える