定義済みストリームは次のものであり、 echo-streamとconcatenated-streamは利用できない。
open [関数]
path &key (direction :input)
(if-exists :new-version)
(if-does-not-exist 'default)
(permission #o644)
(buffer-size 512)
with-open-file (svar path &rest open-options) &rest forms [マクロ]
make-string-input-stream string [関数]
make-string-output-stream &optional size [関数]
get-output-stream-string string-stream [関数]
make-broadcast-stream &rest output-streams [関数]
リーダのグローバル変数は:
Readerのデフォルトマクロ文字は:
( リスト読み込み
" 文字列読み込み
' 引用符表現読み込み
# マクロ変換
; コメント
` back-quote
, list-time eval
@ 追加
% C言語表記の数式読み込み
エスケープ文字:
単一文字エスケープ
多重文字エスケープ
エスケープされていないsymbolが読まれると、 全ての構成される文字はデフォルトで大文字に変換され、 そして大文字のsymbolは内部に蓄えられる。 例えば、'abcと'ABCは同じsymbolとみなされる。 エスケープは、それらを区別するのに必要である。 'ABC, 'ABCと'abcは同一であるが、 'abcと'abcは違うsymbolである。 デフォルトとして、大文字のsymbolを入力したときでさえ、 そのsymbolを表示するときは EusLispのプリンタが内部の大文字表現から小文字に変換する。 この変換は、プリンタによって実行されている。 この変換は、 :UPCASEを*print-case*に設定することにより、禁止される。
10.は整数の10として読まれ、実数の10.0ではない。 ':'がパッケージマーカーとして予約されているので、 'のようにsymbolを構成するものとして使うとき、エスケープ化しなければ ならない。 この制限は、文字':'の構文により強制されないが、 アルファベット順やletterの意味を決定する属性により強制される。 その文字の属性は、リーダから堅く結ばれる(hardwired)。 したがって、copy-readtableで新しいreadtableを作ったり、 set-syntax-from-charで文字のための構文的意味を組み直したりすることにより、 ある文字の構文を変更可能であるが、 その属性はどのようにしても変更することができない。 その一方で、数字はいつも数字であり、アルファベットはアルファベットで、 数値を表現するために'#$%@'の様な文字を使用することはできない。
%は、EusLispで拡張read-macro文字となっている。 挿入記述により書かれた数式の前に%を付けることにより、 その数式はlisp用の式に変換される。 具体例を上げると、 %(1 + 2 * 3 / 4.0)は (+ 1 (/ (* 2 3) 4.0))に変換され、結果は2.5となる。 Cの様な関数呼出や行列参照も、lisp形式に変換される。 従って、%(sin(x) + a[1])は (+ (sin x) (aref a 1))として評価される。 1つ以上の引数を持つ関数や2次元以上の行列は、 func(a b c ...)やary[1 2 3 ...]のように記述し、 func(a,b,c)やary[1][2][3]のように書かない。 相対表現や割り当てもまた、正しく扱われる。 それで、%(a b)は( a b)に変換され、 %(a[0] = b[0] * c[0])は (setf (aref a 0) (* (aref b 0) (aref c 0)))として得られる。 単純な最適化は、重複した関数呼出や行列参照をなくすことである。 %(sin(x) + cos(x) / sin(x))は (let* ((temp (sin x))) (+ temp (/ (cos x) temp)))のように変換される。
マクロ変換は#
文字が前に付いている。
数値(integer)引数は、#
とマクロ変換文字の間に与えられる。
これは、どの数字(0 .. 9)もマクロ変換文字として定義できないことを意味する。
リーダの標準のマクロ変換文字は次の通り:
いくつかのリーダ関数は、eof-error-p, eof-valueや recursive-pのパラメータを持っている。 最初の2つのパラメータは、リーダがend-of-fileに出会ったときの動作を制御する。 eof-error-pのデフォルトは、Tである。これは、eof時のエラーの原因となる。 eofの発生を知りたかったり、snatch controlにシステムエラーを渡したくないなら、 eof-error-pにNILを指定すること。 それで、読み込みの最中にeofが現れたとき、リーダはエラーループに入る代りに eof-valueを返す。 eof-valueのデフォルトは、NILである。 そのため、実際にNILが読まれたのかeofが現れたのか判別できない。 それらを判別するためには、ストリームに決して現れない値を与えること。 そのような特殊データオブジェクトを作るには、consかgensymを 使用すること。
recursive-pは、read-macro関数にしばしば使用される。 それは、リーダを再帰的に呼び出す。 recursive-pのnon-NIL値は、読み込み処理がどこかで始まっていて、 #n=や#n#によってラベル付けされる書式の読み込みのために 内部テーブルを初期化 すべきでないことをリーダに告げている。
read &optional stream (eof-error-p t) (eof-value nil) recursive-p [関数]
read-delimited-list delim-char &optional stream recursive-p [関数]
read-line &optional stream (eof-error-p t) (eof-value nil) [関数]
read-char &optional stream (eof-error-p t) (eof-value nil) [関数]
read-from-string string &optional (eof-error-p t) (eof-value nil) [関数]
unread-char char &optional stream [関数]
peek-char &optional stream (eof-error-p t) (eof-value nil) [関数]
y-or-n-p &optional format-string &rest args [関数]
yes-or-no-p &optional stream [関数]
以下に示すreadtableの操作関数の中で、readtableのデフォルト値は グローバル変数*readtable*の値である。
copy-readtable &optional from-readtable to-readtable [関数]
set-syntax-from-char from-char to-char &optional to-readtable from-readtable [関数]
set-macro-character char func &optional non-teminating-p readtable [関数]
get-macro-character char &optional readtable [関数]
set-dispatch-macro-character dispchar char func &optional readtable [関数]
get-dispatch-macro-character dispchar char &optional readtable [関数]
以下に示すものは、プリンタの行動を制御するための特殊変数である。
再帰的参照を持つオブジェクトを印刷するためには、 再度読み戻しが必要なため、 *print-circle*と *print-structure*を両方Tに設定し、オブジェクトを印刷すること。 ユーザーが定義するほとんどのオブジェクトは再読み込み可能な書式に 表示されるが、 クラス, オブジェクトモジュールやパッケージをその方法でdumpすることはできない。 なぜなら、クラスとオブジェクトモジュールは再配置不可能な実行コードを含み、 パッケージの再読みだしは、構成されるsymbol中に影響があるからである。
print obj &optional stream [関数]
prin1 obj &optional stream [関数]
princ obj &optional stream [関数]
finish-output &optional stream [関数]
princ-to-string x &optional (l 16) [関数]
prin1-to-string x &optional (l 16) [関数]
format stream format-string &rest args [関数]
(format t "~s ~s ~a ~a ~10,3f~%" "abc" 'a#b "abc" 'a#b 1.2) ---> "abc" |A#B| abc a#b 1.200
pprint obj &optional (stream *standard-output*) (tab 0) (platen 75) [関数]
print-functions file &rest fns [関数]
write-byte integer stream [関数]
write-word integer stream [関数]
write-long integer stream [関数]
spaces n &optional stream [関数]
pf func &optional stream *standard-output*) [マクロ]
pp-method class selector &optional (stream *standard-output*) [関数]
tprint obj tab &optional (indent 0) (platen 79) (cpos 0) [関数]
EusLispは、4種類のIPC機能( 共有メモリ, メッセージキュー, FIFOやソケット)を備えている。 一般的に、この命令により性能が悪くなる。 もし、マルチスレッド機能を使用するならば、 12節に記述されている同期関数も通信手段として 用いることができる。 これらの機能のうちで使用できるものは、Unixのバージョンや構成に依存する。
64バイト長のファイルを2つのEusLispで共有するプログラム例を下に示す。
;; 64バイトのファイルを作る (with-open-file (f "afile" :direction :output) (princ (make-string 64) f)) ;; 配置する (setq shared-string1 (map-file "afile" :direction :io)) ;; ;; 他のプロセスの中で (setq shared-string2 (map-file "afile" :direction :io))
その後、shared-string1に書かれたデータは すぐにshared-string2へ現れる。 foreign stringへの書き込みは、 replaceかsetfにarefを組み合せることにより可能である。
map-file filename &key (direction :input) length (offset 0) (share t) (address 0) [関数]
FIFOに対するストリームを作るために、 最初にunix:mknod関数で、 2番目の引数をmode=#o10000に設定した上で FIFOノードを作り、ノーマルファイルとしてオープンする。 メッセージキューとFIFOは、機械の上でローカルに作られ、 機械内での通信チャンネルとしてのみ与えられる。
メッセージキューとFIFOは、自分のプロセスが終了した後でさえも システムから削除されない。 削除するためには、unix:msgctlかipcrmコマンドが必要である。
make-msgq-input-stream key &optional (buffer-size 128) [関数]
make-msgq-output-stream key &optional (buffer-size 128) [関数]
接続されたストリームは、両方向通信チャンネルとして供給されるが、 接続確定処理は、入力・出力で別々である。 片方がサーバーとして参照され、もう一方がクライアントとして参照される。 サーバーとなった端(service access point)は、最初に確定される。 これは、make-socket-port関数により作成される。 この関数は、socket-portのインスタンスを返す。 ソケットポートのオブジェクトは、make-server-socket-streamによって 1つまたは複数のクライアントからの接続を受けるために使用される。 make-server-socket-streamへの呼び出しは、クライアントからの 接続要求が実際に起こるまで実行待ち状態となる。 クライアントは、ソケットアドレスを指定することによって make-client-socket-streamでソケットストリーム を複数作ることができる。
;;; an example of IPC through a socket stream: ;;; server side (setq saddr (make-socket-address :domain af_inet :host "etlic2" :port 2000)) (setq sport (make-socket-port saddr)) (setq sstream (make-server-socket-stream sport)) ;;; ;;; client side (setq caddr (make-socket-address :domain af_inet :host "etlic2" :port 2000)) (setq cstream (make-client-socket-stream caddr))
データベースや移動ロボットの環境シミュレータのようなアプリケーション では、1つのサーバーと複数のクライアント間の multiple connection service(多重接続サービス)が要求される。 この型のサーバーは、open-server関数によりプログラム することができる。 カレントホスト名と与えられたポート番号から open-serverは、接続要求にしたがってソケットポート(service access point) を作る。 このポートは非同期なので、 open-serverは遮断されず、直ちに返信する。 その後、接続要求はそれぞれEuslispのメインループを中断し、 ソケットストリーム が非同期に作成される。 このソケットストリームも非同期モードで働く。 open-serverの2番目の引き数にある非同期入力処理は、 新しいデータがこのストリームに現れたときはいつでも呼び出される。 30以上の接続が可能であるため、同時に多くのクライアントがサーバーの データにアクセスすることができる。
;; server side (defun server-func (s) (case (read s) ... ;do appropriate jobs according to inputs (open-server 3000 #'server-func) ... do other jobs in parallel ;; client-1 through client-N (setq s (connect-server "etlmmd" 3000)) (format s "..." ...) (finish-output s) ;issue a command to the server (read s) ;receive response
確実な通信チャンネルとして供給される接続指向 ストリームと対照的に 非接続 ソケットは、不確実な通信チャンネルである。 メッセージがなくなったり、重複したり、故障したりする可能性がある。 しかしながら、非接続 ソケットは、それぞれの接続にファイルディスクリプタを 割り当てる必要が無いし、 また、データやバッファのオーバーフローの読み込みをしないレシーバーでさえ 送信処理を中断することができないという利点がある。
非接続ソケットを作るためには、以下の命令を使用する。 メッセージはunix:sendtoとunix:recvfromによって変換される。
;;; receiver side (setq saddr (make-socket-address :domain af_inet :host "etlic2" :port 2001)) (setq sock (make-dgram-socket saddr)) (unix:recvfrom sock) ;;; ;;; client side (setq caddr (make-socket-address :domain af_inet :host "etlic2" :port 2001)) (setq sock (unix:socket (send caddr :domain) 2 0)) (unix:sendto sock caddr "this is a message") ;;; ;;; how to use echo service which is registered in /etc/services. (setq caddr (make-socket-address :domain af_inet :host "etlic2" :port (car (unix:getservbyname "echo")))) (setq echosock (unix:socket (send caddr :domain) 2 0)) (unix:sendto echosock caddr "this is a message") (unix:recvfrom echosock) --> "this is a messge"
make-socket-address &key domain pathname host port proto service [関数]
make-socket-port sockaddr [関数]
make-server-socket-stream sockport &optional (size 100) [関数]
make-client-socket-stream sockaddr &optional (timeout 5) (size 512) [関数]
open-server port remote-func [関数]
select-stream stream-list timeout [関数]
def-async stream function [マクロ]
パス名は、OSに依存しないようにファイル名を解析あるいは構成する方法として 与えられるものである。 典型的なパス名は、次のような構成で成り立っていると仮定されている。 host:device/directory1/.../directory-n/name.type.version。 Euslispは、UNIXの上で動作している限り、ホスト・デバイス・バージョンを無視する。 pathname関数は、文字列をディレクトリ要素・名前・型に分解し、パス名 オブジェクトを返す。そのパス名は、#Pを先頭につけた文字列として表示される。
make-pathname &key host device directory name type version defaults [関数]
merge-pathnames name &optional (defaults *default-pathname-defaults*) [関数]
directory &optional (path ".") [関数]
This document was generated using the LaTeX2HTML translator on Sat Feb 5 14:36:44 JST 2022 from EusLisp version 138fb6ee Merge pull request #482 from k-okada/apply_dfsg_patch