#:g1: SRFI-1のbreakの使いどころ

Posted 2021-06-16 00:48:14 GMT

kyannyさんのサルでもわかる L-99 の P09を読んで、これはSRFI-1breakがうまくはまりそうな例だと思ったので試してみました。

SRFI-1のbreakとは、ある条件が成立するところを境にリストを二つに分け、それを多値で返すというものですが、個人的にはどこで使うんだろうという印象を持っていました。

(ql:quickload "srfi-1") ;ultralisp

(srfi-1:break (lambda (x)
                (not (equal 'a x)))
              '(a a a a b c c a a d e e e e))(a a a a)
  (b c c a a d e e e e)

breakを使えば、L-99のP09 packは、下記のように書けます。

(defun pack (list)
  (etypecase list
    (null '())
    (cons (multiple-value-call (lambda (head tail)
                                 (cons head (pack tail)))
            (srfi-1:break (lambda (x)
                            (not (equal (car list) x)))
                          list)))))

(pack '(a a a a b c c a a d e e e e))((a a a a) (b) (c c) (a a) (d) (e e e e))

#| ※3832840949 ;2021-06-16T2302 追記
一致しないもので二分するbreakより一致したもので二分するspanの方が素直ではないかとのご指摘を頂きました。確かに!

(defun pack (list)
  (etypecase list
    (null '())
    (cons (multiple-value-call (lambda (head tail)
                                 (cons head (pack tail)))
            (srfi-1:span (lambda (x)
                           (equal (car list) x))
                         list)))))

(pack '(a a a a b c c a a d e e e e))((a a a a) (b) (c c) (a a) (d) (e e e e))

※3832840949 ;2021-06-16T2302 追記 |#

SRFI-1はSchemeが本家本元なので、一応Racket(Scheme)でも書いてみました。

(require srfi/1)

(define (pack list) (if (null? list) '() (call-with-values (λ () (break (λ (x) (not (equal? (car list) x))) list)) (λ (head tail) (cons head (pack tail))))))

(pack '(a a a a b c c a a d e e e e)) → '((a a a a) (b) (c c) (a a) (d) (e e e e))

L-99の元ネタはPrologのP-99なのですが、P-99の模範回答でもbreakと同等の機能の下請け述語を定義してつかうようです。

ということで、なんとなくShenのProlog機能でbreakを定義してpackを書いてみました。

(defprolog break
  Item [] [] [] <--;
  Item [X|Xs] [] [X|Xs] <-- (when (not (= Item X)));
  Item [Item|Xs] [Item|Ps] Ys <-- (break Item Xs Ps Ys);)

(defprolog pack [] [] <--; [Item|Xs] [Ps|Zs] <-- (break Item [Item|Xs] Ps Ys) (pack Ys Zs);)

(prolog? (pack [a a a a b c c a a d e e e e] Xs) (return Xs)) → [[a a a a] [b] [c c] [a a] [d] [e e e e]]

まとめ

L-99に取り組み始めたのは、かれこれ14年前ですが、いまだに完遂していません……。


HTML generated by 3bmd in LispWorks 7.0.0

comments powered by Disqus