2009年1月31日土曜日

XMLを扱う (その11) [Common Lisp][Unicode]

ワークフロ-の続き。

cxml-stpから。

この際だから、cxmlのDOMに立ちもどって確認する。

http://common-lisp.net/project/cxml/dom.html

をみる。

IDL/Lisp mappingというのはOMGが定めたもので、

http://www.omg.org/docs/formal/00-06-02.pdf

これ。Franzが作成支援したようだ。

さて、cxml-stpが主張しているのは、

** DOMはIDLをつかって規程されている。
** IDL/LISP mappingはOMGで標準化されている。
** だからといってDOM/LISP mappingが標準化されているとはいえないぜ。
** なので、IDL/LISP mappingに従わず、俺流 mappingをするぜ。

ということ。まあ、それはそうだ。

characters/strings instead of runes/rods って何だろ?

調べる。Unicodeに対応していない Lisp処理系にてUnicodeを扱うものな感
じ。

さらに調べる。closure-common packageで定義されているようだ。

--- runes.lisp ---
(deftype rune () '(unsigned-byte 16))
(deftype rod () '(array rune (*)))
(deftype simple-rod () '(simple-array rune (*)))
------------------

Unicodeを扱うためのものであることは間違いなさそうだ。

runeは英語の意味(ルーン文字/呪文)そのまんまから来たんだろうな。rod
は?stringがひもだからそれとの対応としてムチってことかな?

さて、Unicodeとか、UTF-8とかを正確に理解していないような気がする。
私の理解ではUnicodeというのは文字集合の定義とエンコーディング達の定
義を含む総称的な規格であり、その中でもUTF-8というのはPlan9を発祥と
するエンコーディングというものだった。だけどここではUnicodeに対応し
ているものはrune、そうでないものはutf-8という分け方がされている。
むぅ。Unicode 対応ということが何かがわかってないんだな、私は。

文字関係については、確か今夜わかるメールプロトコル、にあったような。
あった、自分なりの補足や調査も交えつつまとめる。

** 文字((graphic) character):

言葉を表記するために社会習慣として用いられる記号。

例: アルファベット、数字、ギリシャ文字、漢字、ひらがな、カタカナ。

** 文字集合(character set):

文字の集合。膨大な文字を計算機で扱いやすくするために、よく使う文字
だけを集めていることが多い。下記の例はcodedが入っていることからわか
るとおり、文字集合の定義だけでなく、次項の文字コードの定義も含んで
いる。ただし、文字集合が何を指すかというのは規格化団体毎に揺れがあ
る。

例:
ISO/IEC 8859-1:1998
Information technology - 8-bit single-byte coded graphic character
sets - Part 1: Latin alphabet No.1

JIS X 0208
7ビット及び8ビットの2バイト情報交換用符号化漢字集合

** 文字コード

文字集合に対して、それと数値を対応づける方式。文字符号化方式
(character encoding scheme)と呼ばれることもある。ただし、文字コード
が何を指すかというのは規格化団体毎に揺れがある。

例:
JIS X 0208は文字集合を規程するとともに、ISO-2022-JP、EUC-JP、
Shift_JISという3つの文字コードを規程している。

さて、ではUnicodeは?

** UnicodeはUnicode Consortiumが企画の策定・維持を行っている規格で
ある。

** The Unicode Standardという文書で規程している。

** The Unicode Standardではそれぞれの文字について、名前とコード
ポイントを定めている。code pointとは数値のことである。

** 現在の最新バージョンは5.1.0である。

** バージョン5.0とISO/IEC 10646は互換である。

** 5.1.0はWebで公開されている。しかしそのPDFは印刷できない。5.0は
書籍としても出版されている。

** The Unicode Standardは、character encoding standardである。
これ以降特にことわりがない限り、The Unicode Standard version 5.1.0
についての話とする。

** 3つのエンコーディング形式を定めている。a 32-bit form (UTF-32)、
a 16-bit form (UTF-16)、 an 8-bit form (UTF-8)。(あれ? やはり
UTF-8とUnicodeに対する理解は間違っていなかった)

** コードポイントの総数は、1,114,112である。(百万以上)

** コードポイントの始めの65,536をBasic Multilingual Plane (BMP)と呼ぶ。

** コードポイントは、0から0x10FFFFまでの間の値をとる。

** 計算機でテキスト処理をするさいには、そのテキストの要素については
いろいろな表現形式や取り扱いがあるであろう。ここでは、テキスト要素
とはコードポイントであるとする。その意味で、コードポイントのことを
encoded characters(符号化文字)と呼ぶ。

** ここまでがだいたいChapter 1 Introduction。

** 続いてChapter 2 General Structure。

** Chapter 2 のアウトライン。

*** text representationとtext processingの本性について整理する。

*** The Unicode Design Prinsipleを紹介する。

*** the Unicode character encoding model を紹介する。そこでは、
character、code point、encoding forms という概念がそれらの相関ふく
めて導入される。これらによって、UTF-8、UTF-16、UTF-32の説明が可能
となり、これらエンコーディングの利点・欠点もあわせて説明する。

*** the Unicode codespaceを紹介する。

*** writing directionの話題を説明する。

*** equivalent sequencesとnormalizationを説明する。

*** the Unicode Standardに対するcomformanceについてざっくりと説明す
る。(お、ここでUnicode対応とはなんぞやがわかるかも)

** 2.1 Architectual Context

character code standardというのはそれ自体が計算機のテキスト処理のア
プリケーションを成しているわけではなく、有用なアプリケーションをつ
くるための部品である。部品であるがゆえ、様々な用途に使われる。それ
ゆえすべての用途のrequirementsをみたしたものを作るのは不可能であり、
それらをいい感じでみたすようなバランスをとることになる。


*** Basic Text Processes

たいていの計算機では、low-levelのテキスト処理機能をまず用意して、
それをもとに多様なテキスト処理が組み立てられる。このlow-levelの部
分をBasic Text Processesと呼ぶ。

**** Rendering characters visible

**** Breaking lines while rendering

**** Modifying appearance, such as point size, kerning,
underlining, slat and weight

**** Determining units such as "word" and "sentence"

**** Interacting with users in processes such as selecting and
highlighting text

**** Accepting keyboard input and editing stored text through
insertion and deletion

**** Comparing text in operations such as in searching or
determining the sort order of two strings

**** Analyzing text content in operations such as spell-checking,
hyphenation, and parsing morphology

**** Treating text as bulk data for operations such as compressing
and decompressing, truncating, transmitting, and receiving


*** Text Elements, Characters, and Text Process

なにがtext elementであるということは、どういうtext processにおいて?
ということと不可分である。普遍的なというか、text processと独立して
いるようなtext elementsの定義は存在しない。

例えば、英語の"A"と"a"はレンダリングでは別のものだが、語を検索する
ときには同じと扱われる。ドイツ語では、letter combination "ck"は、
ハイフネーションするときは"k-k"として分離して扱うが、sortするとき
は"ck"を一体として扱う。

また、英語でspell-checkするときは、"the quick brown fox,"の"fox"が
テキスト要素になる。

で、Unicodeがcharacter encoding standardとして定めているのは、text
elementsでなく、もっとアトミックなcharacterですよ。それを特定する
code pointsですよ。それらをassigned characterと呼びますよ。

charactersからtext elementsを作る形態は4つある。

**** composite (合成)

**** Collation Unit (照合単位)

**** Syllable (音節(を表わすつづり文字))

**** Word (語)

*** Text Processes and Encoding

the Unicode Standardは特定のbasic text-processing algorithmsに依存
しないように設計している。

** 2.2 Unicode Design Principles

---
Universality: The Unicode Standard provides a single, universal
repertoire.

Efficincy: Unicode text is simple to parase and process.

Characters, not glyphs: THe Unicode Standard encodes characters,
not glyphs.

Semantics: Characters have well-defined semantics.

Plain text: Unicode characters represent plain text.

Logical order: The default for memory representaion is logical
order.

Unification: The Unicode Standard unifies duplicate characters
withiin scripts across languages.

Dynamic composition: Accented forms can be dynamically composed.

Stability: Characters, once assigned, cannot be reassigned and key
properties are immutable.

Convertibility: Accurate convertibility is guaranteed between the
Unicode Standard and other widely accepted standards.
---

今、興味があるものだけ深掘りする。

*** Characters, Not Glyphs

Characters: 書き言葉の最小単位の抽象表現である。ここで書き言葉は意
味論上の価値を持つものに限る。代表的なものとして、letters、
punctuation、signsなどがある。自然言語で使われるlettersをグルーピ
ングしたものはscriptsと呼ぶ。あるletterが異なるscriptsに属すること
もあろう。そして、それが意味論的にも見た目的にも同一だとする。それ
でもUnicodeはそれらを別のcharactersとして扱う。scriptsの分類が優先
ということ。

glyphというのは要は見た目のこと。ただし、単一のletterに関するもの
だけではなく、letterの連続もあることに注意たとえば、英語の筆記体に
て"fox"と単語で書くときと"f""o""x"と個別に書くときではglyphが違う。

fontというのは、Rendering processにおけるUnicode charactersから
glyphsへのマッピングである。

*** Semantics

Unicodeのsemanticsは、characterの名前やcode table上の位置などでは
な定義しない。すなわち暗黙の定義はしない。character propertiesで明
示的に定義する。それらを格納したものをThe Unicode Character
Databaseと呼ぶ。このdatabaseの情報をもとに、parsing、sortingなどの
アルゴリズムを構築する。

Unicode流のアプリケーションプログラミングをする場合、このdatabase
のsemanticsを核におくことになり、i18n対応のためのcode set indepent
modelは不要になる。code set indepent modelでは、byte-streamの
semanticsはcode set毎に異なるという見地から、byte-streamの取り扱う
際には、個別のcode setの個別に定義されたsemanticsを選択的に適用する
機構を有するものである。これがUnicodeでは不要となる。もちろん例えば
UTF-8を単なるcode setの追加と位置付けて、code set independet model
で取り扱うことも可能ではあるが。

*** Unification

scriptsという概念とlanguagesという概念はUnicodeでは別。そして、先
程書いたように、同じletterが別のScriptに属するならば、そのletterの
Semanticsや見た目が同じでも別のcharacterとするが、別のlagnguageで
使用されるletterであってもそれを同じscriptにまとめらるならば統一し
て単一のcharacterにしてしまう、ということ。

** 2.3 Compatibility characters

ここは今の興味には無関係なので割愛。

** 2.4 Code Points and Characters

抽象的であるcharactersという概念は、計算機の内部では、具体的に数と
して表現される。

その数の値域をcodespaceと呼ぶ。その中のひとつの数をcode pointと呼
ぶ。

code pointとencoded characterは一対一対応ではない。例えば、Aの上に
○があるabstract character の eEncoded characterは、次の3通りがある。

code point : 00C5
code point : 212B
code point : 0041 + code point : 030A

最後のものは、letter A のcode pointとletter 上付き○のDynamic
Compositionである。

Unicodeのcode pointの表記の関連は、"U+" + 16進数である。

U+0061 LATIN SMALL LETTER A
U+201DF CJK UNIFIED IDEOGRAPH-201DF

*** Types of Code Points

code pointsはいくつかの観点でカテゴライズできる。

基本的な分類は次のとおり。

---
Graphic:
Letter, mark, number, punctuation, symbol, and spaces
Assigned to abstract character

Format:
Invisible but affects neighboring characters; includes
line/paragraph separators
Assigned to abstract character

Control:
Usage defined by protocols or standards outside the Unicode
Standard
Assigned to abstract character

Private-use:
Usage defined by private agreement outside the Unicode standard
Assigned to abstract character

Surrogate:
Permanently reserved for UTF-16; restricted interchange
Not assigned to abstract character

Noncharacter:
Permanent reserved for internal usage; restricted interchange
Not assigned to abstract character

Reserved:
Reserved for future assignment; restricted interchange
Not assigned to abstract character
---

** 2.5 Encoding Forms

計算機は数というものを数学上の数そのままとしてではなく、fixed-size
units で取り扱う。例えばbyteとか32-bit wordsとか。character
encodingはそういう現実に則して設計する必要がある。

計算機上で整数は特定のcode unitsとして実装される。ここでcode units
は、たいていが、8-bit、16-bit、32-bitである。

そこで、Unicodeのencoding formsでは、それぞれのcode point(整数)を
どのようにa sequence of code unitsとして表現するかを規程している。

The Unicode Standardでは、code units 8-bit, 16-bit, 32-bitに対応し
て、次の3のencoding formsを提供している。

UTF-8, UTF-16, UTF-32

UTFは、Unicode (or UCS) Transformation Formatの略である。

これらはどれも表現力として等価であり、相互変換がロスレスで可能であ
る。

*** Non-overlap

CP932等はoverlapするが、Unicodeはoverlapしない。これは便利。

どういうことかというと、CP932は1byteまたは2byteで表現するのだが、
2byteのleading byteと1byteが衝突することはないが、1byteと2byteの
trailing byteは数として衝突することがある。これは衝突している文字
(1byte)側を検索するときなどやっかいである。

The Unicode encoding formsではこの心配はない。lead、trail、single
だろうがなんだろうが、何かを表現している数にoverlapは存在しない。

*** Conformance

"The Unicode Consortium fully endorses the use of any of the three
Unicode encoding forms as a conformant way of implementing the
Unicode Standard. It is important not to fall int the trap of
trying todistinguish "UTF-8 versus Unicode," for example."

あり? ということは、cxml-domの記述はおかしくないか?
やはり私のそもそもの理解でただしかったのか?
もう少しUnicodeを読みといてから、考える。

*** Examples.

AΩ語(不思議な文字)

UTF-32 00000041 0000003A9 00008A9E 00010384
UTF-16 0041 03A9 8A9E D800 DF84
UTF-8 41 CE A9 E8 AA 9E F0 90 8E 84

*** UTF-32

もっともシンプル。code pointの数とcode unitの数が一対一対応。
値域は0..0x10FFFF。いわずもがなだが、code pointと同じ。
なので、U+0000..U+10FFFFというcode pointの表記そのままがencodingの
値である。


*** UTF-16

U+0000..U+FFFF (BMP)は、そのまま16-bit code unitひとつで表わす。
U+10000..U+10FFFFは、2つの16-bit code unitsであらわす。このペアを
surrogate pairと呼ぶ。surrogate pairに割り当てる領域は先の単一の
encodingに使われる領域とは隔離されている。これがnon-overlapを実現し
ている。


*** UTF-8

U+0000..&+007F ASCII code points (0x00..0x7F)

それ以外は、Table 3-6をみるのがよさげ。


うーん。とりあえず、ここまで。次回は2.6 Encoding Schemes。
なんかUnicodeのお勉強になっているが、ま、気にしない。

こつこつ。

2009年1月29日木曜日

XMLを扱う (その10) [Common Lisp]

続き。

さて、xmlsからXMLへ。

---
CL-USER(37): (with-open-file (out "example-xmls.out" :direction :output :element-type '(unsigned-byte 8))
(cxml-xmls:map-node (cxml:make-octet-stream-sink out)
'("test" (("a" "b")) ("child" nil))))
Error: serializing with :INCLUDE-NAMESPACE-URI, but node was created without namespace URI

Restart actions (select using :continue):
0: Return to Top Level (an "abort" restart).
1: Abort entirely from this (lisp) process.
[1] CL-USER(38): :reset
CL-USER(39): (with-open-file (out "example-xmls.out" :direction :output :element-type '(unsigned-byte 8))
(cxml-xmls:map-node (cxml:make-octet-stream-sink out)
'("test" (("a" "b")) ("child" nil))
:include-namespace-uri nil))
Error: File #P"example-xmls.out" already exists.
[condition type: FILE-ERROR]

Restart actions (select using :continue):
0: Return to Top Level (an "abort" restart).
1: Abort entirely from this (lisp) process.
[1] CL-USER(40): :reset
CL-USER(41): (with-open-file (out "example-xmls.out" :direction :output :element-type '(unsigned-byte 8)
:if-exists keyword::supersede)
(cxml-xmls:map-node (cxml:make-octet-stream-sink out)
'("test" (("a" "b")) ("child" nil))
:include-namespace-uri nil))
#<EXCL::BINARY-OUTPUT-FILE-STREAM #P"example-xmls.out" closed @ #x100168f642>
CL-USER(42):
---

Quick-Start examples の例がちょっとよろしくない。

sinkって何だろ?

調べる。しかし、整理された説明はない。ストリームの端や間に設置され
て、なんらかの処理をするデータ貯まりと理解しておく。

次。klacks。
---
CL-USER(42): (klacks:with-open-source
(s (cxml:make-source #p"example.xml"))
(loop
for key = (klacks:peek s)
while key
do
(case key
(:start-element
(format t "~A {" (klacks:current-qname s)))
(:end-element
(format t "}")))
(klacks:consume s)))
test {child {}}
NIL
CL-USER(43):
---
うーん。SAXに似ている?違うのはconsume?

調べる。

** JavaのStreaming API for XML (StAX)が元ネタ。
** pull-basedである。SAXはpush-basedである。
** なるほど。peekとconsumeがあることによって"pull"によって制御の流
れを書くので、制御しやすいということか。

---
CL-USER(43): (cxml:with-xml-output (cxml:make-octet-stream-sink *standard-output* :indentation 2 :canonical nil)
(cxml:with-element "foo"
(cxml::attribute "xyz" "abc")
(cxml:with-element "bar"
(cxml:attribute "blub" "bla"))
(cxml:text "Hi there.")))
<?xml version="1.0" encoding="UTF-8"?>
<foo xyz="abc">
<bar blub="bla"/>
Hi there.
</foo>
#<TERMINAL-SIMPLE-STREAM [initial terminal io] fd 0/1 @ #x1000245e42>
CL-USER(44):
---

cxmlってやたら充実してるな、、、、
まだつづく。次回は、cxml-stp。

XMLを扱う (その9) [Common Lisp]


Common LispでのXMLの取り扱いを検討するワークフロー
--------------------------------------------------

CLでのXMLの取り扱いをしらべる。まず、実践CLにあるように、S式から
XHTML(XML)に変換するインタプリタやコンパイラを作るというやり方はあ
る。ただし、要素や属性についていちいち手で追加するのか、Schemaから
自動抽出にするのかということがある。

次にライブラリでどういうものがあるかを調べる。

まずclbuildに何があるか。

---
cxml get_git git://repo.or.cz/cxml.git #XML parser and DOM implementation
cxml-stp get_lichteblau_com #STP, a DOM alternative
---

この2つの概要を調べる。
まずcxml。

http://www.cliki.net/CXML

** XML parser
** 名前空間対応
** 妥当性検証対応(対応しているSchemaは?)
** In-memory表現
*** DOM
*** xmls形式
*** cxml-stp (あ、これはcxmlのadd-onなのね)
** cxml-rngというadd onにてRelax NGに対応。
** plexippus-xpathにてXPath対応。
** HTMLにはclosure-htmlで対応。
** Closure web browserに利用されている。

というわけで、cxml-stpとは比較対象ではなく、同一の選択肢であった。

知らないことを確認する。

xmls形式って何?

http://www.cliki.net/XMLS
http://common-lisp.net/project/xmls/

---
<?xml version="1.0"?>
<!-- test document -->
<book title='The Cyberiad'>
<!-- comment in here -->
<author xmlns='http://authors'>Stanislaw Lem</author>
<info:subject xmlns:info='http://bookinfo' rank='1'>"Cybernetic Fables"</info:subject>
</book>
---

これが、

---
("book" (("title" "The Cyberiad"))
(("author" . "http://authors") NIL "Stanislaw Lem")
(("subject" . "http://bookinfo") (("rank" "1")) "\"Cybernetic Fables\""))
---

これになる、と。

ルールは、次のようだ。

** 要素名 -> 文字列
** 名前空間URI -> 文字列
** 要素(名前空間なし) -> リスト (要素名 属性リスト 子要素*)
** 要素(名前空間あり) -> リスト ((要素名 . 名前空間) 属性リスト 子要素)
** 属性名 -> 文字列
** 属性(名前空間なし) -> リスト ((属性名 属性値) ...)
** 属性(名前空間あり) -> これがわからない。

試す。

(asdf:oos 'asdf:load-op 'xmls)

---
CL-USER(12): (xmls:parse "<book xmlns='http://n1'><author att='piyo'>test</author></book>")
(("book" . "http://n1") NIL (("author" . "http://n1") (("att" "piyo")) "test"))
CL-USER(13): (xmls:parse "<book xmlns='http://n1' xmlns:n2='http://n2'><author att='piyo'>test</author></book>")
(("book" . "http://n1") NIL (("author" . "http://n1") (("att" "piyo")) "test"))
CL-USER(14): (xmls:parse "<book xmlns='http://n1' xmlns:n2='http://n2'><n2:author att='piyo'>test</author></book>")
(("book" . "http://n1") NIL (("author" . "http://n2") (("att" "piyo")) "test"))
CL-USER(15): (xmls:parse "<book xmlns='http://n1' xmlns:n2='http://n2'><author n2:att='piyo'>test</author></book>")
(("book" . "http://n1") NIL (("author" . "http://n1") (("att" "piyo")) "test"))
CL-USER(20): (xmls:parse "<x xmlns:edi='http://ecommerce.example.org/schema'><lineItem edi:taxClass='exempt'>Baby food</lineItem></x>")
("x" NIL ("lineItem" (("taxClass" "exempt")) "Baby food"))
---

なるほど。属性については名前空間に対応していないのだな。これは困る
だろう。

さて、cxmlを使ってみる。

(asdf:oos 'asdf:load-op 'cxml)

使いかた情報はここにあるようだ。

http://common-lisp.net/project/cxml/

Quick-Startにしたがって多少いじってみる。
---
CL-USER(27): (with-open-file (s "example.xml" :direction :output)
(write-string "<test a='b'><child/></test>" s))
"<test a='b'><child/></test>"
CL-USER(28): (cxml:parse-file "example.xml" (rune-dom:make-dom-builder))
#<RUNE-DOM::DOCUMENT @ #x10014c8292>
CL-USER(29): (defparameter *example* *)
*EXAMPLE*
CL-USER(30): *
*EXAMPLE*
CL-USER(31): *example*
#<RUNE-DOM::DOCUMENT @ #x10014c8292>
CL-USER(32): (dom:document-element *example*)
#<RUNE-DOM::ELEMENT test @ #x1000e185f2>
CL-USER(33): (dom:tag-name *)
"test"
CL-USER(34): (with-open-file (out "example.out" :direction :output :element-type '(unsigned-byte 8))
(dom:map-document (cxml:make-octet-stream-sink out) *example*))
#<EXCL::BINARY-OUTPUT-FILE-STREAM #P"example.out" closed @ #x1001407c12>
CL-USER(35): (cxml:parse-file "example.xml" (cxml-xmls:make-xmls-builder))
("test" (("a" "b")) ("child" NIL))
CL-USER(36): (cxml:parse-file "example-ns.xml" (cxml-xmls:make-xmls-builder))
("x" ((("edi" . "http://www.w3.org/2000/xmlns/") "http://ecommerce.example.org/schema")) "
" ("lineItem" ((("taxClass" . "http://ecommerce.example.org/schema") "exempt")) "Baby food") "
")
CL-USER(37):
---

ここでexample-ns.xmlの中身は次のもの。

---
<x xmlns:edi='http://ecommerce.example.org/schema'>
<lineItem edi:taxClass='exempt'>Baby food</lineItem>
</x>
---

cxmlのxmls-likeというのは属性の名前空間にも対応している。


この項、つづく。

2009年1月28日水曜日

XMLを扱う (その8) [Atom]

実際のAtom feedをみてみる。

$ curl http://aka-cs-blog.blogspot.com/feeds/posts/default > aka-feed.atom

中をみてみると。

  • 改行が無い。(そりゃそうだ。帯域大事)
  • ファイル容量がけっこう多い。(下の例ではエントリを一つだけにした。他は削除)
  • なんと、勝手拡張?なのか、OpenSearchと混ぜている。
  • さて、なんでfeedの中にOpenSearchがあるのかしら、と考えてみる。きっとこのfeedを作るのに検索を実施していることの副作用として入っているのだろう。
  • しかしこういう風に混ぜちゃうと妥当性検証もへったくれもないな、、、



<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?>
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'>
<id>tag:blogger.com,1999:blog-5289049604340113831</id>
<updated>2009-01-28T11:10:24.516+09:00</updated>
<title type='text'>計算機とその周辺</title>
<subtitle type='html'></subtitle>
<link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://aka-cs-blog.blogspot.com/feeds/posts/defau\
lt'/>
<link rel='self' type='application/atom+xml' href='http://aka-cs-blog.blogspot.com/feeds/posts/default'/>
<link rel='alternate' type='text/html' href='http://aka-cs-blog.blogspot.com/'/>
<link rel='next' type='application/atom+xml' href='http://aka-cs-blog.blogspot.com/feeds/posts/default?start-index=26&max-results\
=25'/>
<author><name>aka</name><uri>http://www.blogger.com/profile/02301993913128404609</uri><email>noreply@blogger.com</e\
mail></author>
<generator version='7.00' uri='http://www.blogger.com'>Blogger</generator>
<openSearch:totalResults>450</openSearch:totalResults>
<openSearch:startIndex>1</openSearch:startIndex>
<openSearch:itemsPerPage>25</openSearch:itemsPerPage>
<entry>
<id>tag:blogger.com,1999:blog-5289049604340113831.post-2409689848169847100</id>
<published>2009-01-28T11:06:00.002+09:00</published>
<updated>2009-01-28T11:10:24.533+09:00</updated>
<app:edited xmlns:app='http://purl.org/atom/app#'>2009-01-28T11:10:24.533+09:00</app:edited>
<category scheme='http://www.blogger.com/atom/ns#' term='atom'/>
<category scheme='http://www.blogger.com/atom/ns#' term='xml'/>
<category scheme='http://www.blogger.com/atom/ns#' term='emacs'/>
<title type='text'>XMLを扱う (その7) [Atom]</title>
<content type='html'>Atomを例に名前空間の理解の確認を。<br /><pre><br /> Atomでは、xhtmlの要素も使える。&l\
t;br /><br /> それにはまずxhtmlの語彙を指定する。<br /><br /> ---<br /> namespace xhtml = \
"http://www.w3.org/1999/xhtml"<br /> ---<br /><br /> これで語彙は使えるようになるが、その語彙が母体たるAto\
mの中でどのよ<br /> うな構造の一部となるかは、AtomのSchemaの中で指定しなければならない。<br /><br /> それ\\
にはまず、xhtml:*の形の要素の定義が必要。<br /><br /> ---<br /> # XHTML<br /><br /> any\
XHTML = element xhtml:* {<br /> (attribute * { text }<br /> | text<br /> | anyXHTML)*<br /\
> }<br /><br /> xhtmlDiv = element xhtml:div {<br /> (attribute * { text }<br /> \
| text<br /> | anyXHTML)*<br /> }<br /> ---<br /><br /> それを母体の要素でど\
のように使えるかは次のように定義。<br /><br /> ---<br /> atomXHTMLTextConstruct =<br /> ato\
mCommonAttributes,<br /> attribute type { "xhtml" },<br /> xhtmlDiv<br /><br /> atomTextC\
onstruct = atomPlainTextConstruct | atomXHTMLTextConstruct<br /><br /> atomTitle = element atom:title { atomTextConstru\
ct }<br /> ---<br /><br /> これをatom上で利用するには次のよう。<br /><br /> ---<br /\
> ...<br /> &lt;title type="xhtml" xmlns:xhtml="http://www.w3.org/1999/xhtml"><br /> &lt;\
xhtml:div><br /> Less: &lt;xhtml:em> &lt; &lt;/xhtml:em><br /> &lt;/xhtml:div>\
<br /> &lt;/title><br /> ...<br /> &lt;summary type="xhtml"><br /> &am\
p;lt;div xmlns="http://www.w3.org/1999/xhtml"><br /> This is &lt;b>XHTML&lt;/b> content.<br /> \
&lt;/div><br /> &lt;/summary><br /> ...<br /> &lt;summary type="xhtml">&\
lt;br /> &lt;xh:div xmlns:xh="http://www.w3.org/1999/xhtml"><br /> This is &lt;xh:b>XHTML&l\
t;/xh:b> content.<br /> &lt;/xh:div><br /> &lt;/summary><br /> ...<br /> \
---<br /><br /> ふむ。理解に間違いはなさそうだ。<br /> それにしても、<br /><br /> \
anyXHTML = element xhtml:* ...<br /><br /> と書けるRelax NGって便利だなぁ。<br /></pre><br /><br \
/>なかなかCLに辿りつけないが、こつこつ。</content>
<link rel='replies' type='application/atom+xml' href='http://aka-cs-blog.blogspot.com/feeds/2409689848169847100/comments/default' t\
itle='コメントの投稿'/>
<link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5289049604340113831&postID=2409689848169847\
100' title='0 件のコメント'/>
<link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5289049604340113831/posts/default/24096898481698471\
00?v=2'/>
<link rel='self' type='application/atom+xml' href='http://aka-cs-blog.blogspot.com/feeds/posts/default/2409689848169847100'/>
<link rel='alternate' type='text/html' href='http://aka-cs-blog.blogspot.com/2009/01/xml-7-atom.html' title='XMLを扱う (その7) [Ato\
m]'/>
<author>
<name>aka</name>
<uri>http://www.blogger.com/profile/02301993913128404609</uri>
<email>noreply@blogger.com</email>
</author>
<thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total>
</entry>
</feed>


こつこつ。

XMLを扱う (その7) [Atom]

Atomを例に名前空間の理解の確認を。

Atomでは、xhtmlの要素も使える。

それにはまずxhtmlの語彙を指定する。

---
namespace xhtml = "http://www.w3.org/1999/xhtml"
---

これで語彙は使えるようになるが、その語彙が母体たるAtomの中でどのよ
うな構造の一部となるかは、AtomのSchemaの中で指定しなければならない。

それにはまず、xhtml:*の形の要素の定義が必要。

---
# XHTML

anyXHTML = element xhtml:* {
(attribute * { text }
| text
| anyXHTML)*
}

xhtmlDiv = element xhtml:div {
(attribute * { text }
| text
| anyXHTML)*
}
---

それを母体の要素でどのように使えるかは次のように定義。

---
atomXHTMLTextConstruct =
atomCommonAttributes,
attribute type { "xhtml" },
xhtmlDiv

atomTextConstruct = atomPlainTextConstruct | atomXHTMLTextConstruct

atomTitle = element atom:title { atomTextConstruct }
---

これをatom上で利用するには次のよう。

---
...
<title type="xhtml" xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:div>
Less: <xhtml:em> < </xhtml:em>
</xhtml:div>
</title>
...
<summary type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
This is <b>XHTML</b> content.
</div>
</summary>
...
<summary type="xhtml">
<xh:div xmlns:xh="http://www.w3.org/1999/xhtml">
This is <xh:b>XHTML</xh:b> content.
</xh:div>
</summary>
...
---

ふむ。理解に間違いはなさそうだ。
それにしても、

anyXHTML = element xhtml:* ...

と書けるRelax NGって便利だなぁ。


なかなかCLに辿りつけないが、こつこつ。

XMLを扱う (その6) [Atom]


Atomを扱えるようにするワークフロー
----------------------------------

nxml-modeの配布にatomのrncが含まれているか確認。
含まれていない。

rfc4287からコピペで作成。
これは確立されたschemaなので、~/local/lib/schema/に置くことにする。
nxml-modeのschemaディレクトリには入れない。入れるとnxml-modeの更新
時の作業がややこしくなる。

rnc作成モードもあるようだが、今は使わない。将来やる。

コピペ完了。

中身をみるとSchematronを名前空間で参照している。
Schematronのrncは存在するのか?

http://xml.ascc.net/schematron/

には存在しない。

念のため上記URIから
Schematron schema
XML Schema schema
DTD schema

を取得する。とやってたら、

http://www.schematron.com/spec.html

を発見。

RELAX NG Comapact Syntax schema for ISO Schematron

だって。あるじゃん。

iso-schematron.rnc

を入手。~/local/lib/schema/に設置。

さて、rfcのrncのnamespaceが、

namespace atom = "http://www.w3.org/2005/Atom"

を含んでいるのがわからない。自分のことじゃないの??

http://relaxng.org/compact-tutorial-20030326.html

を確認する。

わかった。自分のことなのだ。

atom.rncにてelementを定義しているところはすべてatom:hogeになってい
る。で、atom:が付いていないシンボル?は、グラマーなどの名前につか
われている。感覚的に言うと、namespace atomの名前たちはexternalであ
り、namespace localの名前達はinternalという感じ。

もちろん、XML側での名前空間の利用時は、

<feed xmlns="http://www.w3.org/2005/Atom">

などとxmlnsをprefixなしで指定するから、atom:は不要である。

これで、rncは揃った。nxml-modeへの登録だ。

変数 rng-schema-locating-filesに
locating-filesに~/local/lib/schema/schemas.xmlを登録する。

(push "~/local/lib/schema/schemas.xml" rng-schema-locating-files)

そして、schemas.xmlはこんな感じ。

----
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
<uri pattern="*.atom" typeId="ATOM"/>
<uri pattern="*.sch" typeId="SCHEMATRON"/>

<namespace ns="http://www.w3.org/2005/Atom" typeId="ATOM"/>
<namespace ns="http://www.ascc.net/xml/schematron" typeId="SCHEMATRON"/>

<typeId id="ATOM" uri="atom.rnc"/>
<typeId id="SCHEMATRON" uri="iso-schematron.rnc"/>
</locatingRules>
----

これで、*.atomを開くと、、、お、自動的にSchemaが選択された。


道程は長い。こつこつ。

2009年1月26日月曜日

<を& l t ;に手で変換している件について

M-x replace-regexpで一括変換するかどうかは問題ではなく、<pre></pre>でソースコードを記載しているのは何かがおかしい。何かがまちがっている。。。

XMLを扱う (その5)

ChangeLog-modeからもってきたので、読みにくかったらすいません。

そういえば、XML namespaceというのを正確には理解していない気がする。まずそ
れをやる。

** 読むべきは、Namespaces in XML 1.0 (Second Edition)

** 隅から隅まで理解したいわけじゃない。そして、XMLのnamespaceって
Common Lispなどのプログラミング言語の名前空間とはかなり違うものであ
ること自体はそこそこ捉えている。

** 興味は、namespaceを指定するURIのあり様がいまどうなっているのか、
ということ。namespaceを実際に規程するのがスキーマ定義文書だとすると、
それが要素や属性を規程する様との兼ね合いにおいてそれを理解したいと
いうこと。

*** an XML namespaceはURIで特定される。

*** an expanded nameはa namespace name とa local nameのa pairである。

*** a name NがURI Iで特定されるa namespaceに属するとき、the namespace
nameはIである。

*** a name Nがどのnamespaceにも属さないとき、them namespace nameは
値が空である。

*** いずれにしても、the local nameはNである。

*** URI自体は、XML文書の中での要素や属性にそのまま使うことはない。
かわりに、qualified namesを使う。

*** qualified namesは、2通りあり、prefixed namesかunprefixed names
である。

*** 属性にてnamespaceを宣言する構文(よくみるやつ)は、prefixesと
namespace namesをbindする。そこで、a default namespaceを指定でき、
それがunprefixed namesとなる。

*** 前項の構文はそこかしこの要素の属性として記述できる。その記述に
したがってスコーピングされる。


*** namespace参照につかわれるURIについて

**** 空文字列は禁止。

**** 相対URIは廃止された。自文書参照も廃止された。

**** URIは、名前が同じ名前空間に属するかどうかの判定に使われる。そ
の判定は、URIどうしを文字列として比較して行う。

**** 次のものは場合によってURIとして指しているリソースは同じかもし
れないが、名前空間としては別である。

------------
http://www.example.org/wine
http://www.Example.org/wine
http://www.example.org/Wine
------------

**** 次のものはURIとして指しているリソースは同じかもしれないが、名
前空間としては別である。

------------
http://www.example.org/~wilbur
http://www.example.org/%7ewilbur
http://www.example.org/%7Ewilbur
------------

*** 名前空間の指定

こんな感じ。

------------
<x xmlns:edi='http://ecommerce.example.org/schema'>
<!-- the "edi" prefix is bound to http://ecommerce.example.org/schema
for the "x" element and contents -->
</x>
------------

*** qualified names

こんな感じ。

------------
<!-- the 'price' element's namespace is http://ecommerce.example.org/schema -->
<edi:price xmlns:edi='http://ecommerce.example.org/schema' units='Euro'>32.18</edi:price>
------------
------------
<x xmlns:edi='http://ecommerce.example.org/schema'>
<!-- the 'taxClass' attribute's namespace is http://ecommerce.example.org/schema -->
<lineItem edi:taxClass="exempt">Baby food</lineItem>
</x>
------------

** 名前空間とスキーマと妥当性検証について

さて、URIによって名前空間が特定される。名前空間はXMLSchemaで記述さ
れているとする。すると、URIと具体的なXMLSchemaのbindを管理している
人がいる。そのbindはどうすればわかるのか? URIが、
http://www.w3.org/1999/xhtml
などの場合は、このドメインの所有者に問合わせればいいのだろう。では、
urn:loc.gov:books
などの場合は、どうするのだ?というとIANAをみればいいのかな。

URN Namespaces

いずれかによって、XMLSchemaを入手できる。ここで疑問がある。このよう
にして人間はbindを知ることができるが、ソフトウエアであるXMLプロセッ
サ(やバリデータ)はどうやってこのbindを知るのだろう?

jingの場合は引数で明示的にSchema (例えばrnc)を渡す。すなわち
default namespace のSchemaをここで指定するのだろう。そしてそのrncの
中には、

namespace ab = "http://www.hoge.com/addressBook"

などと参照するnamespaceの定義がある。ここでは、

http://www.hoge.com/addressBook.rnc

がリソースとして存在していることを仮定しているようだ。

nxml-modeの場合は、locating filesにlocating rulesを記述しておき、
それによって探してくる方式だ。例えば、

------------
<?xml version="1.0"?>
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
<namespace ns="http://www.w3.org/1999/xhtml" uri="xhtml.rnc"/>
<documentElement localName="book" uri="docbook.rnc"/>
</locatingRules>
------------

など。というわけで、何かを仮定したり、何かで人が指定してあげるとい
うことなのだろう。

さて、それらXMLSchemaはどう役に立つのかというと、

------------
<?xml version="1.0"?>
<!-- initially, the default namespace is "books" -->
<book xmlns='urn:loc.gov:books'
xmlns:isbn='urn:ISBN:0-395-36341-6'>
<title>Cheaper by the Dozen</title>
<isbn:number>1568491379</isbn:number>
<notes>
<!-- make HTML the default namespace for some commentary -->
<p xmlns='http://www.w3.org/1999/xhtml'>
This is a <i>funny</i> book!
</p>
</notes>
</book>
------------

みたいなケースにおいて、urn:ISBN:0-395-26341-6に紐付けられたSchema
によって、isbn:numberの型が何であるかがわかる。また、
urn:loc.gov:booksに紐付けられたSchemaによって、book要素の中にtitle
要素を入れていいことがわかる。ここで要注意なのは、さらには、この
Schemaによって、isbn:number要素も入れていいこともわからなくてはいけ
ないのだ。そうでなければ、ここでのbook要素の妥当性チェックをすると
きに、isbn:numberが未知の要素であることになりエラーとなってしまうだ
ろう。

XML namespacesだけを考えているときは、そこかしこにあるSchemaを
xmlnsで指定して語彙拡張できるような単純足し算なものということでで
よいのだけど、 そうやってつくった文書全体の妥当性チェックを考えると、
結局デフォルトSchemaで足し算のあり様がどのようなものなのかを詳細に
記述しなければならない。先の2つの親たるSchemaがあればいいだけでな
く、それをどういう風に組み合わせて使うのかを定義するSchemaが必要で
あり、それは構造に関しては少なからぬ再定義が必要となる。

それゆえ、namespaceを使って再利用するのは構造をもったデータ型でなく、
いわゆる Simple data type がよいのかもしれない。

平日に多少でも進めたのがうれしい。

次回は例を作ってためしてみる。

XMLを扱う (その4)

残件。

  • nxml-modeでnamespaceはどういう扱いになっているのか。
  • スキーマファイルの配置に関する検討。

こつこつ。

XMLを扱う (その3)


  • nxml-modeはrncのみのサポートだった。rngはrncに変換してね、と。
  • 変換にはtrangを使うのがよさげ。
    DLして配置。

    $ java -jar ~/local/lib/java/trang-20081028/trang.jar -I rng -O rnc addressbook.rng addressbook-1.rnc

    で動いた。

  • ふむ。整理してみる。

    • XMLはいろいろなところに存在している。
    • Common Lispでプログラミングするにしても、XMLとは無縁ではいられない。
    • Common Lisp自体には、FranzのモジュールやCL-XMLなどがある。
    • しかし、手でXMLを扱うことも開発の中ではある。
    • それはEmacsだろう。
    • モードはnxml-modeとする。
    • nxml-modeはスキーマとしてrncを採用している。
    • 各種スキーマをrncにもってこれればnxml-modeの機能を使ってXMLを編集できるということ。
    • 2つのツールをつかう。

      • schematools: xsd->rnc
      • trang: (dtd rng xml-instance)->rnc

    • rncを使ったvalidationは、nxml-modeまたはjingで実施する。



大枠は整理できた。こつこつ。

XMLを扱う (その2)

もしや、Eclipseならとおもったら、あった。

XML Buddy

しかしEclipseはできるだけ使いたくないなぁ。開発環境はshellとEmacsに絞りたい。開発環境を広げると、そのこと自体に時間がとられるからなぁ。

XMLを扱う

XMLを扱うためのインフラを準備。

  • nxml-modeをいれてみる。
  • nxml-modeはRelax NGがメイン。
  • 世の中にはXMLSchemaで記述されたスキーマも多い。
  • スキーマ変換を用意せねば。しかしあの複雑なXMLSchemaをすべて変換できるものなどあるのだろうか?
  • schematoolsをためすことにする。
  • XMLSchemaをちょこっと復習。こりゃやっぱり複雑だ。
  • XML Schemaを取扱えるライブラリを多少探してみたが、みつからない。libxml2ですら部分的にしか対応していない。Emacs LispにしてもCommon LispにしてもXML Schemaは避けられている感じ。XMLSpyなどのIDEなら使えるものが多い。オープンソースでの対応が進んでいないということなのか。
  • XML Schema Primerで例示されているxsdをschematoolsでrncに変換してみる。rncが生成されており、エラー通知もない。ところで、rngとrncを復習すべき。まず、RELAX NG Tutorialを。
  • むむ。nxml-modeに問題。rncなスキーマは読み込んで、快調にうごく。しかし、rngなファイルは、no schema loader available for file extension 'rng' となる。対応してないのかね。

とりあえず、ここまで。

こつこつ。

2009年1月25日日曜日

ルポルタージュと言語力

ちょっと誤解を与えるかな、と思ったので、補足を。

ものごとの深層を捉えるには、得られた情報を整理し、それらを吟味することが必要になる。場合によって新しい概念への抽象化が必要になる。抽象と具象をいったりきたりもする。それには言語の力が重要だ。なので、実は表現をする段だけではなく、そもそも考えを形成していく際にも言語力のよしあしが効いてくる。ここの事情があるので、自分としてはなるべく柔軟な言語で思考したいと思い、Lispを選択している。自分の思考が例えばJavaに制約されていくのは苦痛だからだ。

言語力で指しているのは言語なだけに、それはさまざまな思考の根底とはなっている。その上で、プログラムを書くということは対象領域のルポルタージュ的側面が強いということ。

プログラミングとルポルタージュ

クヌース先生はプログラミングは文学であるといっていたらしいが、自分にはどうもルポルタージュに思える。プログラミング言語にいくら精通していてもそれだけではよいプログラムは書けない。というかそれだけではプログラムを書く対象というかモチベーションが存在しない。解決すべき対象に対する調査や知見があって、初めてプログラムを書くことができる。文学もものによってそういう側面があると思うが、より直接的なのはルポルタージュだ。いろいろな手法を用いて根気よく調査して対象の深層を捉える。それを表現するところで言語力がものをいう。

2009年1月24日土曜日

GTD

あまりに業務がいそがしいので、GTDをやってみている。


  • アプリはOmniFocus。
  • GTDというメソッドはいい感じ。
  • OmniFocusもわるくないが、私の場合、アクションと業務が複雑に関連しているので、もうちょっと機能が欲しいところ。
  • rubikitchさんのところでorg-modeでGTDもできるというのがあった。先々はorg-modeに挑戦してみるか。


やってみてGTDでは問題は解決しないことがわかった。GTD自体はいい感じだが。
打ち合わせの数が多すぎるのだ。打ち合わせの準備をして、打ち合わせをして、打ち合わせの結果を周知して、ということで手一杯。一日あたり、大小15個くらいの打ち合わせがある。

逆に言うと、それをなんとかすればなんとかなるかも、ということがわかった。

こつこつ。

mac に ubuntu

業務多忙にてなかなか勉強ができない。それはまた別で書くとして、macにubuntuをいれたい。何かをするときに、macの流儀にしたがっていろいろ調整する時間が惜しいからだ。

http://saladwithsteve.com/2008/02/ubuntu-on-mac-pro.html
http://urakaze.com/post-292.html
http://nu4.nu/tbomb/

大枠としては、

1. refit導入
2. ubuntu LIVE CDでインストール作業
3. カーネル変更
4. 細かい設定変更

という感じ。さて、明日やってみようかな。

こつこつ。

2009年1月19日月曜日

JSONとCL (その3)

ああ、わかった。yasonのskip-whitespaceの問題ではない。

\\nなどがJSONの文字リテラルになるのは、JSONの文字列の中なのだ。だから

"\\n"

は、json:parseに対して\nというシンボルを与えているにすぎない(シンボルリテラルということ)。これがjson:parseにとってNewlineの意味になるのは、

"\"\\n\""

においてだ。なので、json:parseに与えられるストリームや文字列として改行コードをスキップしますよ、というのは、JSONの外として与えるべきであり、それは、

(json:parse (format nil "{ \"input_01\" : 123,~% \"input_02\" : \"hoge\" }"))

などであり、これは

;; => #<EQUAL hash-table with 2 entries @ #x10013ae732>

と正しくskip-whitespaceされてエラーにならない。

なお、ここで言っているJSONの意味とはCLオブジェクトによる意味論である。

こつこつ。

JSONとCL (その2)

yasonを使って、jsonを含むテキストチャンクからJSONらしき部分を抽出する処理を書いた。不細工な書きぶりだけどそこそこ動く。

;; 多値でparse結果を返す関数
(defun analyze (string &key (start 0))
(handler-case (values (with-input-from-string (s string :index index :start start)
(json:parse s))
index t)
(condition () (values nil (incf start) nil))))

;; それを使ってそれなりのチャンクを処理する関数
(defun analyze-chunk (chunk)
(let ((result)
(len (length chunk))
(start 0))
(loop
(multiple-value-bind (match new-start match-p)
(analyze chunk :start start)
(when match-p
(push match result))
(when (> new-start len)
(return (nreverse result)))
(setq start new-start)))))

(analyze-chunk "テストデータを作ってみました。\\n\\r{ \"input_01\" : 123, \"input_02\" : \"hoge\" }\\n\\rこんな感じでいいんでしたっけ?")
;; => (#<EQUAL hash-table with 2 entries @ #x10010b53a2>)
(analyze-chunk "abcd{\"hoge\" : 3} ほげほげ 3")
;; => (#<EQUAL hash-table with 1 entry @ #x10010ee552> 3)
(analyze-chunk "abcd{\"hoge\"\" : 3} ほげほげ 3 [3, 8 ,2")
;; => ("hoge" 3 3 3 8 2)
(analyze-chunk "abcd{\"hoge\"\" : 3} ほげほげ 3 [3, 8 ,2]")
;; => ("hoge" 3 3 (3 8 2))
(analyze-chunk "abcd{\"hoge\" : 3} ほげほげ 3 [3, 8 ,2]")
;; => (#<EQUAL hash-table with 1 entry @ #x100117aef2> 3 (3 8 2))

;; これはerrorになる。skip-whitespaceがおかしい?
(json:parse "{ \"input_01\" : 123,\\n\\r \"input_02\" : \"hoge\" }")

yasonのskip-whitespace関係のせいか、JSON構造の中に改行コードがあるとjson:parseがエラーになる。
これは次回探ってみる。

こつこつ。

2009年1月18日日曜日

【実践CL】19 例外処理を越えて:コンディションと再起動

事情によりスキップして19章へ。

  • こんなシチュエーションを想定しているようだ。

    (defun high (...)
    ...
    (medium ...)
    ...)

    (defun medium (...)
    ...
    (low ...)
    ...)

    (defun low (...)
    ...))

  • lowが失敗し、mediumがそれに対応できないことがありえるとする。highをどうしておくべきか。
  • 選択肢1:原因にしたがって、mediumが担当すべきだった作業含めてhighが実施。これはmediumの機能をほぼhighがもっていることになり、なんだか、という点と、この例のような三階層じゃなくて階層が増えたらhighに詰む機能が膨大になるという課題がある。
  • 選択肢2:パッチをあてる。再度mediumがlowを呼び出したときにlowがエラーを出さないようにする処理をhighが実施して再度mediumを呼出す。これも、mediumの内部仕様についてhighを書く人が熟知していることになるので、関数のブラックボックス性から言うと好ましくない。
  • なんかうまい方法があるの? あるよ。それがCLのコンディションシステム。

  • 19.1 Lispのやり方

    • ログを解析する仮想的なソフトウエアを例にLispのやり方を説明する。
    • 状況設定。

      Webサーバのログのようなテキスト形式のログファイルを読むソフトウエア。

      parse-log-entry:
      入力:ひとつのログエントリを含むテキスト
      出力:log-entryオブジェクト

      parse-log-file:
      入力:ひとつのログファイル
      出力:log-entryオブジェクトのリスト


  • 19.2 コンディション

    • 基礎情報。

      • conditionはstandard-objectの系列ではない。
      • conditionオブジェクトは、make-conditionで生成する。
      • conditionオブジェクトの中身へのアクセスはslot-valueではアクセスできない。
      • conditionオブジェクトの定義には、define-conditionを使う。

    • ここの状況での定義。

      ;; parse-log-entryがパースできないテキストを与えられた時に通知するコンディション
      (define-condition malformed-log-entry-error (error)
      ((text :initarg :text :reader text)))


  • 19.3 コンディションハンドラ

    • コンディションの通知はerrorによって実施する。
    • errorの呼び出し方法は2つ。
    • 1:事前にインスタンス化したconditionオブジェクトをerrorの引数にする。
    • 2:コンディションクラスの名前とそれへの引数をerrorの引数にする。
    • ここの状況での定義。

      ;; parse-log-entryのアウトライン
      (defun parse-log-entry (text)
      (if (woll-formed-log-entry-p text)
      (make-instance 'log-entry ...)
      (error 'malformed-log-entry-error :text text)))


    • コンディションが発行されたときに、何が起こるかは、コールスタック上で発行地点(parse-log-entry)より下に何があるかによる。
    • デバッガに入らないためには、どこかでコンディションハンドラを確立している必要がある。
    • コンディションハンドラは、コンディションハンドラ自体とそれを取扱う処理系部分とで理解すべき。
    • コンディションハンドラの基本事項は次のとおり。

      • コンディションハンドラは、取扱対象コンディションの型指定子と、コンディションを引数とする関数から構成される。
      • コンディションハンドラは、コードのどこかで処理系に登録され、アクティブ状態になる。
      • コンディションハンドラ内関数で、該当コンディションを処理しないこともできる。その場合、処理系に制御は戻る。

    • 処理系は次のとおり。

      • コンディションが発生した場合、アクティブなコンディションハンドラのリストを探索して、その型に対応するコンディションハンドラを呼ぶ。
      • 同じ型に対するコンディションハンドラが複数ある場合は、スタック上の距離で、コンディション発生地点に近いものが呼ばれる。
      • 呼んだコンディションハンドラが処理を拒否した場合は、次のハンドラが存在すれば、それを呼ぶ。
      • コンディションハンドラを呼んだ時点ではスタックは巻き戻らない。処理の流れをどうするかはユーザが決めることだ。

    • handler-caseは、コンディションハンドラを作成し登録する。そして処理系は、conditionが発生した場合、スタックをコンディションハンドラ登録ポイントまで巻き戻し、コンディションハンドラを実行する。
    • ここの状況での定義。

      (defun parse-log-file (file)
      (with-open-file (in file :direction :input)
      (loop for text = (read-line in nil nil) while text
      for entry = (handler-case (parse-log-entry text)
      (malformed-log-entry-error () nil))
      when entry collect it)))

    • これはparse-log-fileとしては、やりすぎである。というのは、無視することを決めこんでいるからだ。不正なエントリがあったときにどうすべきかは、parse-log-fileを使う関数側で指定できるべきだろう。

  • 19.4 再起動

    • これを実現するには、parse-log-fileでは、condition発生時に実行可能なrestartの選択肢を登録するにかぎるようにする。
    • それにはrestart-caseを使う。
    • ここの状況での定義。

      (defun parse-log-file (file)
      (with-open-file (in file :direction :input)
      (loop for text = (read-line in nil nil) while text
      for entry = (restart-case (parse-log-entry text)
      (skip-log-entry () nil))
      when entry collect it)))

    • さて、ここで例として、parse-log-fileの上位に位置する(parse-log-fileを利用する)関数を2つ定義する。

      (defun log-analyzer ()
      (dolist (log (find-all-logs))
      (analyze-log log)))

      (defun analyze-log (log)
      (dolist (entry (parse-log-file log))
      (analyze-entry entry)))

    • これらの中で、malformed-...が発行された場合の対処を指定したい。handler-caseを使うと、そこまで巻き戻ってしまう。
    • そこで、handler-bindを使う。log-analyzerの中で定義する。

      (defun log-analyzer ()
      (handler-bind ((malformed-log-entry-error
      #'skip-log-entry))
      (dolist (log (find-all-logs))
      (analyze-log log))))

      (defun skip-log-entry (c)
      (let ((restart (find-restart 'skip-log-entry)))
      (when restart (invoke-restart restart))))


  • 19.5 複数の再起動を提供する

    • 最下層のparse-log-entryに、2つのrestartを導入する。

      (defun parse-log-entry (text)
      (if (woll-formed-log-entry-p text)
      (make-instance 'log-entry ...)
      (restart-case (error 'malformed-log-entry-error :text text)
      (use-value (value) value)
      (reparse-entry (fixed-text) (parse-log-entry fixed-text)))))

    • このうちのuse-valueを上位で指定して使うとしたら、例えば次のようだ。

      (defun log-analyzer ()
      (handler-bind ((malformed-log-entry-error
      #'(lambda (c)
      (use-value
      (make-instance 'malformed-log-entry :text (text c))))))
      (dolist (log (find-all-logs))
      (analyze-log log))))


  • 19.6 コンディションの別な使い道

    • errorとwarnとcerrorの差異。うーん。よくわからん。


自分なりに、こつこつ。

JSONとCL

業務が大変忙しい。その合間をぬって、JSONとCLについて作業をすすめていた。とにかくこつこつ。


  • JSONのサンプルを作ろうとして、どうも作業しずらいなと感じた。何故かと考えると、REPLがないからだ。探してみると、SpiderMonkeyはREPLがあった。macportsにあるのでインストール。これは便利。
  • 続いて、これをcomintできるのかどうか。探すと、js-comintがあった。これも便利。
  • REPLでJSONのサンプルを試していると、どうも不可思議な振舞いがある。JSONをそもそものJavaScriptにて理解しようとすると、それなりに深くJavaScriptを理解しなければいけなさそう。それは嫌。
  • というわけで、yasonを使って、CLにてJSONの意味論を考えることにした。
  • CL上のテストデータとして、JSON文字列を作成し、これがどのようなCLオブジェクトに変換されるかにてJSONを理解する、ということ。これはうまくいった。

  • 続いて、JSONが文中に埋め込まれているようなテキストをパースできるように作業開始。例えば、

    テストデータを作ってみました。

    { "input_01" : 123,
    "input_02" : "hoge" }

    こんな感じでいいんでしたっけ?

    というテキストから、JSONデータな部分のみを特定してCLオブジェクトに変換するようなもの。
  • これにはyasonのsignalingのつくりの理解が必要。で、yasonのソースリーディング。
  • CLのcondision systemの復習が必要。
  • 実践CLの該当部分を先にやろう

地道にこつこつ。

2009年1月15日木曜日

JSON ???

JSONって変じゃないか?
"x"はJSONでのStringのリテラルなのだが、javascriptでevalしてみると。

js> eval( "x" );
eval( "x" );
typein:90: ReferenceError: x is not defined
js>

となって、シンボルxを参照する処理になる。"x"はシンボルのリテラルなのか?

JSONをちゃんと使えるようになるには、JavaScriptをちゃんと勉強しないといけないのか? それは避けたい、、、

2009年1月13日火曜日

mmm-mode (xhtml + css + javascript)

Web標準編集用に、いろいろ参考にしながら、こんな感じで設定してみた。
とりあえず、動いている。様子をみる。


;;; prerequisites for mmm-mode

;;; html-helper-mode
(autoload 'html-helper-mode "html-helper-mode" "Yay HTML" t)
(setq auto-mode-alist (cons '("\\.html$" . html-helper-mode) auto-mode-alist))

;; css-mode
(autoload 'css-mode "css-mode")
(setq auto-mode-alist (cons '("\\.css$" . css-mode) auto-mode-alist))
(setq cssm-indent-function #'cssm-c-style-indenter)

;; javascript-mode
(add-to-list 'auto-mode-alist '("\\.js$" . javascript-mode))
(autoload 'javascript-mode "javascript" nil t)
(setq javascript-indent-level 4)


;;; mmm-mode for web standards

(load-library "mmm-mode")
(require 'mmm-auto)
(setq mmm-global-mode 'maybe)
(setq mmm-submode-decoration-level 3)
;;(set-face-bold-p 'mmm-default-submode-face t)
;;(set-face-background 'mmm-default-submode-face "#333333") ; meaningless
(set-face-background 'mmm-default-submode-face "black")
; On terminal, #RRGGBB rounded off
; to system-defined colors.

(mmm-add-classes
'((embedded-css
:submode css-mode
:front "<style[^>]*>"
:back "</style>")))
(mmm-add-mode-ext-class nil "\\.html?\\'" 'embedded-css)

(mmm-add-classes
'((html-javascript
:submode javascript-mode
:front "<script[^>]*>"
:back "</script>")))
(mmm-add-mode-ext-class nil "\\.html?\\'" 'html-javascript)

【実践CL】14 ファイルとファイルI/O

pareditの練習のため写経しながら。


  • 14.1 ファイルの読み込み
  • 14.2 バイナリデータの読み込み
  • 14.3 まとめ読み
  • 14.4 ファイル出力
  • 14.5 ファイルを閉じる

    • この5節、特になし。

  • 14.6 ファイル名

    • 論理パスネームを無視すれば、パスネームは悪いもんじゃないよ。
    • 論理パスネームには近づくなよ。
    • 名前文字列からパスネームへの対応はANSIでは規程されていないよ。

  • 14.7 パスネームでどうやってファイル名を表現するか
  • 14.8 新しいパスネームの構築
  • 14.9 ディレクトリ名の2つの表現方法

    • この3節、特になし。

  • 14.10 ファイルシステムとのやり取り

    • P系の言語の気安さとCLとの差は、この部分にあるのかもしれない。P系の言語はまずはUnixベッタリとして、ファイルシステムとのやりとり関係を扱いやすいように言語のconstructsが決められているような気がする。

  • 14.11 その他のI/O

    • 特になし。



こつこつ。

paredit

シンクロニシティでg000001さんところで、pareditというものを知った。これすごいな。

ちょっとづつ調べてみよう。

2009年1月12日月曜日

Emacs-Lisp mode を調べる

どんな便利があるのかな。

  • M-? m でモードの記述をみる。(私はヘルプをM-?にバインドしている)
    あれ、

    key binding
    --- -------

    TAB lisp-indent-line
    ESC Prefix Command
    DEL backward-delete-char-untabify

    M-TAB lisp-complete-symbol
    C-M-q indent-pp-sexp
    C-M-x eval-defun

    C-M-q indent-sexp
    (that binding is currently shadowed by another mode)

    しかない。C-xC-eとかは???
  • lisp interaction modeかな、と*scratch*でモード検査。

    key binding
    --- -------

    TAB lisp-indent-line
    C-j eval-print-last-sexp
    ESC Prefix Command
    DEL backward-delete-char-untabify

    M-TAB lisp-complete-symbol
    C-M-q indent-pp-sexp
    C-M-x eval-defun

    C-M-q indent-sexp
    (that binding is currently shadowed by another mode)

    あり、C-jしかふえてない。C-x系は違うとこで定義? 移動系のC-M-fとかもない、、、
  • ソースを調べる。
    lisp-mode.el

    (defvar emacs-lisp-mode-map ()
    "Keymap for Emacs Lisp mode.
    All commands in `lisp-mode-shared-map' are inherited by this map.")

    (if emacs-lisp-mode-map
    ()
    (let ((map (make-sparse-keymap "Emacs-Lisp")))
    (setq emacs-lisp-mode-map (make-sparse-keymap))
    (set-keymap-parent emacs-lisp-mode-map lisp-mode-shared-map)
    (define-key emacs-lisp-mode-map "\e\t" 'lisp-complete-symbol)
    ...

    なので、lisp-mode-shared-mapなのかな。

    (defvar lisp-mode-shared-map
    (let ((map (make-sparse-keymap)))
    (define-key map "\t" 'lisp-indent-line)
    (define-key map "\e\C-q" 'indent-sexp)
    (define-key map "\177" 'backward-delete-char-untabify)
    ;; This gets in the way when viewing a Lisp file in view-mode. As
    ;; long as [backspace] is mapped into DEL via the
    ;; function-key-map, this should remain disabled!!
    ;;;(define-key map [backspace] 'backward-delete-char-untabify)
    map)
    "Keymap for commands shared by all sorts of Lisp modes.")

    ちがう。
  • キーバインディングで調べてみる。するとC-xC-eとかは major mode bindingsではなく、global bindingsだった。ここから調べればよかった。global-bindingsということはtext-modeとかでもつかえるということ? やってみる。C-xC-e、使えた、、、
  • さて、global bindingsでキーにバインドされている機能って、どういう単位で整理されているのか概念としてまとめられているのか?
  • ソースを調べる。C-x C-e (eval-last-sexp)はどこにいる? あり? lisp-mode.elじゃん。実体はここでバインディングはbindings.elですでに実施されている。
  • bindings.elって? loadup.elによって起動時に必ずloadされるようだ。なので、ここで定義されたものは、mode等に関わらず常に有効だ。
  • ということは、Elisp編集用に用意されている機能をきっちりおさえるには、Emacsのソースの中のlisp/emacs-lisp/*.elを読めということだな。なるほど、、、
  • とりあえず、lisp/emacs-lisp/lisp-mode.elとlisp/emacs-lisp/lisp.elを眺める。
  • あ!! 以前欲しいと言ってた編集機能があった!

    ;; After Zmacs:
    (defun kill-backward-up-list (&optional arg)
    "Kill the form containing the current sexp, leaving the sexp itself.
    A prefix argument ARG causes the relevant number of surrounding
    forms to be removed."
    (interactive "*p")
    (let ((current-sexp (thing-at-point 'sexp)))
    (if current-sexp
    (save-excursion
    (backward-up-list arg)
    (kill-sexp)
    (insert current-sexp))
    (error "Not at a sexp"))))

    いや、yankがいまいちか。でも希望がもてる。
  • なるほど、おもしろい。

みなさん、こんな感じでやっているのだろうか???

こつこつ。

ステイタス変更

PAIPをざっとみたというところで、CLを変更。入門者 -> 初心者。

Emacs Lisp プログラミング入門を通読したというところで、Emacsを変更。入門者 -> 初心者。

まだ入門者なやつをなんとか初心者レベルにもっていかねば、、、

微積、代数幾何と確率・統計の勉強をしなきゃ。

【ELp入門】18 結論

この章は2ページしかない。今後のEmacs Lispへの取組み方の提案が書かれている。参考になる。ふと感じたのはInfoの使いこなしをやってみたいな、ということ。あまり日頃の作業の中でInfoを使えていない。Emacs LispリファレンスマニュアルとかもInfoにあるので、もっと日常的に使っていきたい。

やってみて、ElispというかEmacsはとてもおもしろかった。
やっと、Emacsを使いこなしていくスタートポイントにたてた気がする。

さて、付録は今回はやらないことにする。また機会があったら、演習と付録含めて通読したい。
今後は、ソースを読んだりカスタマイズしていく実践と、次の課題図書を読むことの二本立てにする予定だ。

こつこつ。

【ELp入門】17 デバッグ


  • 17.1 debug

    • 私のEmacsではdebug-on-errorがはじめからtになっているようだ。22だから? それともcarbon emacsのメンテナかな?


  • 17.2 debug-on-entry

    • M-x debug-on-entry RET function RET でその関数に入るとデバッガが起動できるんだ。しらなかった。


  • 17.3 debug-on-quit

    • おお。これは無限ループのデバッグに便利。


  • 17.4 ソースレベルのデバッガ edebug

    • おお。edebugは、ソースにそって評価をトレースできるんだ。
    • ACLでもeliで確かできたはずだがまだ使っていない。


あれ? まだ一章あった。
こつこつ。

【ELp入門】16 個人用ファイル .emacs


  • 16.1 サイト全体の初期化ファイル

    • 自分なりにまとめる。

      * elisp: [emacs][elisp]Emacsの起動ファイル
      ダンプ版を作成するときにロードされるファイル。
      site-load.el
      site-init.el

      ディストリビューションのINSTALLにこれらの説明がある。

      起動時の初期化ファイルの読み込み。

      site-start.el -> ~/.emacs -> default.el and 端末タイプファイル

      ディストリビューションのlisp/loaddefs.elにこれらへの助言がある。


  • 16.2 一回だけの作業用の変数の設定

    • edit-optionsってどうやって起動するんだろう?

  • 16.3 ファイル.emacs入門

    • C-cに単一文字を続けるキーバインドは、個人用。Emacs拡張者(モード作成者など)はこれを使ってはいけない。

  • 16.4 TextモードとAuto Fillモード

    • 特になし。

  • 16.5 メールの別名

    • 特になし。

  • 16.6 Indent Tabsモード (タブによる字下げ)

    • 特になし。

  • 16.7 キーバインド例

    • C-xfの誤打鍵。あるある。

  • 16.8 ファイルのロード

    • 特になし。

  • 16.9 オートロード

    • 特になし。

  • 16.10 簡単な拡張:line-to-top-of-window

    • 特になし。

  • 16.11 キーマップ

    • 特になし。


章としては次が最後。こつこつ。

【ELp入門】15 グラフの準備

前章の復習をした。それから15章を開始。
*を並べてグラフを作るのは、C言語の勉強で山のようにやった記憶が。

  • 前説

    • 所感:なんとなくだが、この本のプログラミングスタイルは「中間データとしてリストを用いる」という感じがする。すなわち、私だと、おおもとのデータから最終データ(リストでないもの)をいっきに生成しようと手続きを考えるところもいったん途中でリストを生成してそれを最終データにもっていくということ。こういうのもありといえばあり。基本リストであると決めてしまえば、補助関数の入出力も考えやすいし、再利用も考えやすい。
    • 雑感:「リスト遊び」を勉強したときに、繰返しに関する章では、代入ばっかで気持ち悪いと書いた。それはEmacsの中身のelispコードが代入ばっかりなことを反映していたんだなぁ。
    • (apply 'max '(4 8 5))。'maxなんだな。

  • 15.1 関数 graph-body-print

    • 特になし。

  • 15.2 関数 recursive-graph-body-print

    • 特になし。


こつこつ。

【ELp入門】14 defun 内の単語の数え上げ

ここまでやってきて感じるのは、Emacsというのは本当に副作用ゴリゴリだな、ということ。別にだから嫌だとか、悪いということではない。とにかく事実としてゴリゴリ。Elispというlisp層で書いてはいるが、それはなんというか指圧で体調をコントロールしようとしているような感じであり、体表を押すことが目的ではなく、その結果として体内の気脈と血脈をコントロールするということが目的だが、目的を実現するには体表を押すしかないというイメージ。CLプログラミングの場合は、もっと直にコントロールしようとしているものを触っているというか中に入りこんでいるように感じる。

さて、そろそろ最終局面。


  • 前説

    • 要旨:ヒストグラムを出力する関数をつくりたい。対象は関数に含まれる単語(とシンボル?)の数。

  • 14.1 何を数えるか?

    • 要旨:文字列に含まれる単語を数える。またシンボルも数える。

  • 14.2 単語やシンボルを構成するものは何か?

    • 構文テーブル(Syntax Tables)の話。
    • 構文テーブルは重要な気がする。EmacsリファレンスマニュアルやEmacs Lispリファレンスマニュアルを参照して、要点を自分なりにまとめる。

      • readerは構文テーブルを使わない。構文テーブルはテキスト内をElispで動き回るために使われる。
      • 構文テーブルはバッファローカルである。
      • 典型的には、メジャーモード毎に独自の構文テーブルがあり、モード起動時にそのバッファに構文テーブルをインストールする。
      • 構文テーブル間には継承関係を設定できる。

      • 構文テーブルは、各文字の構文クラスを指定する。
      • 構文クラスの文字への割当ては排他的である。ひとつの文字はひとつの構文クラスにのみ属する。
      • 構文記述子は、「構文クラス、(括弧のクラスの場合に使われる)釣り合う文字、構文フラグ」の3つの組み合わせを指定するニーモニックである。(例: Cモードにおける文字#の構文記述子は23。23は「句読点、釣り合う文字なし、コメント開始の二番目の文字、コメント終了の最初の文字」を表す)
      • 構文テーブルは関数sytanx-tableで取得できる。
      • 構文テーブルの印字は、#^[ ... ]だった。#^って何だろ? ベクター? 調べる。ベクター型は、[ ... ]。#^[ ... ]は文字テーブル型。文字コードでインデックスされる。
      • 構文クラスの一覧は次のとおり。

        • 白文字 (whitespace character)
        • 単語構成文字 (word constituent)
        • シンボル構成文字 (symbol constituent)
        • 句読点文字 (punctuation character)
        • 開き括弧文字 (open parenthesis character)
        • 閉じ括弧文字 (close parenthesis character)
        • 文字列クォート (string quote)
        • エスケープ (escape)
        • 文字クォート (character quote)
        • 対になった区切り (paired delimiter)
        • 式前置子 (expression prefix)
        • 継承 (inherit)
        • 汎用コメント区切り (generic comment delimiter)b
        • 汎用文字列区切り (generic string delimiter)

      • 構文フラグは、複数の文字からなるコメント区切りの指定に使う。
      • 構文テーブルの中で、文字に対して別の構文テーブルを指定することもできる。

      • 構文クラスよりも柔軟な構文定義として、カテゴリがある。カテゴリはカテゴリテーブルで定義される。
      • カテゴリテーブルはバッファローカルである。
      • カテゴリテーブルは、文字テーブルである。
      • カテゴリテーブルの要素は、ブールベクトルである。ブールベクトルの値によってその文字が属するカテゴリを指定する。
      • カテゴリの指定は排他的ではない。
      • クラスは上記のように仕様で語彙が定義されているが、カテゴリは仕様では定義されていない。ユーザが独自に定義して使うのか?

    • おもしろいなぁ。こういう仕組みになっているんだ。ひとつの観点では、Emacsの編集機能はルールベースになっているといえるな。構文テーブルがルールを記述している。そして各バッファでそれが設定されて、関数がルールを解釈してそのバッファのテキストに対して動作する、ということ。
    • さて、戻る。
    • この本では、クラスとカテゴリが上記の定義に比して混乱している。おそらく、Ver.18〜19あたりでは、クラスの別名としてカテゴリを使っているようだ。そしてクラスは排他的ではなくカテゴリ的な性質をもっているようだ。

  • 14.3 関数 count-words-in-defun

    • 特になし。

  • 14.4 ファイル内の複数のdefunsの数え上げ

    • 「問題をこのように文章にすることは、関数定義の基本である。」

  • 14.5 ファイルを探す

    • 特になし。

  • 14.6 lengths-list-fileの詳細

    • ユーザフレンドリならば、対象とするバッファについてナロウイングの復帰に加えてsave-excursionしたほうがよさげ。

  • 14.7 別のファイルのdefunx内の単語の数え上げ
  • 14.8 別のファイルの再帰による単語の数え上げ
  • 14.9 グラフ表示用データの準備

    • この3節はあっさり。


こつこつ。

2009年1月11日日曜日

【実践CL】13 リストを越えて:コンスセルの別用途


  • 前説

    • 要旨:リストは幻想である。コンスセルから成るものをリストとして扱う関数群がある、というだけだ。
    • 要旨:同様に、コンスセルから成るものを違うものとした扱う関数群もある。木、集合、ルックアップテーブルだ。

  • 13.1 木


      ;; リストとして。
      (substitute 10 1 '(1 2 (3 2 1) ((1 1) (2 2))))
      ;; -> (10 2 (3 2 1) ((1 1) (2 2)))

      ;; 木として。
      (subst 10 1 '(1 2 (3 2 1) ((1 1) (2 2))))
      ;; -> (10 2 (3 2 10) ((10 10) (2 2)))

      なるほど。

  • 13.2 集合

    • 特になし。

  • 13.3 ルックアップテーブル:連想リストと属性リスト

    • あれ? '"a"の動作がわからない、、、。考える。

      • "a"であれば、これはまずreaderが文字列オブジェクトを生成する。それをevaluatorが評価する。評価した結果は同じ文字列オブジェクトである。それをprinterがR/W eqivalenceで印字する。それが"a"である。
      • '"a"の場合。分析の記述を簡単にするために、(quote "a")であるとする。これはまずreaderがLispフォームを生成するのだが、それはリストであり、第一要素はシンボルquoteである。第二要素は、文字列オブジェクトである。このリストをevaluatorが評価する。評価にあたり、quoteはスペシャルフォームであり、その引数位置にあるLispオブジェクトを評価せずにそのまま返却する。よって文字列オブジェクトである。それをprinterがR/W eqivalenceで印字する。それが"a"である。

    • ふむ。あたりまえのことだった。
    • getfは常にeqで比較。
    • 本のremfは例が悪い。次の例が簡明。

      CL-USER(32): *plist*
      NIL
      CL-USER(33): (setf (getf *plist* :a) 2)
      2
      CL-USER(34): (setf (getf *plist* :b) 3)
      3
      CL-USER(35): *plist*
      (:B 3 :A 2)
      CL-USER(38): (remf *plist* :a)
      T
      CL-USER(39): *plist*
      (:B 3)
      CL-USER(40):

    • get-propertiesも中途半端な例だな。簡明な例は次のとおり。

      CL-USER(47): *plist*
      (:C 0 :B 3 :A 2)
      CL-USER(48): (get-properties *plist* '(:a :b))
      :B
      3
      (:B 3 :A 2)
      CL-USER(49):


  • 13.4 DESTRUCTURING-BIND

    • 特になし。


こつこつ。

【ELp入門】13 数え上げ:繰り返しと正規表現


  • 前説

    • 繰り返しと正規表現の探索は、Elispでよく使うよ。(多分この組み合わせをよく使うということだと思われる)
    • この章では、領域内の単語数を数える関数を作るよ。

  • 13.1 関数 count-words-region

    • 「どの文字が単語を構成し、どの文字が単語を構成しないかは、バッファのシンタックステーブルで決まる」なるほど。

  • 13.2 再帰による単語の数え上げ

    • 特になし。


こつこつ。

【初SQL】8 グループ化と集約化

そろそろSQL文が長くなってくるので、sql-mysqlモードを使いはじめることにする。
これはEmacs本体の配布に同梱されていて、M-x sql-mysqlで立ち上がる。使い勝手が悪いようなら、他の選択肢を探す。


  • 8.1 グループ化

    • なんかこのあたり、構文と意味がぐちゃぐちゃ。SQLは汚ないな。

  • 8.2 集約関数

    • この本を読んでいくなかで、徐々に徐々に違和感というか居心地の悪さが増していったのだが、その理由がわかった。やはり、スキーマというかサンプルデータベースの構造に関する説明なしに、データ取得用のSQLをどんどん繰り出されても、暗闇に何かをなげたら何かがかえってくるみたいな話になってしまっているからだ。なので、ここらへんで、勝手ながらサンプルデータベースの構造の理解を進めてみる。
    • Webでいろいろ調べてみることにする。米国の金融用語についてはまったく素人なので、間違っている可能性が少からずです。ご注意ください。

      • 付録AのER図を眺める。まあ、ER図はあまり役に立たないものだ。
      • LearningSQLExample.sqlを眺める。ポイントは次のとおり。

        • department(部門)とbranch(支社)とtitle(役職)は独立した概念である。
        • employeeのtitleは列挙型ではなく、varcharである。現況を調べる必要あり。

          • 現況。

            mysql> select title from employee group by title;
            +--------------------+
            | title |
            +--------------------+
            | Head Teller |
            | Loan Manager |
            | Operations Manager |
            | President |
            | Teller |
            | Treasurer |
            | Vice President |
            +--------------------+

          • President, Vice Presidentはわかる。
          • Teller: 出納係;出納主任;窓口係;計算係; と辞書にはある。これじゃ言葉の意味として多様すぎないか?
          • Head Teller: Tellerのリーダのことだろう。
          • Treasurer: 会計[出納]係, 経理[財務]部長; と辞書にはある。しかし、会計係と財務部長じゃずいぶん違わないか???
          • Loan Manager: 融資の責任者、だろう。
          • Operations Manager: このOperationは投機取引のことなのか、業務運用のことなのか、、、
          • 役職の階層構造をみる。

            mysql> select it.title, sup.title from employee it inner join employee sup on it.superior_emp_id = sup.emp_id;
            +--------------------+--------------------+
            | title | title |
            +--------------------+--------------------+
            | Vice President | President |
            | Treasurer | President |
            | Operations Manager | Treasurer |
            | Loan Manager | Operations Manager |
            | Head Teller | Operations Manager |
            | Teller | Head Teller |
            | Teller | Head Teller |
            | Teller | Head Teller |
            | Head Teller | Operations Manager |
            | Teller | Head Teller |
            | Teller | Head Teller |
            | Head Teller | Operations Manager |
            | Teller | Head Teller |
            | Teller | Head Teller |
            | Head Teller | Operations Manager |
            | Teller | Head Teller |
            | Teller | Head Teller |
            +--------------------+--------------------+
            17 rows in set (0.00 sec)

            役職と部門の関係もみる。

            mysql> select it.title, dep.name from employee it inner join department dep on it.dept_id = dep.dept_id;
            +--------------------+----------------+
            | title | name |
            +--------------------+----------------+
            | Operations Manager | Operations |
            | Head Teller | Operations |
            | Teller | Operations |
            | Teller | Operations |
            | Teller | Operations |
            | Head Teller | Operations |
            | Teller | Operations |
            | Teller | Operations |
            | Head Teller | Operations |
            | Teller | Operations |
            | Teller | Operations |
            | Head Teller | Operations |
            | Teller | Operations |
            | Teller | Operations |
            | Loan Manager | Loans |
            | President | Administration |
            | Vice President | Administration |
            | Treasurer | Administration |
            +--------------------+----------------+
            18 rows in set (0.00 sec)

            ああ、わかった。

            President (社長)
            ->Vice President (副社長)
            -> Treasurer (財務担当役員)
            -> Operations Manager (本部長)
            -> Loan Manager (融資部長)
            -> Head Teller (出納係統括)
            -> Teller (出納係)


          ということだ。
        • product_typeのnameは列挙型ではなく、varcharである。

          mysql> select * from product_type;
          +-----------------+-------------------------------+
          | product_type_cd | name |
          +-----------------+-------------------------------+
          | ACCOUNT | Customer Accounts |
          | LOAN | Individual and Business Loans |
          | INSURANCE | Insurance Offerings |
          +-----------------+-------------------------------+
          3 rows in set (0.00 sec)

          これはまんまだな。
        • productのproduct_cdもvarchar。調べる。

          mysql> select * from product;
          +------------+-------------------------+-----------------+--------------+--------------+
          | product_cd | name | product_type_cd | date_offered | date_retired |
          +------------+-------------------------+-----------------+--------------+--------------+
          | CHK | checking account | ACCOUNT | 2000-01-01 | NULL |
          | SAV | savings account | ACCOUNT | 2000-01-01 | NULL |
          | MM | money market account | ACCOUNT | 2000-01-01 | NULL |
          | CD | certificate of deposit | ACCOUNT | 2000-01-01 | NULL |
          | MRT | home mortgage | LOAN | 2000-01-01 | NULL |
          | AUT | auto loan | LOAN | 2000-01-01 | NULL |
          | BUS | business line of credit | LOAN | 2000-01-01 | NULL |
          | SBL | small business loan | LOAN | 2000-01-01 | NULL |
          +------------+-------------------------+-----------------+--------------+--------------+
          8 rows in set (0.00 sec)

          checking account (account): 当座預金 (手形や小切手の支払いを決済するためのもの)。transactional accountの北米名。
          savings account (account): 普通預金 (自由に預入・払戻ができる預金)
          money market acccout (account): 金融市場預金 (当座預金の一種。ただし、比較的ハイリスクハイリターン。銀行は金融市場への投資運用に利用する)
          cerificate of deposit (account):譲渡性預金証書 (定期預金のひとつ。預金者がこれを金融市場で事由に譲渡できる)
          home mortgage (loan): 住宅ローン
          auto loan (loan): 自動車ローン
          business line of credit (loan): 法人クレジットカード?
          small business loan (loan): 中小企業融資
        • officerって何?

          • どうやら、business(法人)における役員のこと。

        • accountのpending_balanceって何?

          • available balance: 利用可能残高? (払戻し等、利用できる金額)
          • pending balance: 銀行が処理待ちで保持しているものも勘案した残高? (小切手などを即時処理せずに、銀行が信用調査するなど?)

        • transactionのtxn_type_cdの'DBT'と'CDT'は何?

          • 簿記の、debit(借方)、credit(貸方)のことかな?

        • transactionのfunds_avail_dateは何?

          • そのtransaction(取引)の結果として利用可能と処理された資金が実際に利用可能となる日時かな。



    • PCLのときも書いたが、なぜ、オブジェクトやエンティティの説明のときに銀行や預金を持ち出すのか? 以上の用語の説明は、グーグル、Yahoo!、Wikipediaや金融機関サイトなどをいろいろ検索しまくって、それらかの情報をつぎはぎにしてやっと構成したものだ。用語体系として、または、概念体系として、英語のサイトですらちゃんと説明できているところが簡単には見付からないということだ。例えば、図書館の貸出システムとかの方が、例としてはマシなんじゃないか?
    • さて、進める。
    • 集約関数は、groupに対して作用する。

  • 8.3 グループの生成

    • この節、翻訳がいまいち。
    • roll-up:巻き上げ式
    • ドリルダウン:データの集計レベルを1つずつ掘り下げて集計項目をさらに詳細にする操作。
    • うーん。5.1では、with rollupの結果とwith cubeの結果が同じだ。。。

  • 8.4 グループのフィルタ条件

    • 集約関数など、グループ化された後に生成される値をフィルタ条件に用いるにはhaving節を使う。


こつこつ。

【実践CL】12 リスト処理:やつらがLISPと呼ぶ理由


  • 12.1 「リストなんてない」

    • そうだ、実践CLではrplaca,rplacdはつかわずにsetfでいくんだった。
    • 箱を使った説明は常にきらいだ。。。

  • 12.2 関数プログラミングとリスト

    • 要旨:リストは不変なオブジェクトでない。しかし、equalによって等価が判定されるとすれば、リストを入出力として関数プログラミングができる。

  • 12.3 「破壊的」な操作

    • 要旨:破壊的操作には二種類ある。副作用が目的なものと、リソースのリサイクルが目的のもの。
    • あれ、ここではnreverseのnはnon-consingのnになっている。どこかで、nuclearのnと読んだような。まあ、いいや。

  • 12.4 リサイクルな関数と構造共有の組み合わせ
    • 特になし。

  • 12.5 リスト操作関数

    • 特になし。

  • 12.6 マッピング

    • 特になし。


こつこつ。

【ELp入門】12 正規表現の探索

Elispに少し重点を置く。理由はいくつか。

  • CLでプログラミングするにしても、CLだけではすまない。WebアプリならHTMLも書くし、Ajaxやるなら、CSSもJavaScriptもやる。JSONも書く。DBにつなぐならSQLも書く。それらを設置するのはUNIXの上なので、Shell scriptも書いたりする。IMAPするならMIMEを扱う。そしてそういうもののフロントエンドとなっているのがEmacsなので、Emacsをどれだけ理解していてコントロールできるかが、どれだけ快適に開発作業ができるかの鍵になってくる。
  • S式の編集機能についてeliはどうやらslimeに遅れをとっているようだ。なので、slime的な機能をeliから使えるようにしたい。これはCLのコードの編集速度に大きく影響すると思う。

なので、「CLを勉強しよう」ということではなくて「CLでアプリをつくろう」となると、途端に「もうちょいEmacsを手なづけねば」と思えてしまう。

さて12章。


  • 前説

    • Emacsでは正規表現が多用されている。

  • 12.1 sentence-endのための正規表現

    • 「括弧と縦棒のまえには2つのバックスラッシュ\\が必要である。」いや、そうなのだが、それはElispでは正規表現を文字列で表現しているためそうなるということを説明しないと読者は混乱する。
    • sentence-endはソースとしては、emacs-22.3/lisp/textmode/にある。

  • 12.2 関数re-search-forward

    • 翻訳がすこし不器用。

  • 12.3 forward-sentence

    • これもソースとしては、emacs-22.3/lisp/textmode/にある。

  • 12.4 forward-paragraph : 関数の宝庫

    • forward-paragraph、長い。。。S-expを指定した深さでshrink/expandできる機能があるといいなぁ。
    • Emacsの文字は整数である。すなわちCL的ではなくC的であるということ。
    • 文字リテラルは?aなどである。#\aであるCLとは違う。

  • 12.5 専用タグファイルの作成方法

    • 開発時のTAGの運用もそのうち整理しないと。


こつこつ。

【RW】10日やってみて

1日30分〜1時間、10日程度やってみた。ロゼッタワールドのこと。
気づきは初日からたくさんあったが、気が重くて書けなかった。
気力を振り絞り、書いてみる。

まず、自分の発音というかSpeakingのひどさに衝撃を受けた。生まれてこのかた練習したことがないからできなくてあたりまえといえばあたりまえなのだが、なぜかそうとうに衝撃を受けた。

理由を考えてみた。
自分が例えば "This is a pen." という文を英語で発しているつもりだったものが、全然似ても似つかぬというかめちゃくちゃなものを発していたからなのかもしれない。お手本を聞いたとおりに真似をして発音しても全然認識されない(ロゼッタワールドは英語音声認識エンジンをつんでおり、そのエンジンが認識できるかどうかで発音の善し悪しを評価しているようだ)。そこで、もういちどお手本を聞いてみると、自分が軽んじていたこまかな発音が為されて初めて "This is a pen." というメッセージを表現(エンコード)できるのだということに気付く。その差異が大きくて衝撃を受けた。

発音について言うと、私が訓練をそうとう詰まなければいけないのは重要度の高い順にならべると次のものと気付いた。


  • ピッチ。音の高低が意味を運ぶ。文全体と、単語単体がある。
  • 子音。子音のバリエーションが日本語よりもかなり多い。それぞれをちゃんと発音できないとほぼエンコードエラーで、相手が理解できるわけもない。
  • 母音の連続。例えば、fourだったりgirlだったり。母音が連続するという口腔の動作に慣れていない。
  • 子音の連続。例えば、twelveのtwとかlveなど。子音が連続するという口腔の動作にも慣れていない。


また、たまに "There is ..."などについて、音としてはThereの最後のrとisが結合して、「デァリズ」などになるのが英語、というのを以前聞いたことがあった。確かにそうなのだが、それは、There isのthereとisがそれぞれ単体としてちゃんと発音できた上での話だ。それがちゃんとできないのに、つなげて発音したところで、うにょむにょ唸っているだけにすぎない。

正しく発音をしようとすると、音を聞きとらなければならない。神経を集中して、口腔の形状と舌と歯と唇の連携をダイナミックにコントロールして、聞いたものを実現しようとする。もう子供じゃないので、なかなかそれらが言うことを聞かない。もうこの口のまわりというか、鼻から下というかを切って捨てたくなるほど思い通りにならない。しどろもどろで練習しているうちに、少し発音できるようになってくる。そうすると、今まで聞こえていなかった発音が聞きとれてくる。つまり、発音できる、ということと、聞き取れる、ということは相補的になっており、片方がレベルアップするともう片方もレベルアップする。逆に言うと、発音できないと聞き取れない、聞き取れないと発音できない、というジレンマがそこにはある。そのジレンマを乗り越えて、ホフク前進の右手と左手のような感じで発音と聞き取りを向上させてジリジリ進んでいくしかない。

副次的な効果として、10日間の訓練だけでも、ヒアリング能力がずいぶん上がった。英語の映画をみて、今まで聞き取れていたつもりのものでも、ずいぶん聞き取れかたが違うのだ。うまく言葉で表現できないが、聞き取れ「かた」が違うのだ。
また、リーディングも変わりつつある。読むときは、頭の中で音が聞こえる状態のときと、音が聞こえない状態のときがある。これは日本語でもそうだと思う。聞こえる状態のときに、頭の中に響く音声が向上しているのだ。たぶんこのことによって、頭の中で音としての英語と文字としての英語が交錯しつつ反復的にスキルが上がっていくのだと思う。

こつこつ。

2009年1月10日土曜日

【ELp入門】11 ループと再帰


  • 11.1 while

    • そうなのだ。whileは常に副作用のために評価されるのだ。

  • 11.2 再帰

    • お、C-uC-xC-eで、副作用出力も*scratch*に出せるんだ。


ページ数は16とそこそこだが、さすがにループと再帰はそこそこやってきているので、さくっと。

こつこつ。

【初SQL】7 データの生成、変換、操作

前回は、MySQLが5.1になってもSQL標準にあまり準拠していなくて、へこんだ。
気をとりなおして、進む。


  • 前説

    • おお、文字列、数値、時間データの生成、変換、操作などについては、SQL言語には含まれていないんだ。。。

  • 7.1 文字列データの操作

    • 処理が進んじゃって、別途Warningがでる、というのはいやーな感じ。
    • お、quoteだ。
    • DBでは文字列のインデックスは1始まりなんだ。

  • 7.2 数値データの操作

    • 特になし。

  • 7.3 時間データの操作

    • 特になし。

  • 7.4 変換関数

    • ベンダー固有関数ではなくcastを使おう。



この章の内容をどう捉えるか。
まず、RDBMSが提供するSQL+αで情報の表示をカスタマイズするのには使える。また、その道具立てで、どう情報をRDBにいれるかというときにも使える。そうか、データの入出力関係、ということか。CLでいうと、基本的なデータ型のリテラルとそれらを引数とする関数、ということか。

こつこつ。

【ELp入門】10 テキストの取り出し方


  • kill-ringとかkill-ring-yankなどを*scratch*で見ると興味深い。
  • emacsでは*scratch*などをつかっていつでもinspectできるということが、知識としてはわかっていても活用はできていない現状。

3ページしかないので、あっさり。

cl-benchをとりあえずやってみる

とりあえず、aclとsbclについてCL-benchをかけてみた。
いろいろ調整をしないと、正確なベンチにならないかな、と思います。その点ご了承ください。
まず、acl。

;; -*- lisp -*- International Allegro CL Enterprise Edition 8.1 [64-bit Linux (x86-64)] (Jul 28, 2007 7:38)
;;
;; Implementation *features*:
;; (:ALLEGRO-CL-ENTERPRISE :IPV6 :ACL-SOCKET :HIPER-SOCKET :PROFILER :MULTIPROCESSING :FLAVORS :LITTLE-ENDIAN :GSGC :COMPILER :USE-STRUCTS-IN-COMPILER :CLOS :DYNLOAD :DLFCN :UNIX :LINUX :AMD64 :LINUX86-64 :X86-64 :ENCAPSULATING-EFS :RELATIVE-PACKAGE-NAMES :MODULE-VERSIONS :IEEE :IEEE-FLOATING-POINT :CONFORMING-IEEE :ICS :COMMON-LISP :ANSI-CL :DRAFT-ANSI-CL-2 :X3J13 :ALLEGRO :EXCL :FRANZ-INC :ALLEGRO-VERSION>= :ALLEGRO-VERSION= :NEW-ENVIRONMENTS :SYMBOL-VALUE-VECTOR :PROCESS7 :DYNLOAD-ACL-LIBRARY :ALLEGRO-V8.1 :64BIT :TLSVALUES :TLSBNP :SSL-SUPPORT)
;;
;; Function real user sys consed
;; ----------------------------------------------------------------
;; COMPILER 1.13 1.08 0.00 0
;; LOAD-FASL 0.26 0.26 0.00 0
;; SUM-PERMUTATIONS 2.13 2.02 0.00 0
;; WALK-LIST/SEQ 0.04 0.03 0.00 0
;; WALK-LIST/MESS 0.04 0.04 0.00 0
;; BOYER 5.79 5.73 0.00 0
;; BROWSE 0.29 0.28 0.00 0
;; DDERIV 0.34 0.34 0.00 0
;; DERIV 0.30 0.31 0.00 0
;; DESTRUCTIVE 0.20 0.20 0.00 0
;; DIV2-TEST-1 0.37 0.37 0.00 0
;; DIV2-TEST-2 0.44 0.42 0.00 0
;; FFT 0.04 0.05 0.00 0
;; FRPOLY/FIXNUM 0.37 0.37 0.00 0
;; FRPOLY/BIGNUM 0.37 0.37 0.00 0
;; FRPOLY/FLOAT 0.77 0.77 0.00 0
;; PUZZLE 0.49 0.49 0.00 0
;; TAK 0.19 0.19 0.00 0
;; CTAK 0.38 0.38 0.00 0
;; TRTAK 0.19 0.19 0.00 0
;; TAKL 0.35 0.35 0.00 0
;; STAK 2.11 2.10 0.00 0
;; FPRINT/UGLY 0.82 0.75 0.00 0
;; FPRINT/PRETTY 1.92 1.90 0.00 0
;; TRAVERSE 1.00 0.99 0.00 0
;; TRIANGLE 0.66 0.65 0.00 0
;; RICHARDS 1.30 1.30 0.00 0
;; FACTORIAL 0.28 0.27 0.00 0
;; FIB 0.08 0.08 0.00 0
;; FIB-RATIO 0.02 0.02 0.00 0
;; ACKERMANN 4.98 4.93 0.00 0
;; MANDELBROT/COMPLEX 0.75 0.73 0.00 0
;; MANDELBROT/DFLOAT 0.01 0.02 0.00 0
;; MRG32K3A 0.56 0.57 0.00 0
;; CRC40 1.04 1.02 0.00 0
;; BIGNUM/ELEM-100-1000 0.14 0.14 0.00 0
;; BIGNUM/ELEM-1000-100 0.24 0.23 0.00 0
;; BIGNUM/ELEM-10000-1 0.18 0.19 0.00 0
;; BIGNUM/PARI-100-10 0.01 0.02 0.00 0
;; BIGNUM/PARI-200-5 0.06 0.07 0.00 0
;; PI-DECIMAL/SMALL 0.73 0.72 0.00 0
;; PI-DECIMAL/BIG 0.32 0.33 0.00 0
;; PI-ATAN 1.08 1.09 0.00 0
;; PI-RATIOS 1.40 1.38 0.00 0
;; HASH-STRINGS 0.45 0.45 0.00 0
;; HASH-INTEGERS 0.70 0.69 0.00 0
;; SLURP-LINES 0.00 0.00 0.00 0
;; BOEHM-GC 2.64 2.58 0.00 0
;; DEFLATE-FILE 0.58 0.58 0.00 0
;; 1D-ARRAYS 0.08 0.06 0.00 0
;; 2D-ARRAYS 1.11 1.10 0.00 0
;; 3D-ARRAYS 2.93 2.89 0.00 0
;; BITVECTORS 0.54 0.54 0.00 0
;; BENCH-STRINGS 0.92 0.91 0.00 0
;; fill-strings/adjustable 9.92 9.83 0.00 0
;; SEARCH-SEQUENCE 1.12 1.10 0.00 0
;; CLOS/defclass 0.17 0.17 0.00 0
;; CLOS/defmethod 0.24 0.24 0.00 0
;; CLOS/instantiate 1.31 1.29 0.00 0
;; CLOS/simple-instantiate 0.39 0.39 0.00 0
;; CLOS/methodcalls 1.91 1.89 0.00 0
;; CLOS/method+after 0.95 0.94 0.00 0
;; CLOS/complex-methods 0.29 0.29 0.00 0
;; EQL-SPECIALIZED-FIB 0.31 0.31 0.00 0

つづいて、sbcl。

;; -*- lisp -*- SBCL 1.0.24.8
;;
;; Implementation *features*:
;; (:SB-THREAD :ANSI-CL :COMMON-LISP :SBCL :SB-DOC :SB-TEST :SB-LDB
;; :SB-PACKAGE-LOCKS :SB-UNICODE :SB-EVAL :SB-SOURCE-LOCATIONS
;; :IEEE-FLOATING-POINT :X86-64 :UNIX :ELF :LINUX :GENCGC
;; :STACK-GROWS-DOWNWARD-NOT-UPWARD :C-STACK-IS-CONTROL-STACK :LINKAGE-TABLE
;; :COMPARE-AND-SWAP-VOPS :UNWIND-TO-FRAME-AND-CALL-VOP
;; :RAW-INSTANCE-INIT-VOPS :STACK-ALLOCATABLE-CLOSURES :ALIEN-CALLBACKS
;; :CYCLE-COUNTER :OS-PROVIDES-DLOPEN :OS-PROVIDES-PUTWC
;; :OS-PROVIDES-SUSECONDS-T)
;;
;; Function real user sys consed
;; ----------------------------------------------------------------
;; COMPILER 2.27 2.24 0.00 0
;; LOAD-FASL 0.35 0.34 0.00 0
;; SUM-PERMUTATIONS 1.94 1.93 0.00 0
;; WALK-LIST/SEQ 0.03 0.03 0.00 0
;; WALK-LIST/MESS 0.04 0.04 0.00 0
;; BOYER 4.10 4.05 0.00 0
;; BROWSE 0.28 0.27 0.00 0
;; DDERIV 0.32 0.32 0.00 0
;; DERIV 0.38 0.38 0.00 0
;; DESTRUCTIVE 0.23 0.23 0.00 0
;; DIV2-TEST-1 0.52 0.51 0.00 0
;; DIV2-TEST-2 0.70 0.69 0.00 0
;; FFT 0.06 0.06 0.00 0
;; FRPOLY/FIXNUM 0.33 0.33 0.00 0
;; FRPOLY/BIGNUM 0.27 0.27 0.00 0
;; FRPOLY/FLOAT 0.45 0.45 0.00 0
;; PUZZLE 0.36 0.35 0.00 0
;; TAK 0.33 0.32 0.00 0
;; CTAK 0.38 0.38 0.00 0
;; TRTAK 0.33 0.33 0.00 0
;; TAKL 0.45 0.45 0.00 0
;; STAK 0.74 0.73 0.00 0
;; FPRINT/UGLY 1.43 1.41 0.00 0
;; FPRINT/PRETTY 2.60 2.58 0.00 0
;; TRAVERSE 0.93 0.93 0.00 0
;; TRIANGLE 0.89 0.87 0.00 0
;; RICHARDS 0.71 0.71 0.00 0
;; FACTORIAL 0.18 0.19 0.00 0
;; FIB 0.28 0.28 0.00 0
;; FIB-RATIO 0.04 0.05 0.00 0
;; ACKERMANN 3.57 3.55 0.00 0
;; MANDELBROT/COMPLEX 0.48 0.47 0.00 0
;; MANDELBROT/DFLOAT 0.01 0.01 0.00 0
;; MRG32K3A 0.76 0.75 0.00 0
;; CRC40 0.36 0.36 0.00 0
;; BIGNUM/ELEM-100-1000 0.11 0.12 0.00 0
;; BIGNUM/ELEM-1000-100 0.13 0.13 0.00 0
;; BIGNUM/ELEM-10000-1 0.06 0.06 0.00 0
;; BIGNUM/PARI-100-10 0.01 0.01 0.00 0
;; BIGNUM/PARI-200-5 0.05 0.04 0.00 0
;; PI-DECIMAL/SMALL 0.65 0.66 0.00 0
;; PI-DECIMAL/BIG 0.29 0.27 0.00 0
;; PI-ATAN 0.62 0.62 0.00 0
;; PI-RATIOS 1.25 1.23 0.00 0
;; HASH-STRINGS 0.34 0.35 0.00 0
;; HASH-INTEGERS 0.68 0.67 0.00 0
;; SLURP-LINES 0.003 0.00 0.00 0
;; BOEHM-GC 1.66 1.63 0.00 0
;; DEFLATE-FILE 0.33 0.34 0.00 0
;; 1D-ARRAYS 0.04 0.04 0.00 0
;; 2D-ARRAYS 0.75 0.75 0.00 0
;; 3D-ARRAYS 2.18 2.17 0.00 0
;; BITVECTORS 0.53 0.51 0.00 0
;; BENCH-STRINGS 0.71 0.71 0.00 0
;; fill-strings/adjustable 9.12 9.04 0.00 0
;; STRING-CONCAT 33.66 33.50 0.00 0
;; SEARCH-SEQUENCE 0.41 0.41 0.00 0
;; CLOS/defclass 1.51 1.46 0.00 0
;; CLOS/defmethod 6.03 6.00 0.00 0
;; CLOS/instantiate 7.99 7.95 0.00 0
;; CLOS/simple-instantiate 0.28 0.28 0.00 0
;; CLOS/methodcalls 0.92 0.92 0.00 0
;; CLOS/method+after 3.56 3.54 0.00 0
;; CLOS/complex-methods 2.43 2.41 0.00 0
;; EQL-SPECIALIZED-FIB 0.27 0.27 0.00 0

【実践CL】11 コレクション


  • 前説

    • ANSIにコレクションという用語はあるのかな、Seaquencesというイメージがあるけど。調べる。HyperSpecにはなさそうだ。CLの用語としてではなく、プログラミング言語にまたがった一般的な概念として、ということなのだろう。

  • 11.1 ベクタ

    • elispではベクタはアトムだったが、CLでは?

      CL-USER(2): (vector 1)
      #(1)
      CL-USER(3): (atom (vector 1))
      T
      CL-USER(5): (atom (make-array 5 :fill-pointer 0))
      T
      CL-USER(8): (atom (make-array 5 :fill-pointer 0 :adjustable t))
      T
      CL-USER(9):

    • アトムだ!! adjustableなものもatomなのはちょっと驚いた。しかしsymbolも中身は書き換え可能だがatomだ。atomという概念は、中身の書き換え云々についてではなく、その表象というか表現というかなんというかについてのことなんだろう。

  • 11.2 特殊ベクタ

    • 特殊よりも特定とか特定化の方が訳としては好み。

  • 11.4 シーケンス反復関数

    • 特になし。

  • 11.5 さまざまな高階関数

    • 特になし。

  • 11.6 シーケンス全体の操作

    • 特になし。

  • 11.7 ソートとマージ

    • sortもstable-sotrも破壊的関数。

  • 11.8 部分シーケンス操作

    • 特になし。

  • 11.9 シーケンス述語

    • 特になし。

  • 11.10 シーケンスマッピング関数

    • ありmapcarは?と思い、HyperSpecを見ると、Sequencesのchapterにはmapとmap-intoしかない。調べるとConsesにあった。そうか、mapcarとかはconsesが対象だからね。
    • reduceの言葉のイメージが曖昧で、違和感がある。関数としての機能はわかるんだけど、なんでこれをreduceと呼ぶの? ということ。辞書を調べる。

      • reduce the speed. これは減ずる、という意味。なんか違う。
      • a beautiful building reduce to ashes. これはAをBにむりやり変える、ということ。ちょっと近いのかな。
      • reduce grapes to wine. これは分解する変形するということ。
      • これらを見てわかるとおりreduceにはより矮小な状態や要素的な状態に変えるというニュアンスがある。なので数学だと分数の訳文とか通分を指したりする。

    • うーん、やっぱりすっきりしない。

  • 11.11 ハッシュテーブル

    • 特になし。

  • 11.12 ハッシュテーブル上の反復

    • 特になし。


こつこつ。

2009年1月8日木曜日

【ELp入門】9 リストの実装方法


  • 要点:LISPのリストはポインタ対を用いている。
  • 要点:シンボルに様々な情報を記録することができる。

4ページしかないので。
こつこつ。

JSON

CLでアプリを書くとしても、外部とのデータ入出力は常にS-expで、とは常にはいかない。代替的な手段として、Shibuya.lispのTTでは、JSONの採用が提案されていた。JSONを調べていくにあたっての情報源をまとめておく。調べる前の予見としては、JSONまたはYAMLがいいのではないかと思っている。あくまでS式がつかえない場合ですが。


こつこつ。

【初SQL】6 集合


  • 6.1 集合理論:入門

    • ベン図で集合のunionなどを紹介。

  • 6.2 集合理論:実践

    • ああ、なるほど。異なるエンティティどうしでも、内部構造が同じなら集合演算できるんだ。
    • 何か、新鮮。こんなSQL書いたことなかった。

      mysql> select 1 num, 'abc' str
      -> union
      -> select 9 num, 'xyz' str;
      +-----+-----+
      | num | str |
      +-----+-----+
      | 1 | abc |
      | 9 | xyz |
      +-----+-----+
      2 rows in set (0.00 sec)


  • 6.3 集合演算子

    • union all
    • union
    • intersect (なんとMySQL5.1でもintersectに対応していない。どうなってるの???)
    • intersect all (MySQL5.1 非対応)
    • except (MySQL5.1 非対応)
    • except all (MySQL5.1 非対応)
    • いや、MySQLまずいんじゃないか、これじゃ。Postgreはちゃんと対応している。しかしACLがMySQLよりみたいだからしょうがなし。

  • 6.4 集合演算のルール

    • ルールの紹介。


こつこつ。

【実践CL】10 数、文字、そして文字列


  • 10.1 数

    • 数について、CLは充実しているよ。

  • 10.2 数値リテラル

    • REPLにおける数値リテラルと数値オブジェクトとcanonical textual syntaxをちゃんと理解しとけよ。
    • 私の経験でいうと、baseとradixについて覚えるのがちょっと面倒。

  • 10.3 基本的な数学

    • 四則演算と、丸めを紹介。

  • 10.4 数値比較

    • 関数=は数として等価であるかを判断するよ。

  • 10.5 高度な数学

    • logとかsinとかいろいろな関数がCLにあるよ。

  • 10.6 文字

    • CLでは文字と数は違うよ。(Cとは違うということ)
    • 処理系内部で文字をどういうコーディングで扱うかはCLでは規程されていないよ。

  • 10.7 文字比較

    • 数値比較とは別に文字比較の関数があるよ。

  • 10.8 文字列

    • 文字列は、一次元の配列。要素は文字。

  • 10.9 文字列比較

    • 文字比較とは別に文字列比較の関数があるよ。


こつこつ。

【ELp入門】8 テキストのカットと保存


  • 前説

    • バッファからテキストをkillするとkill ringというリストに格納される。yankするとkill ringからテキスト要素が返される。
    • 本章では、kill ringとzap-to-char関数について説明する。

  • 8.1 zap-to-char

    • 第22版での関数の実装

      (defun zap-to-char (arg char)
      "Kill up to and including ARG'th occurrence of CHAR.
      Case is ignored if `case-fold-search' is non-nil in the current buffer.
      Goes backward if ARG is negative; error if CHAR not found."
      (interactive "p\ncZap to char: ")
      (if (char-table-p translation-table-for-input)
      (setq char (or (aref translation-table-for-input char) char)))
      (kill-region (point) (progn
      (search-forward (char-to-string char) nil nil arg)
      ; (goto-char (if (> arg 0) (1- (point)) (1+ (point))))
      (point))))

    • 関数の本体は(kill-region point-a point-b)。point-aからpoint-bまでの領域をkillする。
    • search-forwardは、pointを移動するという副作用を目的とした関数である。

  • 8.2 kill-region

    • 第22版での実装は多少長くなっているようだ。

      (defun kill-region (beg end &optional yank-handler)
      "Kill (\"cut\") text between point and mark.
      This deletes the text from the buffer and saves it in the kill ring.
      The command \\[yank] can retrieve it from there.
      \(If you want to kill and then yank immediately, use \\[kill-ring-save].)

      If you want to append the killed region to the last killed text,
      use \\[append-next-kill] before \\[kill-region].

      If the buffer is read-only, Emacs will beep and refrain from deleting
      the text, but put the text in the kill ring anyway. This means that
      you can use the killing commands to copy text from a read-only buffer.

      This is the primitive for programs to kill text (as opposed to deleting it).
      Supply two arguments, character positions indicating the stretch of text
      to be killed.
      Any command that calls this function is a \"kill command\".
      If the previous command was also a kill command,
      the text killed this time appends to the text killed last time
      to make one entry in the kill ring.

      In Lisp code, optional third arg YANK-HANDLER, if non-nil,
      specifies the yank-handler text property to be set on the killed
      text. See `insert-for-yank'."
      ;; Pass point first, then mark, because the order matters
      ;; when calling kill-append.
      (interactive (list (point) (mark)))
      (unless (and beg end)
      (error "The mark is not set now, so there is no region"))
      (condition-case nil
      (let ((string (filter-buffer-substring beg end t)))
      (when string ;STRING is nil if BEG = END
      ;; Add that string to the kill ring, one way or another.
      (if (eq last-command 'kill-region)
      (kill-append string (< end beg) yank-handler)
      (kill-new string nil yank-handler)))
      (when (or string (eq last-command 'kill-region))
      (setq this-command 'kill-region))
      nil)
      ((buffer-read-only text-read-only)
      ;; The code above failed because the buffer, or some of the characters
      ;; in the region, are read-only.
      ;; We should beep, in case the user just isn't aware of this.
      ;; However, there's no harm in putting
      ;; the region's text in the kill ring, anyway.
      (copy-region-as-kill beg end)
      ;; Set this-command now, so it will be set even if we get an error.
      (setq this-command 'kill-region)
      ;; This should barf, if appropriate, and give us the correct error.
      (if kill-read-only-ok
      (progn (message "Read only text copied to kill ring") nil)
      ;; Signal an error if the buffer is read-only.
      (barf-if-buffer-read-only)
      ;; If the buffer isn't read-only, the text is.
      (signal 'text-read-only (list (current-buffer)))))))

    • kill-regionのある意味本体は、filter-buffer-stringとkill-newに移ったようだ。

      (defun filter-buffer-substring (beg end &optional delete noprops)
      "Return the buffer substring between BEG and END, after filtering.
      The buffer substring is passed through each of the filter
      functions in `buffer-substring-filters', and the value from the
      last filter function is returned. If `buffer-substring-filters'
      is nil, the buffer substring is returned unaltered.

      If DELETE is non-nil, the text between BEG and END is deleted
      from the buffer.

      If NOPROPS is non-nil, final string returned does not include
      text properties, while the string passed to the filters still
      includes text properties from the buffer text.

      Point is temporarily set to BEG before calling
      `buffer-substring-filters', in case the functions need to know
      where the text came from.

      This function should be used instead of `buffer-substring',
      `buffer-substring-no-properties', or `delete-and-extract-region'
      when you want to allow filtering to take place. For example,
      major or minor modes can use `buffer-substring-filters' to
      extract characters that are special to a buffer, and should not
      be copied into other buffers."
      (cond
      ((or delete buffer-substring-filters)
      (save-excursion
      (goto-char beg)
      (let ((string (if delete (delete-and-extract-region beg end)
      (buffer-substring beg end))))
      (dolist (filter buffer-substring-filters)
      (setq string (funcall filter string)))
      (if noprops
      (set-text-properties 0 (length string) nil string))
      string)))
      (noprops
      (buffer-substring-no-properties beg end))
      (t
      (buffer-substring beg end))))


      (defun kill-new (string &optional replace yank-handler)
      "Make STRING the latest kill in the kill ring.
      Set `kill-ring-yank-pointer' to point to it.
      If `interprogram-cut-function' is non-nil, apply it to STRING.
      Optional second argument REPLACE non-nil means that STRING will replace
      the front of the kill ring, rather than being added to the list.

      Optional third arguments YANK-HANDLER controls how the STRING is later
      inserted into a buffer; see `insert-for-yank' for details.
      When a yank handler is specified, STRING must be non-empty (the yank
      handler, if non-nil, is stored as a `yank-handler' text property on STRING).

      When the yank handler has a non-nil PARAM element, the original STRING
      argument is not used by `insert-for-yank'. However, since Lisp code
      may access and use elements from the kill ring directly, the STRING
      argument should still be a \"useful\" string for such uses."
      (if (> (length string) 0)
      (if yank-handler
      (put-text-property 0 (length string)
      'yank-handler yank-handler string))
      (if yank-handler
      (signal 'args-out-of-range
      (list string "yank-handler specified for empty string"))))
      (if (fboundp 'menu-bar-update-yank-menu)
      (menu-bar-update-yank-menu string (and replace (car kill-ring))))
      (if (and replace kill-ring)
      (setcar kill-ring string)
      (push string kill-ring)
      (if (> (length kill-ring) kill-ring-max)
      (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil)))
      (setq kill-ring-yank-pointer kill-ring)
      (if interprogram-cut-function
      (funcall interprogram-cut-function string (not replace))))

    • そして、C関数として、delete-and-extract-regionを使うようだ。(delete-regionではない)

  • 8.3 delete-region : Cへの回り道

    • さはさりなんで、delete-regionをみてみる。
    • editfns.cに含まれている。
    • そうか。EmacsというのはElispインタプリタの上に書かれているというのがちょっとはばかられるほど、Cで書かれている部分がありそうだ。

  • 8.4 defvarによる変数の初期化

    • defvarの紹介。
    • elispは動的スコープしかないので、あっさり。

  • 8.5 copy-region-as-kill

    • kill-apped, kill-newのことは、上記のとおり、kill-regionにも含まれている。

      (defun copy-region-as-kill (beg end)
      "Save the region as if killed, but don't kill it.
      In Transient Mark mode, deactivate the mark.
      If `interprogram-cut-function' is non-nil, also save the text for a window
      system cut and paste."
      (interactive "r")
      (if (eq last-command 'kill-region)
      (kill-append (filter-buffer-substring beg end) (< end beg))
      (kill-new (filter-buffer-substring beg end)))
      (if transient-mark-mode
      (setq deactivate-mark t))
      nil)

    • そしてkill-ringに関する処理は、kill-newに移っている。


こつこつ。