#:g1: frontpage

 

cl-sliceの紹介

Posted 2014-07-27 23:30:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の209日目です。

cl-sliceとはなにか

 cl-sliceは、Tamas K Papp氏作のCommon Lispでシークエンス/配列をスライスするのに特化したライブラリです。

パッケージ情報

パッケージ名cl-slice
Quicklisp
Quickdocscl-slice | Quickdocs
CL Test Grid: ビルド状況cl-slice | CL Test Grid

インストール方法

(ql:quickload :cl-slice)

試してみる

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

 シークエンス/配列のスライスに特化しているだけあって結構面白いことができます。

(cl-slice:slice #(0 1 2 3) 1) 
;=>  1


(cl-slice:slice #(0 1 2 3) '(1 . 3)) 
;=>  #(1 2)


(cl-slice:slice #(0 1 2 3) '(0 . -1)) 
;=>  #(0 1 2)



(cl-slice:slice #(0 1 2 3) #(1 3)) 
;=>  #(1 3)

この辺りは普通ですが、ビットベクタで1が立っているところを取得できたりするのが面白いところ
他、範囲の指定方法やフィルター的なものがあります。また、多次元配列も扱えます。

(cl-slice:slice '(0 1 2 3) #*0101) 
;=>  (1 3)
(cl-slice:which #'evenp #(0 1 2 3)) 
;=>  #(0 2)


(cl-slice:slice #(0 1 2 3) (cl-slice:head 1)) 
;=>  #(0)


(cl-slice:slice #(0 1 2 3) (cl-slice:head 2)) 
;=>  #(0 1)


(cl-slice:slice #(0 1 2 3) (cl-slice:tail 1)) 
;=>  #(3)


(cl-slice:slice #(0 1 2 3) (cl-slice:tail 2)) 
;=>  #(2 3)


(cl-slice:slice #(0 1 2 3) (cl-slice:including 2 3)) 
;=>  #(2 3)


(cl-slice:slice #(0 1 2 3) (cl-slice:nodrop 2)) 
;=>  #(2)


(cl-slice:slice #2A((0 1 2)
                    (3 4 5))
                t 2) 
;=>  #(2 5)

まとめ

 今回は、cl-sliceを紹介してみました。
特化したライブラリは紹介しやすくて良いですね。

t-listsの紹介

Posted 2014-07-26 16:45:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の208日目です。

t-listsとはなにか

 t-listsは、Toby Weinberg氏作のDylanの所謂tconsのライブラリです。

パッケージ情報

パッケージ名t-lists
プロジェクトサイトopendylan/sources/lib/t-lists at master · dylan-lang/opendylan · GitHub

インストール方法

 OpenDylanには標準で添付されてくるので、library.dylanで

Module: dylan-user

define library ライブラリ名
  ...
  use t-lists;
  ...
end library;

define module ライブラリ名
  ...
  use t-lists;
  ...
end module;

で使えます。

試してみる

 tconsは、リストの最後のセルのポインタを保持することにより、リストが苦手とする最後の要素へのアクセス〈O(要素数)〉をO(1)とするものです。
Interlispでは標準ライブラリとして存在していたみたいですが、後の方言では標準ライブラリに入ることもなく同じアイデアが手書きで実装されることが多いようです(Common LispのLOOP内のCOLLECT節等)。ちなみに、tconsのTはInterlispの開発者であるTeitelman氏のTです。

 さてそんなtconsですが、t-listsでは、Dylanのコレクションの枠組みと繰り返し規約(The Iteration Protocol)を利用して綺麗に組み込んでいます。

make(<t-list>, size: 10)
//=> (<t-list> of (#f, #f, #f, #f, #f, #f, #f, #f, #f, #f))


empty?(make(<t-list>, size: 0));
//=> #t


let tl = make(<t-list>, size: 10);

push(tl, foo:)
//=> #"foo"


push-last(tl, bar:)
//=> #"bar"


tl
//=> (<t-list> of (#"foo", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, #"bar"))


pop(tl)
//=> #"foo"


tl
//=> (<t-list> of (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, #"bar"))


pop-last(tl)
//=> #"bar"


tl
//=> (<t-list> of (0, 1, 2, 3, 4, 5, 6, 7, 8, 9))


shallow-copy(tl)
//=> (<t-list> of (0, 1, 2, 3, 4, 5, 6, 7, 8, 9))


concatenate!(tl, make(<t-list>, size: 5))
//=> (<t-list> of (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, #f, #f, #f, #f, #f))


tl.size
//=> 15


as(<list>, tl)
//=> #(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, #f, #f, #f, #f, #f)


as(<t-list>, make(<list>, size: 5))
//=> (<t-list> of (#f, #f, #f, #f, #f))


element(tl, 0)
//=> 0


last(tl)
//=> #f


for (idx from 0 to tl.size)
  tl[idx] := idx;
end;


tl
//=> (<t-list> of (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14))

まとめ

 今回は、t-listsを紹介してみました。
繰り返し規約は、SBCLにも取り入れられていますが、便利な機能ですね。

hu.dwim.reiterateの紹介

Posted 2014-07-25 12:30:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の206日目です。

hu.dwim.reiterateとはなにか

 hu.dwim.reiterateは、dwim.huの人達によるiterateの再実装のようです。

パッケージ情報

パッケージ名hu.dwim.reiterate
Quicklisp
Quickdocshu.dwim.reiterate | Quickdocs
CL Test Grid: ビルド状況hu.dwim.reiterate | CL Test Grid

インストール方法

(ql:quickload :hu.dwim.reiterate)

試してみる

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

 iterateに何か不満があっての再実装なんだと思いますが、ドキュメントも無いので何が不満だったのかは外から眺める限りは謎です。テストケースがあるのでiterateに慣れた人なら何を解決しようとしていたかが分かるのかもしれません。

 とりあえずロード方法についての注意ですが、duim.huのプロダクトはduim.huで良く使われているリードテーブルで読まないと何かが上手くロードできないことがあります。
hu.dwim.reiterateに関しては、標準のリードテーブルで読めば、loggerがないよと怒られますが、リーダーマクロが定義されていないのが原因です。とりあえず、

(let ((*readtable* (or (named-readtables:find-readtable :hu.dwim)
                       (named-readtables:make-readtable :hu.dwim :merge '(:standard)))))
  (ql:quickload :hu.dwim.syntax-sugar)
  (asdf/utility:call-function :hu.dwim.syntax-sugar :set-feature-cond-syntax-in-readtable)
  (asdf/utility:call-function :hu.dwim.syntax-sugar :set-sharp-boolean-syntax-in-readtable)
  (ql:quickload :hu.dwim.reiterate))

こんな感じにロードしてやる必要があります。

 さて、hu.dwim.reiterateとiterateの比較ですが、基本的に同じですが、微妙に違っています、開発途中のようなので作りかけなのか仕様なのかは不明です。

(defpackage :maliikto
  (:use :cl :hu.dwim.reiterate))


(cl:in-package :maliikto)


(iter (:for i :from 0 :to 9)
      (collecting i))
;=>  (0 1 2 3 4 5 6 7 8 9)

こういうシンプルなものは全く同じですが、toを省略したfor節がどうも上手く動きません。
それと、:fromはキーワードでないと上手く動かなかったり、collectは、collectingと書かないといけません。

(iter:iter (iter:for x :from 0)
           (iter:repeat 10)
           (iter:collecting x))
;=>  (0 1 2 3 4 5 6 7 8 9)


(iter (for x :from 0)
      (repeat 10)
      (collecting x))
;!> The variable X is unbound.


(iter:iter (iter:for x downfrom 0)
           (iter:for e :in-vector "いろはにほへとちりぬるを")
           (iter:collect (list x (string e))))
;=>  ((0 "い") (-1 "ろ") (-2 "は") (-3 "に") (-4 "ほ") (-5 "へ") (-6 "と") (-7 "ち") (-8 "り") (-9 "ぬ") (-10 "る") (-11 "を"))


(iter (for x :from 0 :downto most-negative-fixnum) 
      (for e :in-vector "いろはにほへとちりぬるを")
      (collecting (list x (string e))))
;=>  ((0 "い") (-1 "ろ") (-2 "は") (-3 "に") (-4 "ほ") (-5 "へ") (-6 "と") (-7 "ち") (-8 "り") (-9 "ぬ") (-10 "る") (-11 "を"))

ちなみに、:hu.duim.loggerを読み込んだ状態で実行すると、

(iter (:for i :from 0 :to 9)
      (collecting i))
;=>  (0 1 2 3 4 5 6 7 8 9)
;>> 20:42 3              LOG DEBUG   Registering as body of #<LOOP-FORM NIL {1047901A63}> ((:FOR CL-USER::I :FROM 0 :TO 9) (HU.DWIM.REITERATE:COLLECTING CL-USER::I))
;>> 20:42 3              LOG DEBUG   Registering as body of #<LOOP-FORM NIL {1047901A63}> (:FOR CL-USER::I :FROM 0 :TO 9)
;>> 20:42 3              LOG DEBUG   Registering as body of #<LOOP-FORM NIL {1047901A63}> (HU.DWIM.REITERATE:COLLECTING CL-USER::I)
;>> 20:42 3              LOG DEBUG   Processing toplevel iterate form #<HU.DWIM.REITERATE::LOOP-FORM NIL {1047901A63}>; stack is (#<LOOP-FORM NIL {1047901A63}>)
;>> 20:42 3              LOG DEBUG   Walking body form (:FOR CL-USER::I :FROM 0 :TO 9); stack is (#<LOOP-FORM NIL {1047901A63}>)
;>> 20:42 3              LOG DEBUG   Form (:FOR CL-USER::I :FROM 0 :TO 9) matched as a clause in stack (#<LOOP-FORM NIL {1047901A63}>)
;>> 20:42 3              LOG DEBUG   LOOP-STACK-POSITION will search stack (#<LOOP-FORM NIL {1047901A63}>)
;>> 20:42 3              LOG DEBUG   BELONGS-TO-A-PARENT-ITERATE-FORM? (:FOR CL-USER::I :FROM 0 :TO 9) #<LOOP-FORM NIL {1047901A63}> loop-form T
;>> 20:42 3              LOG DEBUG   Will try to process clause (:FOR CL-USER::I :FROM 0 :TO 9) in loop called 0
;>> 20:42 3              LOG DEBUG   Hijacked clause stack is (#<LOOP-FORM NIL {1047901A63}>)
;>> 20:42 3              LOG DEBUG   Will walk 0 in context #<LOOP-FORM NIL {1047901A63}>
;>> 20:42 3              LOG DEBUG   Will walk 9 in context #<LOOP-FORM NIL {1047901A63}>
;>> 20:42 3              LOG DEBUG   Augmented environment with variable CL-USER::I in the context of #<LOOP-FORM NIL {1047901A63}>
;>> 20:42 3              LOG DEBUG   Augmented environment with variable #:FOR/LIMIT/2344 in the context of #<LOOP-FORM NIL {1047901A63}>
;>> 20:42 3              LOG DEBUG   Expanded (:FOR CL-USER::I :FROM 0 :TO 9) into ((WHEN # #))
;>> 20:42 3              LOG DEBUG   Finished walking body form (:FOR CL-USER::I :FROM 0 :TO 9), will unwalk now
;>> 20:42 3              LOG DEBUG   Walking body form (HU.DWIM.REITERATE:COLLECTING CL-USER::I); stack is (#<LOOP-FORM NIL {1047901A63}>)
;>> 20:42 3              LOG DEBUG   Form (HU.DWIM.REITERATE:COLLECTING CL-USER::I) matched as a clause in stack (#<LOOP-FORM NIL {1047901A63}>)
;>> 20:42 3              LOG DEBUG   LOOP-STACK-POSITION will search stack (#<LOOP-FORM NIL {1047901A63}>)
;>> 20:42 3              LOG DEBUG   BELONGS-TO-A-PARENT-ITERATE-FORM? (HU.DWIM.REITERATE:COLLECTING CL-USER::I) #<LOOP-FORM NIL {1047901A63}> loop-form T
;>> 20:42 3              LOG DEBUG   Will try to process clause (HU.DWIM.REITERATE:COLLECTING CL-USER::I) in loop called 0
;>> 20:42 3              LOG DEBUG   Hijacked clause stack is (#<LOOP-FORM NIL {1047901A63}>)
;>> 20:42 3              LOG DEBUG   Will walk CL-USER::I in context #<LOOP-FORM NIL {1047901A63}>
;>> 20:42 3              LOG DEBUG   Registering new clause data with key (HU.DWIM.REITERATE:COLLECTING NIL) in loop #<LOOP-FORM NIL {1047901A63}>
;>> 20:42 3              LOG DEBUG   Augmented environment with variable #:COLLECTING/HEAD/2345 in the context of #<LOOP-FORM NIL {1047901A63}>
;>> 20:42 3              LOG DEBUG   Augmented environment with variable #:COLLECTING/LAST-CONS/2346 in the context of #<LOOP-FORM NIL {1047901A63}>
;>> 20:42 3              LOG DEBUG   Registering result-form-candidate with key (HU.DWIM.REITERATE:COLLECTING NIL), form #:COLLECTING/HEAD/2345, stack is (#<LOOP-FORM NIL {1047901A63}>)
;>> 20:42 3              LOG DEBUG   Expanded (HU.DWIM.REITERATE:COLLECTING CL-USER::I) into ((LET #
;>>                                                                                             #))
;>> 20:42 3              LOG DEBUG   Finished walking body form (HU.DWIM.REITERATE:COLLECTING CL-USER::I), will unwalk now
;>> 20:42 3              LOG DEBUG   Finished walking body of #<LOOP-FORM NIL {1047901A63}>
;>> 20:42 3              LOG DEBUG   Building result form for #<LOOP-FORM NIL {1047901A63}>

マクロ展開時にこんな感じでログが出ます。

まとめ

 今回は、hu.dwim.reiterateを紹介してみました。
やはり、何故自前で実装しているのかが知りたいところです。

stringsの紹介

Posted 2014-07-23 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の205日目です。

stringsとはなにか

 stringsは、DEP-0004で提案されたDylanの新しい文字列ライブラリです。

パッケージ情報

パッケージ名strings
プロジェクトサイトdylan-lang/strings · GitHub

インストール方法

 OpenDylanには標準で添付されてくるので、library.dylanで

Module: dylan-user

define library ライブラリ名
  ...
  use strings;
  ...
end library;

define module ライブラリ名
  ...
  use strings;;
  ...
end module;

で使えます。

試してみる

 DEPというのは、PythonのPEPに範を取った改良のための提案の仕組みのようです。

stringsでは、

  • alphabetic?
  • alphanumeric?
  • control?
  • graphic?
  • printable?
  • lowercase?
  • uppercase?
  • whitespace?
  • octal-digit?
  • decimal-digit?
  • hexadecimal-digit?
  • char-compare
  • char-compare-ic
  • char-equal-ic?
  • string-compare
  • string-equal-ic?
  • string-equal?
  • string-greater-ic?
  • string-greater?
  • string-less-ic?
  • string-less?
  • starts-with?
  • ends-with?
  • lowercase!
  • lowercase
  • uppercase!
  • uppercase
  • strip
  • strip-left
  • strip-right
  • pad
  • pad-left
  • pad-right
  • find-substring
  • replace-substrings
  • count-substrings
  • split-lines

が定義されていますが、名前から使い方は推測できる感じです。

block ()
  let s = "litokan";
  format-out("%= -> %=\n", s, lowercase(s));
  format-out("%= -> %=\n", s, uppercase(s));
  format-out("%= -> %=\n", s, uppercase('a'));
  format-out("%= -> %=\n", s, find-substring(s, "ok"));
  let s = "foo\nbar\nbaz\n\nquux";
  format-out("%= -> %=\n", s, split-lines(s));
  format-out("%= -> %=\n", s, split-lines(s, remove-if-empty?: #t));
end;
//>> "litokan" -> "litokan"
//>> "litokan" -> "LITOKAN"
//>> "litokan" -> 'A'
//>> "litokan" -> 3
//>> "foo\nbar\nbaz\n\nquux" -> #("foo", "bar", "baz", "", "quux")
//>> "foo\nbar\nbaz\n\nquux" -> #("foo", "bar", "baz", "quux")

まとめ

 今回は、stringsを紹介してみました。
OpenDylanのコミュニティでは、ユーザー一人あたりのドキュメンテーションの量が抜群に多いという自虐的な冗談があるようなのですが、確かに充実しています。

clの紹介

Posted 2014-07-22 16:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の204日目です。

clとはなにか

 clは、Scott McKay氏作のDylanのCommon Lisp互換ユーティリティです。

パッケージ情報

パッケージ名cl
プロジェクトサイトopendylan/sources/lib/cl at master · dylan-lang/opendylan · GitHub

インストール方法

 OpenDylanには標準で添付されてくるので、library.dylanで

Module: dylan-user

define library ライブラリ名
  ...
  use cl;
  ...
end library;

define module ライブラリ名
  ...
  use cl-sequences;
  use cl-strings;
  use cl-macros;
  ...
end module;

みたいにすれば使えます。

試してみる

 作者は、Symbolics在籍時には、CLIMやOpenGeneraを開発していたことで有名なScott McKay氏。
現在は、ITAに在籍されているようですが、Harlequin 〜 Functional Objects でDylanの開発にも携わっていたようです。

 さてライブラリですが、命名規約が色々入り交じっている気もしますが、3つのモジュールで提供されているのは下記のようなものです。

cl-macros
  • push!
  • pop!
cl-sequences
  • cl-position
  • cl-position-if
  • cl-find
  • cl-find-if
  • cl-assoc
  • cl-assoc-if
  • cl-count
  • cl-count-if
  • cl-remove
  • cl-remove-if
  • cl-remove!
  • cl-remove-if!
  • cl-substitute
  • cl-substitute-if
  • cl-substitute!
  • cl-substitute-if!
  • cl-remove-duplicates
  • cl-remove-duplicates!
  • cl-search
  • cl-mismatch
  • cl-merge
cl-strings
  • char-equal?
  • char-not-equal?
  • char-less?
  • char-not-less?
  • char-greater?
  • char-not-greater?
  • string-equal?
  • string-not-equal?
  • string-less?
  • string-not-less?
  • string-greater?
  • string-not-greater?
  • alpha-char?
  • digit-char?
  • alphanumeric-char?
  • upper-case?
  • lower-case?
  • standard-char?
  • graphic-char?
  • ordinary-char?
  • whitespace-char?
  • string-capitalize
  • string-capitalize!
  • string-capitalize-words
  • string-capitalize-words!
  • string-trim
  • string-left-trim
  • string-right-trim
  • string-search-set
  • string-search-not-set
  • string-pluralize
  • string-a-or-an

string-pluralize、string-a-or-anはCommon Lispには存在しませんが、FORMATに該当する機能があります。
また、ordinary-char?もCommon Lispには存在しませんが、graphic-char?に'\n'、'\r'、'\t'が追加された文字セットに属するかどうかを判定します。

let u = list(1, 2, 3, 4);
pop!(u);
u; //=> #(2, 3, 4)
cl-search("a", "fooooooaoooo");
//=> 7
ordinary-char?('\n') //=> #t

みたいな感じで使えます。

まとめ

 今回は、clを紹介してみました。
Dylanのライブラリには作者情報を書くところがあるため、作者が誰か分かり易くて良いですね(Common Lisp方面が謎すぎる気もしますが)。

uncommon-dylanの紹介

Posted 2014-07-22 07:30:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の203日目です。

uncommon-dylanとはなにか

 uncommon-dylanは、Carl Gay氏作のDylanの便利ユーティリティです。

パッケージ情報

パッケージ名uncommon-dylan
プロジェクトサイトdylan-lang/uncommon-dylan · GitHub

インストール方法

 sourceディレクトリのext以下にソースを配置して、registryに登録すれば、library.dylanでuse uncommon-dylanできるようになります。

$ git clone https://github.com/dylan-lang/uncommon-dylan.git ext/uncommon-dylan
$ echo abstract://dylan/ext/uncommon-dylan/uncommon-dylan.lid > registry/generic/uncommon-dylan

試してみる

 OpenDylanで標準ライブラリとしてはcommon-dylanというのがあるのですが、uncommon-dylanにはCommon Lisp的な関数が定義されています。

 目についた所を紹介すると

bind
letと同じですが、Dylanのletはブロックの中に記述するもので、それ自身がブロックを作らないことから作られたようです。つまりLispのletと同じですね。
iff
意味としては、ifと同じですがDylanのifだとendがうるさいからなのか、xifや、iffとして関数のフォームと同じ形式で書けるようなものが定義されていることが多いです。
as <integer> string
string-to-integerはありますが、asでの定義はないのでメソッドを追加しています。
ignore-errors
Common Lispではお馴染ですが、それのDylan版です。Common Lispと違って#fを返すのみで二値目でコンディションを返したりはしない様子。
elt/inc!/dec!
Common Lispのものと同じです。
Module: hello
Synopsis: 
Author: 
Copyright: 

define function main (name :: <string>, arguments :: <vector>)
  bind (mesg = "おはよう日本!\n")
    format-out(mesg);
  end;

  iff (#t, format-out("true\n"));

  bind (n = $maximum-integer)
   format-out("%=\n", n);
   format-out("%=\n", wrapping-inc!(n));
  end;

  format-out("%=\n", 1234 + as(<integer>, "1234"));

  format-out("error => %=\n", ignore-errors(3 + "3"));

  format-out("%=\n", slice("0123456789", 1, 4));

  format-out("%=\n", elt("0123456789", 1));

  exit-application(0);
end function main;

main(application-name(), application-arguments());
$  _build/bin/hello                                               
おはよう日本!
true
2305843009213693951
0
2468
error => #f
"123"
'1'

まとめ

 今回は、uncommon-dylanを紹介してみました。
DylanにもREPLがある処理系はあったみたいですが、OpenDylanもREPLが使えてライブラリを簡単に試せるようになると非常に嬉しいなと思うこの頃です。

iolibがビルドできない

Posted 2014-07-21 15:55:00 GMT

 最近iolibがビルドできないなあと思っていたら、外部ライブラリが必須になった様子。

現在Quicklispだけでは拾ってこないので手動で準備しないといけないらしい。

$ git clone https://github.com/sionescu/libfixposix.git
$ cd libfixposix
$ autoreconf -i -f
$ ./configure
$ make
$ make install
$ ldconfig -v

あとは処理系からiolibをロードすれば良い。

hu.dwim.quasi-quoteの紹介

Posted 2014-07-21 12:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の202日目です。

hu.dwim.quasi-quoteとはなにか

 hu.dwim.quasi-quoteは、dwim.huの人達による拡張されたquasiquoteのライブラリです。

パッケージ情報

パッケージ名hu.dwim.quasi-quote
Quicklisp
CLiKiCLiki: Article not found
Quickdocshu.dwim.quasi-quote | Quickdocs
CL Test Grid: ビルド状況hu.dwim.quasi-quote | CL Test Grid

インストール方法

(ql:quickload :hu.dwim.quasi-quote)

試してみる

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

 このライブラリは、どうも最近整備されていないので、恐らくですが、現在まともにインストールして利用できる人はほとんどいないのではないかと言う感じです。
それはともかく、hu.dwim.quasi-quoteがどんなものかというと、quasiquoteをリストだけでなく文字列やバイナリのストリームに拡張したり、埋め込み言語を展開したりというものです。

(hu.dwim.quasi-quote:enable-quasi-quoted-string-to-string-emitting-form-syntax '*standard-output*)

`str("1 2" ,(reverse (list `str(" 5 6") `str(" 3 4"))) " 7 8")
;>>  1 2 3 4 5 6 7 8
;=>  <no values>

 他バイトストリームで

`bin(1 2)

のように書けたり

bivalentストリームで

`biv(1 2
            ,(list
              " 3 4"
              `biv(5 6 " 7 8")
              #(9 10))
            " 11 12")

こんな感じに書けたりというところですが、リーダーマクロを登録するにあたって利用するストリームも指定しないといけません。
バイトストリーム系のことを考えれば致し方ない気もしますが、どうもこの辺りが使い辛いですね。

 その他、pdfが、

[document
   [info [dictionary "Author" "levy"]]
   [root [catalog "Pages" [indirect-object-reference pages]
                  "StructTreeRoot" [indirect-object-reference structure-tree-root]]]
...

のように書けたり、CSS、JavaScriptが、quasiquote的に書けたりです。

`js(if (and (or (not true) true)
                (not false))
           (print "ok")
           (print "wrong"))

まとめ

 今回は、hu.dwim.quasi-quoteを紹介してみました。
どうもこのライブラリは周りから取り残されているようで、依存しているライブラリがアップデートしたため、そのままでは動かなかったりしますので修正して使いましょう。
dwim.hu関係のライブラリは使い方を知るだけで一苦労です。

lol-reの紹介

Posted 2014-07-20 14:50:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の201日目です。

lol-reとはなにか

 lol-reは、Alexander Popolitov氏作のLet Over Lambdaの#~m、#~sにインスパイアされたCL-PPCREを便利に使うためのライブラリです。

パッケージ情報

パッケージ名lol-re
Quicklisp
CLiKiCLiki: lol-re
Quickdocslol-re | Quickdocs
CL Test Grid: ビルド状況lol-re | CL Test Grid

インストール方法

(ql:quickload :lol-re)

試してみる

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

 色々と謎なところが多いのですが、まず名前が紛らわしい。
Let Over Lambdaにインスパイアされただけでオリジナルと違うなら別の名前を付けた方が良いのではと思ったりはします。また、リーダーマクロの処理としてcl-read-macro-tokensを利用しているのは、何故なんでしょうね。必要なんでしょうか。
などと書いてしまいましたが、動作はこんな感じです。

(defpackage :lol-re-foo
  (:use :cl :lol-re))


(cl:in-package :lol-re-foo)


(enable-read-macro-tokens)


(list (m~ "(f)(o)(o)" "foo")
      $1
      $2
      $3)
;=>  ("foo" "f" "o" "o")


(funcall (s~ "foo" "bar") "foo")
;=>  "bar"
;    T


(dolist (elt '("1" "2" "3"))
  (format t "~a" (m~ "[0-9]" elt)))
;>>  123
;=>  NIL

 その他、便利ユーティリティが数点用意されています。

まとめ

 今回は、lol-reを紹介してみました。
くどいですが、lol-reという名前なら、Let Over Lambdaのcl-ppcreのリーダーマクロ部分を取り出したライブラリって思っちゃいますよねー。

anaphora.pltの紹介

Posted 2014-07-19 09:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の200日目です。

anaphora.pltとはなにか

 anaphora.pltは、wcy氏作のRacketのアナフォリックマクロ集です。

パッケージ情報

パッケージ名anaphora.plt
PLaneTPLaneT Package Repository : PLaneT > wcy > anaphora.plt

インストール方法

 Racketから

(require (planet wcy/anaphora:1:0))

で使えます。

試してみる

 Racketにもanaphoraがあったので無駄に比較してみましょう。
Racket版anaphoraもCommon Lisp版anaphoraとは無関係。定義されている構文もオリジナルのものが混っています。
定義されている構文は以下の通りです。

  • aif
  • aif-not
  • awhen
  • aprogn
  • aand

 これらのうち、aif、awhen、aandはお馴染ですが、

(aif (list-ref '(1 2 #f 3) (random 4))
     it
     'other)
;=> 1 or other


(awhen (list-ref '(1 2 #f 3) (random 4))
  (display it))
;>>> 1 or 2 or 3


(aand 'foo it)
;=> it

aif-not、aprognというのがオリジナルかなと思います。

(aif-not (list-ref '(1 2 #f 3) (random 4))
         it
         'other)
;=> #f or other


(aprogn (list 1 2 3)
        (cdr it)
        (cdr it))
;=> '(3)

aprognの動作は、各々の式が都度itで束縛されるので、代入っぽい操作に使えそうです。
展開は、

(let ((it (list 1 2 3)))
  (let ((it (cdr it)))
    (cdr it)))

のようになる様子。RacketにもSchemeにもprognはないのに何故にprognなのか。

まとめ

 今回は、anaphora.pltを紹介してみました。
Scheme(特にRacket)だとCommon Lispのようなgeneralized booleanはスタイル的にあまり活用されていないようなのでアナフォリックマクロのようなものも、あまり使いでがない感じですね。

Older entries (1724 remaining)