erlterm: Erlang項とCommon Lispオブジェクトの相互変換
Erlang -- External Term Formatを参考にして、Erlangの項(のバイナリ表現)とCommon Lispのオブジェクトを相互変換するライブラリを作成。
・erlterm-0.0.1
ポートを用いた外部接続での利用を想定。
細かい作り込みや最適化はまだまだだけど、一応一通りの変換は行える。※ 未対応箇所に関しては、erltermのREADMEを参照
使用例
軽く使用例を。
使える関数はerlterm:decode-termとerlterm:encode-termの二つ。
;;;; Common Lisp側# Erlangから送られてきたリストを反転して送り返す ;;;; ファイル名: reverse.lisp ;;;; ;;;; 処理系: sbcl-1.0.40 ;;;; ※ 標準入出力に対してバイナリ操作が行えるのは(おそらく)SBCLの拡張 (require :asdf) (require :erlterm) (handler-case (loop (let ((list (erlterm:decode-term *standard-input* :packet 2))) ; 受信 (erlterm:encode-term (reverse list) *standard-output* :packet 2) ; 返信 (force-output *out*))) (end-of-file () 'done))
%%%% Erlang側# ポート関連の操作をラップ %%%% ファイル名: port_rpc.erl -module(port_rpc). -export([open/1,close/1,call/2]). %% 接続 open(Command) -> open_port({spawn, Command}, [{packet, 2},binary]). %% クローズ close(Port) -> Port ! {self(), close}. %% リクエスト送信 call(Port, Message) -> Port ! {self(), {command, term_to_binary(Message)}}, % バイナリに変換して送信 receive {Port, {data, Data}} -> binary_to_term(Data) % レスポンスをバイナリから復元 end.
%%%% Erlangシェル %% コンパイル & ロード > c(port_rpc). => {ok,port_rpc} %% lispプロセスを開く > Port = port_rpc:open("sbcl --script reverse.lisp"). => #Port<0.1723> %% 送信するデータ > List = [first, {self(), {1, "middle", 3.2}, make_ref()}, last]. => [first,{<0.33.0>,{1,"middle",3.2},#Ref<0.0.0.66>},last] %% リクエスト > port_rpc:call(Port, List). => [last,{<0.33.0>,{1,"middle",3.2},#Ref<0.0.0.66>},first] %% クローズ > port_rpc:close(Port). => {<0.33.0>,close}
もう一つ。
Erlang項のデコード例。
%%%% Erlang %% 上の例のリストをバイナリに変換して、ファイルに書き出す > file:write_file("list.bin", term_to_binary([first, {self(), {1, "middle", 3.2}, make_ref()}, last])). %% 無名関数をバイナリに変換して、ファイルに書き出す > file:write_file("fun.bin", term_to_binary(fun (X) -> X*X*X end)).
;;;; Common Lisp (require :erlterm) ;; Erlangのリストのバイナリデータを読み込む (with-open-file (in "list.bin" :element-type '(unsigned-byte 8)) (erlterm:decode-term in)) --> (:FIRST #(#S(ERLTERM::PID :NODE :NONODE@NOHOST :ID 33 :SERIAL 0 :CREATION 0) #(1 "middle" 3.2d0) #S(ERLTERM::NEW-REFERENCE :NODE :NONODE@NOHOST :CREATION 0 :ID #(94 0 0))) :LAST) ;; Erlang無名関数のバイナリデータを読み込む (with-open-file (in "fun.bin" :element-type '(unsigned-byte 8)) (erlterm:decode-term in)) --> #S(ERLTERM::NEW-FUN :SIZE 722 :ARITY 1 :UNIQ 75230672122209326657346363854110770891 :INDEX 2 :MODULE :ERL_EVAL :OLD-INDEX 6 :OLD-UNIQ 13229925 :PID #S(ERLTERM::PID :NODE :NONODE@NOHOST :ID 49 :SERIAL 0 :CREATION 0) :FREE-VARS #(NIL #(:VALUE #S(ERLTERM::NEW-FUN :SIZE 96 :ARITY 2 :UNIQ 9719462018325469980632351212009778472 :INDEX 7 :MODULE :SHELL :OLD-INDEX 7 :OLD-UNIQ 115410035 :PID #S(ERLTERM::PID :NODE :NONODE@NOHOST :ID 49 :SERIAL 0 :CREATION 0) :FREE-VARS #(#S(ERLTERM::PID :NODE :NONODE@NOHOST :ID 27 :SERIAL 0 :CREATION 0)))) #(:EVAL #S(ERLTERM::NEW-FUN :SIZE 417 :ARITY 3 :UNIQ 9719462018325469980632351212009778472 :INDEX 14 :MODULE :SHELL :OLD-INDEX 24 :OLD-UNIQ 81953817 :PID #S(ERLTERM::PID :NODE :NONODE@NOHOST :ID 49 :SERIAL 0 :CREATION 0) :FREE-VARS #(#(:VALUE #S(ERLTERM::NEW-FUN :SIZE 96 :ARITY 2 :UNIQ 9719462018325469980632351212009778472 :INDEX 7 :MODULE :SHELL :OLD-INDEX 7 :OLD-UNIQ 115410035 :PID #S(ERLTERM::PID :NODE :NONODE@NOHOST :ID 49 :SERIAL 0 :CREATION 0) :FREE-VARS #(#S(ERLTERM::PID :NODE :NONODE@NOHOST :ID 27 :SERIAL 0 :CREATION 0)))) 8207 #S(ERLTERM::NEW-FUN :SIZE 208 :ARITY 1 :UNIQ 9719462018325469980632351212009778472 :INDEX 15 :MODULE :SHELL :OLD-INDEX 14 :OLD-UNIQ 68813366 :PID #S(ERLTERM::PID :NODE :NONODE@NOHOST :ID 49 :SERIAL 0 :CREATION 0) :FREE-VARS #(#(:VALUE #S(ERLTERM::NEW-FUN :SIZE 96 :ARITY 2 :UNIQ 9719462018325469980632351212009778472 :INDEX 7 :MODULE :SHELL :OLD-INDEX 7 :OLD-UNIQ 115410035 :PID #S(ERLTERM::PID :NODE :NONODE@NOHOST :ID 49 :SERIAL 0 :CREATION 0) :FREE-VARS #(#S(ERLTERM::PID :NODE :NONODE@NOHOST :ID 27 :SERIAL 0 :CREATION 0)))) 8207 #S(ERLTERM::PID :NODE :NONODE@NOHOST :ID 27 :SERIAL 0 :CREATION 0))) #S(ERLTERM::PID :NODE :NONODE@NOHOST :ID 27 :SERIAL 0 :CREATION 0)))) ;; (X) -> X * X * X (#(:CLAUSE 1 (#(:VAR 1 :|x|)) NIL (#(:OP 1 :* #(:OP 1 :* #(:VAR 1 :|x|) #(:VAR 1 :|x|)) #(:VAR 1 :|x|)))))))