named-letの練習
なんかnamed-letが分かりにくかったので書いて理解しようとした。
文字列の空白を除いて文字数をカウントする手続き
(define (str-count str) (let loop ((ls (string->list str)) (count 0)) (let ((inc (lambda (x) (+ x 1)))) (cond ((null? ls) count) ((char-whitespace? (car ls)) (loop (cdr ls) count)) (else (loop (cdr ls) (inc count))))))) ;;string-lengthだと17だけど… (str-count "ayato_p & ayato_p") ;;=> 15
named-let使うとlambdaで末尾再帰書かなくてもいいよってのが分かればいいのかな。
個人的には、取っ付きにくかったけど、わかってしまえばなんてことないので好きです。
なんとなーく使い方は分かった!!(たぶん)
あと、数のリスト*1から10進数の数字をつくる手続きも書いてみた。
数のリストから10進数の数をつくるよ!!
(define (comp-tup tup) (define (pow x y) (let iter ((a x) (b y) (c 1)) (if (zero? b) c (iter a (- b 1) (* c a))))) (let tup-iter ((t tup) (comp 0)) (cond ((null? t) comp) (else (let ((size (- (length t) 1))) (let ((exp (pow 10 size)) (x (car t))) (tup-iter (cdr t) (+ comp (* x exp))))))))) (comp-tup '(1 2 3 4)) ;;=> 1234 (comp-tup '(1 0 0 0)) ;;=> 1000 (comp-tup '(0 0 0 1)) ;;=> 1
と、ここまで書いた段階でvallogの中の人からツッコミ入った。
@ayato_p これって、文字列にして連結して数字にしたらダメなんですかwこんな感じで >(define (comp-tup tup)(string->number (apply string-append (map number->string tup))))
2013-02-13 12:17:40 via twicli to @ayato_p
@ayato_p ダメならこんな感じで >(define (comp-tup tup)(apply + (map * tup (map (pa$ expt 10)(reverse (iota (length tup)))))))
2013-02-13 12:21:13 via twicli to @ayato_p
余談1
こんな感じで再帰書こうとしたら、ダメだった…。
letに書ける手続きって、再帰しないlambdaだけなのかなー。とか。
;;前略 (let ((size (- (length tup) 1)) (pow (lambda (a b) (if (zero? b) 1 (* a (pow a (- b 1))))))) ;;後略
追記
letrecで書けた…。named-letで書ける気がするけども、そっちは良くわからない。*2
(define (comp-tup tup) (define (comp-tup-iter tup comp) (cond ((null? tup) comp) (else (let ((size (- (length tup) 1))) (letrec ((pow (lambda (a b) (if (zero? b) 1 (* a (pow a (- b 1))))))) (let ((exp (pow 10 size)) (x (car tup))) (comp-tup-iter (cdr tup) (+ comp (* x exp))))))))) (comp-tup-iter tup 0))
余談2
もともとこの手続き2つを書こうと思ったきっかけは、ProjectEulerのProblem11で、こういうデータを取り扱わないといけなかったので、なんかこれを解くための補助手続き書かないと駄目だよなーって思って書きはじめたんだけど…。
08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
最初、これは文字列で引数として受け取って、分解して云々…ってしようと思ってたんだけど、Scheme(Lisp)って「08」とか書いてあっても10進数の「8」として解釈してくれるんですね…って後で気づきました。
'((08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08) (49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00) (81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65))
これでいいらしい。。。
最初はこうしてから、どうにかパースしないといけないのかなーとか…。
'("08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08" "49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00" "81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65")
続き…(2/14追記)
letで再帰する手続き書けないなぁと書いていたら、@valvallowさんからvallogの記事に誘導されました。
2013-02-13 12:58:23 via twicli to @ayato_p
で、元々named-letについて書いてたんですけど、僕の書いていた記事中の手続きは「こう書けるよ!」的なツイートが@SaitoAtsushiさんと@valvallowさんからポンポン投げられてきました。
@ayato_p こういうときは fold 系の手続きが役に立ちます。 (define comp-tup(fold$(^[e a](+ e(* 10 a)))0))
2013-02-13 18:52:19 via web to @ayato_p
@ayato_p gauche.collectionをuseすると文字列にもfold$が使えます (use gauche.collection)(define str-count(fold$(^[e a](+ a(if(char=? e #\space)0 1)))0))
2013-02-13 19:44:24 via web to @ayato_p
@SaitoAtsushi @ayato_p 僕なりに素直に >(define(str-count str)(string-length(list->string(filter(complement char-whitespace?) (string->list str)))))
2013-02-13 20:05:50 via twicli to @SaitoAtsushi
@valvallow @SaitoAtsushi @ayato_p わー、楽しそうっ!!
2013-02-13 20:07:37 via TweetDeck to @valvallow
愚直な書き方というか、今まではこういう書き方しか知らなかったというか、まだそんなに詳しくないので勉強しなきゃなとおもいますね。
@valvallow @ayato_p よく見たら srfi-13 に string-count があった…。
2013-02-13 20:16:17 via web to @valvallow
string-count SRFI 13:String Libraries
@SaitoAtsushi @ayato_p ほんまや・・・ >(use srfi-13)(string-count "ayato_p & ayato_p" (complement char-whitespace?))
2013-02-13 20:21:34 via twicli to @SaitoAtsushi
@valvallow @ayato_p 文字セットで渡した方がちょっと短かく書けますね。 (use srfi-13)(string-count "ayato_p & ayato_p" #[\S])
2013-02-13 20:24:52 via web to @valvallow
@kazh98 @SaitoAtsushi @ayato_p たぶんこの辺の経過がURLにのるはず・・・
2013-02-13 20:22:33 via twicli to @kazh98
@valvallow @kazh98 @ayato_p ああ、元は named let の話だった…
2013-02-13 20:26:08 via web to @valvallow
勉強になりました><