29

私はスキームを学んでいます。ラムダ式とレット式の両方を使用する方法を知っています。

ただし、ラムダを使用することのポイントを理解するのに苦労しています。ラムダでできることをletですべて行うことはできませんか?

ラムダ式がletよりも優れた選択である状況の例を見ると特に役立ちます。

もう1つ-ラムダよりもletの方が便利な状況もありますか?もしそうなら、そのような例もいいでしょう。

編集:defineとlambdaは同様のタスクを実行しているように見えるので、それらを対比することにも興味があります。


アップデート:

みんな助けてくれてありがとう。私はあなたの答えを読んだ後、ラムダ/レット/定義をもう少し調べました、そして今それをもっとよく理解しています。

クールなラムダの使用法の優れた例に出くわしました-プロシージャから無名関数を返します。たとえば、operateTwice以下のプロシージャは、プロシージャに渡されたパラメータに基づく無名関数を返します。

(define operateTwice
  (lambda (op1 op2)
    (lambda (x y)
      (op2 (op1 x y) y))))

((operateTwice * +) 2 3) ;equivalent to: (+ (* 2 3) 3), or in standard notation 2*3+3

出力:

9
4

6 に答える 6

48

Aletlambdaです。

例えば

(let ((x 1))
  body)

に翻訳することができます

((lambda (x) body) 1)

さらに、Schemeでは、すべての制御および環境構造をラムダ式およびラムダのアプリケーションで表すことができます。

したがって、Schemeに見られる多くの興味深い構造lambdaよりも厳密に強力であり、その基礎を形成します。let

defineとに関してlambdaは、トップレベルdefineがトップレベル環境にバインディングを追加します。

あなたが書くとき

(define (f x)
  body)

あなたは本当に言っています

(define f (lambda (x) body))

ネストされた定義はに変換されletrec、ラムダを使用して書き換えることもできます。

したがって、繰り返しになりますが、多くのScheme構造は、を使用して何かに変換できます。lambdaしたがって、よく理解することは非常に価値がありますlambda

于 2010-05-31T11:15:19.967 に答える
16

lambda別の関数(たとえばmap)への引数として使用する関数を作成したいが、実際には関数に名前を付けたくない場合に使用します。

たとえば、リスト内のすべての番号に42を追加する場合は、次のように実行できます。

(define (add42 x) (+ x 42))
(map add42 (list 1 2 3 4))

ただし、これを1回だけ使用する関数に名前を付けたくない場合は、次のようにすることができます。

(map (lambda (x) (+ x 42)) (list 1 2 3 4))
于 2010-05-31T11:14:43.433 に答える
5

実際には、Lambda式の省略形です。次の2つの式は同等です。

(let ((alpha 7)) (* 5 alpha))

((lambda (alpha) (* 5 alpha)) 7)

ラムダは、すべてが数学関数のように見えるべきであるという言語哲学に従います。しかし実際には、Letを使用すると、変数が多すぎる場合に何が起こっているのかを簡単に把握できます。Lambdaブロックの後に値が定義されている10個の変数を想像してみてください。それぞれの変数を変数名と一致させようとすると、変数の値を名前のすぐ隣に配置します。これは、プログラマーにとっては便利ですが、関数型にはあまり準拠していません。プログラミング哲学。

Lambdaを使用して、高階関数から関数を返すことができますが、それはできません。例えば:

(define (plus-list x)
  (cond ((number? x)
         (lambda (y) (+ (sum-n x) y)))
        ((list? x)
         (lambda (y) (+ (sum-list x) y)))
        (else (lambda (x) x))
        ))

> ((plus-list 3) 4)
10
> ((plus-list '(1 3 5)) 5)
14
> ((plus-list 'a) 5)
5

Lambdaを使用して、関数を関数に渡すこともできます。

>(map (lambda (x) (+ 1 x)) '(-1 2 -3))
(0 3 -2)
于 2011-12-17T17:06:19.643 に答える
3

lambdaは新しい無名関数を作成します。もちろん、それらを使用するたびに評価されます。

letは値の一時的な名前を作成し、letフォームで定義されたスコープで使用するために一度設定されます。

彼らは本当に非常に異なる獣です。

いくつかの例 :

(ラムダ(x)(* 5 x))

(let([x 2])(* 5 x))10(let([f(lambda(x)(* 5 x))])(f 2))10

最初のフォームは、5を掛ける関数を作成します

2番目の形式はxに2を割り当て、それを5で乗算すると、10になります。

3番目に、1の関数(5で乗算)を使用し、パラメーターとして2を使用して呼び出すと、10になります。

于 2010-05-31T11:12:00.057 に答える
3

スキームでは、プロシージャ(または関数)は、リスト、数値、文字列などのファーストクラスのオブジェクトです。リストリテラルを作成するには、次のプリミティブを使用しますlist

> (define marks (list 33 40 56))
> marks
> (33 40 56)

このように、プロシージャを作成するには、lambdaプリミティブ(または特殊な形式)を使用します。

> (define add-marks (lambda (m) (apply + m)))
> (add-marks marks)
> 129

プロシージャは抽象化の主要な形式であるため、Schemeは、新しいプロシージャを簡単にバインドできるようにするためのショートカットを提供します。define

> (define (add-marks m) (apply + m))

これを除けば、プロシージャは他のすべてのファーストクラスオブジェクトとまったく同じです。それらは引数として他のプロシージャに渡すことができ、プロシージャは別のプロシージャを生成(または返す)するために評価できます。

于 2010-05-31T11:35:40.360 に答える
1

あなたはそれをそのように考えることができます...あなたは別の関数を使用する関数を作成しますが、物事をよりモジュール化したいので、あなたがすることはあなたが最初の関数の引数として2番目の関数を呼び出すことです、そしてそれはあなたに可能性を残します別の機能が必要だと感じたときはいつでも秒を変更してください...それが理にかなっていることを願っています

于 2010-05-31T11:24:49.620 に答える