質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.62%

  • LISP

    55questions

    LISPはプログラミング言語の一種であり、関数型言語に分類されています。 特徴として、括弧を多様する独特の構文を持ちます。

  • 再帰

    28questions

    情報工学における再帰とは、プログラムのあるメソッドの処理上で自身のメソッドが再び呼び出されている処理の事をいいます。

Schemeのコードで、何故定義してある関数をlambdaで書かなければならないのか?

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 365

tochu_cha

score 6

湯浅太一著「Scheme入門」を読んでおります。
その8章の例題問題、8.2.2の解答を見て、疑問があります。

(define (diff-fmla fmla var)
  (cond ((symbol? fmla)
     (if (eq? fmla var) 1 0))
    ((number? fmla) 0)
    (else
     (case (car fmla)
       ((+) (cons '+
              (map (lambda (f) (diff-fmla f var))
               (cdr fmla))))
       ((*) (cons '+
              (map (lambda (f) (cons '* f))
               (diff-*-args (cdr fmla) var))))
       ((^) (list '*
              (caddr fmla)
              (list '^
                (cadr fmla)
                (- (caddr fmla) 1))
              (diff-fmla (cadr fmla) var)))
       ((-) (list '-
              (diff-fmla (cadr fmla) var)))))))


(define (diff-*-args fmlas var)
  (if (null? fmlas)
      '()
      (cons (cons (diff-fmla (car fmlas) var)
          (cdr fmlas))
        (map (lambda (fs) (cons (car fmlas) fs))
         (diff-*-args (cdr fmlas) var)))))


これは例えば

(diff-fmla '(+ (^ x 2) (* x 2) 'x)


を評価すると

(+ (* 2 (^ x 1) 1) (+ (* 1 2) (* x 0)))


と導関数を返す関数です。


疑問なのはまず diff-fmla 関数の

((+) (cons '+
              (map (lambda (f) (diff-fmla f var))
               (cdr fmla))))


です。この

(map (lambda (f) (diff-fmla f var))
               (cdr fmla))


の部分は

(map diff-fmla (cdr fmla) var)


と同じように思えるのですが、何故lambdaでdiff-fmlaを書かなければならないのでしょうか?
ちなみに私に思えたように書いてみると、Errorになりました。


. 次にdiff-*-args関数内の

(map (lambda (fs) (cons (car fmlas) fs))
         (diff-*-args (cdr fmlas) var))


です。mapのあとにconsを書くならば、何となく

(map cons 'a '((1) (2)))


とすれば

((a 1) (a 2))


になるように思えるのですが、実際にはこれもエラーになります。mapの後に引数を2つ取る関数(例えばcons)を置くならば、lambdaで一つ一つ書かなければならないのでしょうか?

この2ヶ所がよく納得行きません。お分かりの方、どうかよろしくご教授のほどお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+1

mapの後に引数を2つ取る関数(例えばcons)を置くならば、lambdaで一つ一つ書かなければならないのでしょうか?

質問文中のコードの範囲でざっくりいうと「はい」です。

引数を2つ取る関数の場合、原則として同じ数だけ並べた2つのリストを指定します。

(map cons '(a a a) '((1) (2) (3)))

同じ要素を繰り返す場合、circular-listで循環リストにするという手もありますが、lambdaを使ったほうが意図が明快なように思います(主観ですが)。

(use srfi-1)
(map cons (circular-list 'a) '((1) (2) (3)))

2引数の関数のうち1つの引数を固定して1引数の関数を作るには、部分適用という方法もあります。

(map (cut cons 'a <>) '((1) (2) (3)))

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.62%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • LISP

    55questions

    LISPはプログラミング言語の一種であり、関数型言語に分類されています。 特徴として、括弧を多様する独特の構文を持ちます。

  • 再帰

    28questions

    情報工学における再帰とは、プログラムのあるメソッドの処理上で自身のメソッドが再び呼び出されている処理の事をいいます。