もうひとつのScheme入門 7.繰り返し の練習問題3 名前付きlet


問題数が多くて解くのに時間がかかってしまった。zencodingで<pre>タグを生成したら少し煩わしさが消えた気がする。(pre+br)*16とかすると一気に出てくるのが確かに癖になる気がした。このぐらいのやつだと自分でコピペの方が早いかもしれないけどなれるために使っていこうと思う。


練習問題3-1a

(define (element-remove-let lst element)
  (let loop ((lst0 lst) (result-lst ()))
    (if (null? lst0)
      (reverse result-lst)
      (let ((head (car lst0)) (rest-lst (cdr lst0)))
	(loop
	 rest-lst
	 (if (equal? head element)
	   result-lst
	   (cons head result-lst)))))))

実行結果

(element-remove-let '(1 2 3 4 5) 4)
(1 2 3 5)

エラー

;;*** ERROR: Compile Error: syntax-error: malformed let: (let 
((head (car lst0) (rest-lst (cdr lst0)))) rest-lst (if (equal?
 head element) result-lst (cons head result-lst)))
;;"(stdin)":43:(define (element-remove-let lst elem ...
;;syntax error: malformed let の場合は、let関数のカッコの位置が
;;間違っている可能性が高いかも

;;名前付きlet
;;(let 名前付きlet関数名 ((仮引数1) (仮引数2) ...) body)
;;てな感じ

練習問題3-1b

(define (element-position-let lst element)
  (let loop((lst0 lst) (i 0))
    (cond 
     ((null? lst0) #f)
     ((equal? element (car lst0)) i)
     (else (loop (cdr lst0) (+ 1 i))))))

実行結果

(element-position-let '(1 2 3 4 5) 3)
2
(element-position-let '(1 2 3 4 5) 6)
#f
;;1+
;;1+は自分で定義しないといけないようだ。
;;だけどいちいち定義するのはめんどいのでどうしたらいいかな...
;;パッケージとかまだよく分からないし...

;;#f
;;f#ではない。f#だと音階になってしまう。


練習問題3-2a

(define (my-reverse-tail lst)
    (my-reverse-rec lst '()))

(define (my-reverse-rec lst result-lst)
  (if (null? lst)
    result-lst
    (my-reverse-rec (cdr lst) 
		    (cons (car lst) result-lst))))

実行結果

(my-reverse-tail '(1 2 3 4 5))
(5 4 3 2 1)
(my-reverse-tail '())
()
;;my-sum-let
;;letでlstをlst0とすると引数の名前を間違えて無限ループってことが
;;多い。名前がやっぱりよくないのでlst-letとしたけどいまいちパッと
;;しない名前だなぁと。どんな名前がいいのかしらん。


練習問題3-2b

(define (my-reverse-let lst)
  (let loop((lst0 lst) (result-lst ()))
    (if (null? lst0)
      result-lst
      (loop (cdr lst0) (cons  (car lst0) result-lst)))))

実行結果

(my-reverse-let '(1 2 3 4 5))
(5 4 3 2 1)
(my-reverse-let '())
()

;;(cons 1 '())
;;(1)

;;(+ 1 num)
;;これでnumの値が変わると思ってしまった...
;;そういえばsetfとかしないと変わることはないね


練習問題3-2c

(define (my-sum-let lst)
  (let loop ((lst-let lst) (sum 0))
    (if (null? lst-let)
      sum
      (loop (cdr lst-let) (+ (car lst-let) sum)))))

実行結果

(my-sum-let '(1 2 3 4 5))
15
(my-sum-let '())
0

練習問題3-2d

(define (my-string-to-integer-let str)
  (let loop ((str-lst-let (string->list str)) 
	     (result-num 0))
    (if (null? str-lst-let)
      result-num
      (loop (cdr str-lst-let)
	    (+ (- (char->integer (car str-lst-let)) 48)
	       (* result-num 10))))))

実行結果

(my-string-to-integer-let "1234567890")
1234567890
(my-string-to-integer-let "")
0

練習問題3-3

(define (my-range n)
  (let loop ((num 0) (result-lst ()))
    (if (= num n)
      (reverse result-lst)
      (loop (+ 1 num) (cons num result-lst)))))

実行結果

(my-range 1)
(0 1 2 3 4 5 6 7 8 9)
(my-range 0)
()

練習問題3-4

(define (my-ave-let . lst)
  (let loop ((lst-let lst) (sum 0))
    (if (null? lst-let)
      (/ sum (length lst))
      (loop (cdr lst-let) (+ sum (car lst-let))))))

実行結果

(my-ave-let 1 2 3 4 5 6)
7/2