多値メモ
多値のメモ。
とりあえずMzSchemeのデフォルトで使えるのが、
(call-with-values (lambda () (values 2 3)) (lambda (a b) (list a b)))
valuesで多値を投げて、lambdaで受け取る。
SRFI-8で定義されてるレシーバマクロを使うと、ちょっと短く書ける。
(require (lib "8.ss" "srfi")) ; MzScheme用 (receive (a b) (values 1 2) (list a b))
短くなった。
take-dropなるものを作ってみたら、
(define (take-drop l n) (cond ((null? l) (values '() '())) ((zero? n) (values '() l)) (else (receive (t d) (take-drop (cdr l) (- n 1)) (values (cons (car l) t) d))))) (receive (a b) (take-drop (iota 10) 5) (list a b)) ; ((0 1 2 3 4) (5 6 7 8 9))
案外めんどくさかったり。
で、もうちょっと調べてみると
(receive (a b) (split-at (iota 10) 5) (list a b)) ; ((0 1 2 3 4) (5 6 7 8 9))
SRFI-1にsplit-atがあったりして、ちょっと悲しくなったり。
んじゃ多値ってどうなってんだ!?という疑問が湧いてくるので、作ってみる。
(define (values . v) v) (define (call-with-values v f) (apply f (v)))
valuesはリストになっちゃってるので、工夫したほうがよさげ。
もうcall-with-valuesとかreceiveとか呼ぶの面倒過ぎるので、
(define (take-drop l n) (cond ((null? l) (list '() '())) ((zero? n) (list '() l)) (else (apply (lambda (t d) (list (cons (car l) t) d)) (take-drop (cdr l) (- n 1)))))) (apply (lambda (a b) (list a b)) (take-drop (iota 10) 5)) ; ((0 1 2 3 4) (5 6 7 8 9))
これでいいんじゃね。
するっと、Haskellのx:xsが実装出来そうな予感がしてくる訳。
(define (head l) (apply (lambda (x . xs) x) l)) (define (tail l) (apply (lambda (x . xs) xs) l)) (head '(1 2 3 4 5)) ; 1 (tail '(1 2 3 4 5)) ; (2 3 4 5)
おぉ!!
で、apply使わなくてもいいんじゃねぇかという話題が出てくる。
(define (take-drop l n cont) (cond ((null? l) (cont '() '())) ((zero? n) (cont '() l)) (else (take-drop (cdr l) (- n 1) (lambda (t d) (cont (cons (car l) t) d)))))) (take-drop (iota 10) 5 (lambda (x y) (list x y))) ; ((0 1 2 3 4) (5 6 7 8 9))
継続渡しスタイルで多値が書けるらしい。valuesよりは断然楽。
ほほぅ。おもろい。
そんなメモでした。