Gauche本勉強メモ(8日目)

ゆだんするとすぐ3日くらい空いちゃう。なるべく毎日やるぞ。

リストの要素を逆転するreverseを考えてみる

(define (reverse lis)
  (fold cons '() lis))

;;; もしくは
(define (reverse lis)
  (if (null? (cdr lis))
	  lis
	  (append2 (reverse (cdr lis)) (list (car lis)))))

リスト中から条件を満たす要素を返す手続きfindを考えてみる。perlgrepみたいな感じ?

(define (find condition lis)
  (if (condition (car lis))
	  (append2 (car lis) (find (cdr lis)))
	  (find (cdr lis))))

でこんな感じで書いてみた

gosh> (find (lambda (x) (< 5 x)) '(1 2 6 3))
*** ERROR: wrong number of arguments for #<closure find> (required 2, got 1)
Stack Trace:

あれ?引数が2つ必要だけど、1つしかないといわれてるっぽい。なぜ?2つ渡してるつもりだけど。
んんん、、わからん。
本を見てみると。。。
あれ?そもそもfindの定義の意味を間違えていた。条件をみたすものすべてじゃなくて条件をみたすものをひとつ返すんだった。
正解は

(define (find pred lis)
  (if (null? lis)
	  #f
	  (if (pred (car lis))
		  (car lis)
		  (find pred (cdr lis)))))

;;; もしくはcondを使って
(define (find pred lis)
  (cond [(null? lis) #f]
		[(pred (car lis)) (car lis)]
		[else (find (cdr lis))))]

しかし依然として上の引数の数でエラーになるのは何がまずいのか分からない。

練習問題

リストの長さを計算するlengthをfoldを使わずに定義する

(cdr lis)の長さに1を足せばよいかな?だとすると、(cdr lis)の長さは(length (cdr lis)なので

(define (length lis)
  (if (null? lis)
	  0
	  (+ 1 (length (cdr lis)))))

gosh> (length '(1 2 3))
3
gosh> (length '(1))
1
gosh> (length '())
0
リストの中から、条件を満たす要素だけを抜き出したリストを返すfilterを定義する

これがさっき作ろうとしたfind(のまちがえたやつ)だな

(define (filter pred lis)
  (cond [(null? #?=lis) '()]
		[(pred (car lis)) (cons (car lis) (filter pred (cdr lis)))]
		[else (filter pred (cdr lis))]))

あー、さっきのやつもなんで引数の数でエラーでてたかわかった。再帰で読んでる中の手続きの引数が足りなかったんだ。

(define (find condition lis)
  (if (null? lis)
	  '()
	  (if (condition (car lis))
		  (cons (car lis) (find condition (cdr lis)))
		  (find condition (cdr lis)))))

gosh> (find (lambda (x) (< 5 x)) '(20 4 2 7 0 1))
(20 7)
gosh> (find odd? '(20 4 2 7 0 1))
(7 1)

append2使ってるところも間違えてた。consだった。


ところで、いまだに(define hoge (x) ..って書きそうになる。elispのせいだろうなぁ。

今日はここまで