Before LISPs Just Part of the Past #3 ~ Irritating packages ~

251 views

Published on

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
251
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
2
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Before LISPs Just Part of the Past #3 ~ Irritating packages ~

  1. 1. BeforeLISPsJust Part of the Past〜 #3 irritating Packages 〜
  2. 2. PackageとSymbol● PackageはSymbolの集合● 関数の集合だとか変数の集合という考え方はしない。ひたすらSymbolの集合。● Symbolはいろいろな物を持っていて、関数として使われた場合は関数を返し、グローバル変数として使われた場合はグローバル変数の値を返す– (list 0 1 2)と(funcall (symbol-function list) 0 1 2))はだいたい同じ
  3. 3. SymbolFOO packageIOTAFLATTENGROUP-HEADED…> (iota 3) => (0 1 2)> iota => 72symbol-function(lambda (n)(loop for i from 0 upto (1- n)collect i))symbol-value72symbol-package#<PACKAGE “FOO”>symbol-name“IOTA”symbol-plist()
  4. 4. SymbolBAR packageALPHABETA...IOTA…> (iota 3) => NIL> iota => “i”symbol-function(lambda (str)(and (stringp str)(string= “i” str)))symbol-value“i”symbol-package#<PACKAGE “BAR”>symbol-name“IOTA”symbol-plist()
  5. 5. Current PackageBAR packageALPHABETA…IOTA...FOO packageIOTAFLATTENGROUP-HEADED…カレントパッケージがFOOの場合> (iota 3) => (0 1 2)カレントパッケージがBARの場合> (iota 3) => NILカレントパッケージは*PACKAGE*の値で制御カレントパッケージの切り替えはIN-PACKAGEで行うのが無難例) (in-package :chat-with-tree)
  6. 6. DEFPACKAGE● パッケージを定義する● 他のパッケージに所属しているシンボルで使いたいシンボルがあったらそのパッケージをUSEするか、シンボルを直接指定してIMPORTする。● (defpackage :chat-with-tree(:use :cl :chiku.util))● これで、カレントパッケージがCHAT-WITH-TREEの場合にはCHIKU.UTILパッケージの外部シンボルがすべて使える● (defpackage :chat-with-tree(:use :cl)(:import-from :chiku.util :aif :it))– これはCHIKU.UTILパッケージから2つのシンボル、AIFとITだけ使う場合
  7. 7. 今日の主題はPackage入門ではありません
  8. 8. 参考書● パッケージの説明はPractical Common Lispの21章が素晴らしい– 邦訳版:実践Common Lisp● ただし、Practical Common Lispはシンボルの説明があんまりわかりやすくないというか、まとまっていない● シンボルの説明はANSI Common Lispの第8章がよくまとまっている– 邦訳版:ANSI Common Lisp
  9. 9. ズボラなDEFPACKAGE(defpackage :chiku.register(:use :cl :chiku.util :sqlite :cl-fad:split-sequence :sb-ext))どのパッケージからどんなシンボルを使ってるのかがさっぱりわからない→ 読む人にやさしくない
  10. 10. 律儀なDEFPACKAGE● 書くのが面倒● 以下の2箇所で意思表示しなくちゃいけない– DEFPACKAGE– 実際の使用(defpackage :chiku.register(:import-from :common-lisp:defpackage :in-package :defparameter :merge-pathnames :defun :cadr:position :subseq:car :list :string= :ignorable :declare :quote:stringp :if :&rest :destructuring-bind :&body :defmacro :defgeneric:defclass :defmethod :call-next-method :append :t :make-instance:length :- :make-list :zerop :remove-if :gethash :push :dolist :equal:function :make-hash-table :let :lambda :mapcar :nreverse :reduce:maphash :rename-file :delete-file :apply :mapc :namestring)(:import-from :chiku.util:str<-textfile :concat-str :once-only :str-case :_ :papply :itoa :drop)(:import-from :sqlite:execute-single :disconnect :execute-to-list :execute-non-query :connect)(:import-from :split-sequence :split-sequence)(:import-from :cl-fad :pathname-as-directory :copy-file)(:import-from :sb-ext :*posix-argv* :run-program))
  11. 11. 問題点● 2箇所以上で意思表示するのはかなりまずい– 修正が難しいから、そして面倒だから● ロジックを記述している瞬間はどのシンボルを使ってるのか理解しているはずだから、実際の使用が優先されるべき– どのシンボルを使っているのか履き違えている場合は、ロジックを正しく記述できない● シンボルはオブジェクトで、パッケージもオブジェクト、つまりLISPで扱える。 →ズボラver.から律儀ver.を生成できる
  12. 12. ズボラver.から律儀ver.を作る● シンボルは自分の出自を知っているので、実装はすごく簡単● ソースコードから式を読み、シンボルだけ取り出して各シンボルの所属パッケージを調べる– READ– FLATTEN, REMOVE-IF-NOT, REMOVE-DUPLICATE– SYMBOL-PACKAGE● 手書きの時は、インターンされずかつ書きやすいKeyword Symbolが手軽だが、自動生成なら文字列が便利– SYMBOL-NAME, PACKAGE-NAME– Keyword Symbolの方がかっこいいという感性の人は、KEYWORDパッケージへINTERNすればOK
  13. 13. ちょっとした問題● 新しく起動したREPLで単にファイルをLOADして律儀ver.の生成、とやってもうまくいかない● つまり、よそから持って来たライブラリのDEFPACKAGEがズボラver.で書かれていても、単にLOADして律儀ver.の出力、とやってもうまく行かない。● READはシンボルをカレントパッケージにインターンしようとする– カレントパッケージを変更した上で出力すれば問題ない– (load “sample.lisp”)(let ((*package* (find-package :chiku.register)))(recompose-defpackage :chiku.register “sample.lisp”))
  14. 14. ズボラのススメ● ソースコードは静的なものなので、この結果を貼りこむのは本質的に手動– LISPオブジェクトじゃない、LISPの外という意味– 公開するソースコードのDEFPACKAGEフォームをこのやり方で生成して貼りこむ、という使い方自体はできる● むしろ、ズボラver.以外書かない方針を提唱したい– 律儀ver.は簡単な手順で生成できる● LISPに聞いてわかることをわざわざ書かない、書かせない● ソースコード(読む用の)もテキストじゃなくLISPオブジェクトとして配布できたらいいと思う。– 危ないけど
  15. 15. その他の細々したこと● あるパッケージをIN-PACKAGEするファイルが複数ある場合● IN-PACKAGEが書かれていないファイルがある場合● 1つのファイルでIN-PACKAGEが複数回行われている場合● LOADが好ましくない副作用を持つ場合● ズボラと律儀の間にあるDEFPACKAGE● EXPORT節などの取り扱い● 神は細部に宿ります

×