Created
April 21, 2015 08:32
-
-
Save nenono/c19beee35a8a2103808c to your computer and use it in GitHub Desktop.
Schemeによるリスト処理関数のサンプル
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; 整数値からfizzbuzz結果の値に変換します。 | |
(define (int->fizzbuzz x) | |
(let ((is-fizz (= (modulo x 3) 0)); 3で割り切れたらFizz | |
(is-buzz (= (modulo x 5) 0))); 5で割り切れたらBuzz | |
(let ((is-fizzbuzz (and is-fizz is-buzz))); FizzかつBuzzならFizzBuzz | |
(cond | |
(is-fizzbuzz "FizzBuzz") | |
(is-fizz "Fizz") | |
(is-buzz "Buzz") | |
(else x))))) | |
;; 指定された値までのfizzbuzzをコンソールに出力します。 | |
(define (fizzbuzz max) | |
(*> (range 1 max); 1からmaxまでの範囲の整数のリストを生成 | |
(map int->fizzbuzz); 全ての要素を整数からフィズバズ結果に変換 | |
(iter print))); 全ての要素を順にコンソール出力 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; 関数合成 | |
;; 複数の関数(f1, f2, f3...)を引数にとり、それを順に適用するような新しい関数を生成します。 | |
;; つまり、(>> f1 f2 f3) == (lambda (x) (f3 (f2 (f1 x)))) というようなイメージ。 | |
;; 可変長引数対応で複雑になっているので、実装それ自体はあまり気にしないでください。 | |
(define >> | |
(lambda fs | |
(letrec | |
((>> | |
(lambda (fs) | |
(cond | |
((null? (cdr fs)) (car fs)) | |
(else | |
(lambda (x) | |
((>> (cdr fs)) ((car fs) x)))))))) | |
(>> fs)))) | |
;; パイプライン演算子 | |
;; 関数合成に加え、関数に最初に渡す値を指定します。 | |
;; (*> x f1 f2 f3) == (f3 (f2 (f1 x))) というようなイメージ。 | |
(define *> | |
(lambda (x . fs) | |
((call-with-values | |
(lambda () (apply values fs)) | |
>>) x))) | |
;; 2引数関数の引数の順番を入れ替えます。 | |
(define (flip f) | |
(lambda (x y) (f y x))) | |
;; listを先頭から走査し、順にアキュムレーター関数fを適用していき、その蓄積を返します。 | |
;; fは2引数の関数で、第一引数に前回までの蓄積結果、第二引数に今回チェックする要素を取り、返り値として今回の蓄積結果を返します。 | |
;; 参照: [List.fold<'T,'State> 関数 (F#)](https://msdn.microsoft.com/ja-jp/library/ee353894.aspx) | |
;; カリー化形式を模倣するため、listだけは最後に別で与える形とします。 | |
(define (fold f init) | |
(letrec ((loop | |
(lambda (acc lis) | |
(cond | |
((null? lis) acc) | |
(else (loop (f acc (car lis)) (cdr lis))))))) | |
(lambda (lis) (loop init lis)))) | |
;; listを逆順にします。 | |
(define reverse | |
(fold (flip cons) '())) | |
;; listを先頭から走査し、順に関数fを適用していき、その結果を同じ順のリストにして返します。 | |
;; カリー化形式を模倣するため、listだけは最後に別で与える形とします。 | |
(define (map f) | |
(>> | |
(fold (lambda (acc x) (cons (f x) acc)) '()) | |
reverse)) | |
;; listを先頭から走査し、順に関数fを適用していき、その結果を破棄します。 | |
;; カリー化形式を模倣するため、listだけは最後に別で与える形とします。 | |
(define (iter act) | |
(fold (lambda (acc x) (begin (act x) #f)) #f)) | |
;; initからmaxまでの整数のリストを生成します。 | |
;; Scheme標準ではiota関数が知られています。 | |
(define (range init max) | |
(cond | |
((< max init) '()) | |
(else (cons init (range (+ 1 init) max))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment