結城浩のSICP日記 RSSフィード

2006-05-16

list* list* - 結城浩のSICP日記 を含むブックマーク

list*と同じ機能を持つmylist*という関数を定義しました(練習)。

(mylist* 1 2 3) #=> (1 2 . 3)
(mylist* 1)     #=> 1
(mylist*)       #=> ()

結城のプログラムは以下です。

(define (mylist* . xs)
  (cond ((null? xs) '())
        ((null? (cdr xs)) (car xs))
        (else
          (cons (car xs) (apply mylist* (cdr xs))))))

疑問:任意個数の引数を渡すとき、applyを使うしかないのでしょうか。たとえば(mylist* . (cdr xs)) みたいな感じにできないものかと。

追記:shiroさんからコメントをいただきました。「applyが「任意個数の引数を渡すプリミティブ」だと考えた方が良いでしょう」とのこと。なるほど、なるほど。いつもありがとうございます。

追記:適用可能なオブジェクトは微妙に関連しそうな話題。参考:object-apply と reader macro

define-syntax でユニットテスト define-syntax でユニットテスト - 結城浩のSICP日記 を含むブックマーク

tomapdさんが、define-syntax でユニットテストというエントリで、マクロの素敵な使い方をご紹介している。なるほど、なるほど。重複している部分を見つけ、さくりとマクロ化できたら楽しそうですね。

Schemeに限らないけれど、(プログラムがデータになっている)Lispの強みの一つはマクロにあるのだと思っています。

自然対数の底e 自然対数の底e - 結城浩のSICP日記 を含むブックマーク

自然対数の底eを計算してみます。特に工夫なし。

(use srfi-42)

(define (factorial n)
  (cond ((<= n 0) 1)
        (else (* n (factorial (- n 1))))))

(define (approx-e n)
  (cond ((< n 0) 0)
        (else (+ (/ 1 (factorial n))
                 (approx-e (- n 1))))))

(do-ec (: n 1 20)
  (print (approx-e n)))

実行結果です。

2
2.5
2.6666666666666665
2.708333333333333
2.7166666666666663
2.7180555555555554
2.7182539682539684
2.71827876984127
2.7182815255731922
2.7182818011463845
2.718281826198493
2.7182818282861687
2.7182818284467594
2.71828182845823
2.718281828458995
2.718281828459043
2.7182818284590455
2.7182818284590455
2.7182818284590455

shiroshiro2006/05/17 12:45> 疑問:任意個数の引数を渡すとき、applyを使うしかないのでしょうか。
はい。「使うしかない」というよりも、applyが「任意個数の引数を渡すプリミティブ」だと考えた方が良いでしょう。何らかのsyntax sugarを作って、それをapplyを使う形に展開するということが考えられますが、元のSchemeではsyntax sugarもprefixになってしまうのであまり変わらないかと。S式の範囲を逸脱するなら少し見やすい形があるかもしれませんが。
なお (mylist* . (cdr xs)) は定義により (mylist* cdr xs) と同じなので、使えません。

hyukihyuki2006/05/17 14:21shiroさん、いつもありがとうございます。「applyがプリミティブ」にすごく納得しました。言われてみれば確かに…。うーむ。

トラックバック - http://sicp.g.hatena.ne.jp/hyuki/20060516