多値をreceiveで受け取らなかったら
114ページからの「手続きによるパターンの抽象化」を読み返しているとき、ふと不思議に思ったことがある。
それは、手続きtraverseを使ったmember2の定義内での、valuesの使い方。
;; traverseを用いない (define member2 (lambda (elt lis . opt) (let-optionals* opt ((cmp-fn equal?)) (define loop (lambda (l) (cond ((null? l) #f) ((cmp-fn (car l) elt) l) (else (loop (cdr l)))))) (loop lis)))) ;; member2、delete-1、assocの共通部分を取り出し、抽象化したtraverse (define traverse (lambda (fallback find-key return repeat) (lambda (elt lis . opt) (let-optionals* opt ((cmp-fn equal?)) (define loop (lambda (l) (cond ((null? l) fallback) ((cmp-fn (find-key l) elt) (return l)) (else (repeat loop l))))) (loop lis))))) ;; traverseによるmember2 (define member2/traverse (traverse #f car values (lambda (loop l) (loop (cdr l)))))
便宜的に、traverseを使って定義したmember2相当の手続きはmember2/traverseと名付けた。
このようにvaluesは、意味から考えてみると、引数で受け取った値をそのまま返す手続きとして利用されているようだ。
しかし、valuesに関する今までの知識(p85〜p88)では、こんな使い方は知らない。
つまり、(values 1)は1であり、(values (iota 5 1))は(1 2 3 4 5)であるわけね。
ホンマかいな?ってことで、実験してみた。
gosh> (equal? (values 1) 1) #t gosh> (map fact (values (iota 5 1))) (1 2 6 24 120) gosh> (+ 1 (values 1 2 3)) 2
だそうな。
3つめの結果から、要するに、多値はreceiveで受け取らない限り、必ず1個目の値が使われるわけね。