#:g1: flexi-streamsの紹介

Posted 2014-05-18 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の139日目です。

flexi-streamsとはなにか

 flexi-streamsは、bivalent stream(キャラクタでもバイトでも読めるストリーム)を実現するライブラリです。

パッケージ情報

パッケージ名flexi-streams
Quicklisp
プロジェクトサイトFLEXI-STREAMS - Flexible bivalent streams for Common Lisp
CLiKihttp://cliki.net/flexi-streams
Quickdocshttp://quickdocs.org/flexi-streams

インストール方法

(ql:quickload :flexi-streams)

試してみる

 どんな関数があるかは、Quickdocsで確認できます。

 flexi-streamsはメジャーなライブラリが依存しているので、名前は耳にすることが多いかと思います。
日本語周りだとエンコーディング関係で問題が発生した場合、flexi-streamsが対応していなかったりするのが原因だったりするため、エンコード関係のライブラリかと思われ勝ちですが、基本的には、bivalent streamを実現するためのライブラリです。
キャラクターストリームとしての読み出しの方でエンコーディング関係諸々も必要になってくる、というところでしょうか。

 こんな感じでflexi-streamでストリームのアダプタを作ってやることにより、同じストリームに対してread-byteもread-charもできるようになります。

(with-open-file (in "/etc/motd" :element-type '(unsigned-byte 8))
  (let ((in (flex:make-flexi-stream in)))
    (loop :for c := (peek-char nil in nil)
          :for b := (read-byte in nil nil) :while b
          :collect (list c b))))
;=>  ((#\Newline 10) (#\T 84) (#\h 104) (#\e 101) (#\  32) (#\p 112) (#\r 114)
;     (#\o 111) (#\g 103) (#\r 114) (#\a 97) (#\m 109) (#\s 115) (#\  32) (#\i 105)
;     (#\n 110) (#\c 99) (#\l 108) (#\u 117) (#\d 100) (#\e 101) (#\d 100) (#\  32)
;     (#\w 119) (#\i 105) (#\t 116) (#\h 104) (#\  32) (#\t 116) (#\h 104) (#\e 101)
;     (#\  32) (#\D 68) (#\e 101) (#\b 98) (#\i 105) (#\a 97) (#\n 110) (#\  32)
;     (#\G 71) (#\N 78) (#\U 85) (#\/ 47) (#\L 76) (#\i 105) (#\n 110) (#\u 117)
;     (#\x 120) (#\  32) (#\s 115) (#\y 121) (#\s 115) (#\t 116) (#\e 101) (#\m 109)
;     (#\  32) (#\a 97) (#\r 114) (#\e 101) (#\  32) (#\f 102) (#\r 114) (#\e 101)
;     (#\e 101) (#\  32) (#\s 115) (#\o 111) (#\f 102) (#\t 116) (#\w 119) (#\a 97)
;     (#\r 114) (#\e 101) (#\; 59) (#\Newline 10) (#\t 116) (#\h 104) (#\e 101)
;     (#\  32) (#\e 101) (#\x 120) (#\a 97) (#\c 99) (#\t 116) (#\  32) (#\d 100)
;     (#\i 105) (#\s 115) (#\t 116) (#\r 114) (#\i 105) (#\b 98) (#\u 117) (#\t 116)
;     (#\i 105) (#\o 111) (#\n 110) (#\  32) (#\t 116) (#\e 101) (#\r 114) (#\m 109)
;     (#\s 115) (#\  32) (#\f 102) (#\o 111) (#\r 114) (#\  32) (#\e 101) (#\a 97)
;     (#\c 99) (#\h 104) (#\  32) (#\p 112) (#\r 114) (#\o 111) (#\g 103) (#\r 114)
;     (#\a 97) (#\m 109) (#\  32) (#\a 97) (#\r 114) (#\e 101) (#\  32) (#\d 100)
;     (#\e 101) (#\s 115) (#\c 99) (#\r 114) (#\i 105) (#\b 98) (#\e 101) (#\d 100)
;     (#\  32) (#\i 105) (#\n 110) (#\  32) (#\t 116) (#\h 104) (#\e 101)
;     (#\Newline 10) (#\i 105) (#\n 110) (#\d 100) (#\i 105) (#\v 118) (#\i 105)
;     (#\d 100) (#\u 117) (#\a 97) (#\l 108) (#\  32) (#\f 102) (#\i 105) (#\l 108)
;     (#\e 101) (#\s 115) (#\  32) (#\i 105) (#\n 110) (#\  32) (#\/ 47) (#\u 117)
;     (#\s 115) (#\r 114) (#\/ 47) (#\s 115) (#\h 104) (#\a 97) (#\r 114) (#\e 101)
;     (#\/ 47) (#\d 100) (#\o 111) (#\c 99) (#\/ 47) (#\* 42) (#\/ 47) (#\c 99)
;     (#\o 111) (#\p 112) (#\y 121) (#\r 114) (#\i 105) (#\g 103) (#\h 104)
;     (#\t 116) (#\. 46) (#\Newline 10) (#\Newline 10) (#\D 68) (#\e 101) (#\b 98)
;     (#\i 105) (#\a 97) (#\n 110) (#\  32) (#\G 71) (#\N 78) (#\U 85) (#\/ 47)
;     (#\L 76) (#\i 105) (#\n 110) (#\u 117) (#\x 120) (#\  32) (#\c 99) (#\o 111)
;     (#\m 109) (#\e 101) (#\s 115) (#\  32) (#\w 119) (#\i 105) (#\t 116) (#\h 104)
;     (#\  32) (#\A 65) (#\B 66) (#\S 83) (#\O 79) (#\L 76) (#\U 85) (#\T 84)
;     (#\E 69) (#\L 76) (#\Y 89) (#\  32) (#\N 78) (#\O 79) (#\  32) (#\W 87)
;     (#\A 65) (#\R 82) (#\R 82) (#\A 65) (#\N 78) (#\T 84) (#\Y 89) (#\, 44)
;     (#\  32) (#\t 116) (#\o 111) (#\  32) (#\t 116) (#\h 104) (#\e 101) (#\  32)
;     (#\e 101) (#\x 120) (#\t 116) (#\e 101) (#\n 110) (#\t 116) (#\Newline 10)
;     (#\p 112) (#\e 101) (#\r 114) (#\m 109) (#\i 105) (#\t 116) (#\t 116)
;     (#\e 101) (#\d 100) (#\  32) (#\b 98) (#\y 121) (#\  32) (#\a 97) (#\p 112)
;     (#\p 112) (#\l 108) (#\i 105) (#\c 99) (#\a 97) (#\b 98) (#\l 108) (#\e 101)
;     (#\  32) (#\l 108) (#\a 97) (#\w 119) (#\. 46) (#\Newline 10))

 その他、with-output-to-string/with-input-from-stringのようなインメモリのストリームのsequence版が用意されています。

(flex:with-output-to-sequence (out :as-list T)
  (map nil
       (lambda (x)
         (write-byte (char-code x) out))
       "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
;=>  (65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90)

まとめ

 今回は、flexi-streamsを紹介してみました。
bivalent streamというのは、どうも二種類の燃料を利用できるエンジンのbivalent engineに由来するのではないかと思うのですが、フレックス燃料車(Flexible-fuel engine/vehicle => flexi-streamsということなのでしょうか。

comments powered by Disqus