Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2007-12-27

PLEACの空き地

| 18:39 | PLEACの空き地 - わだばLisperになる を含むブックマーク はてなブックマーク - PLEACの空き地 - わだばLisperになる

どう書く.orgはマルチリンガルなクックブックも狙っているそうなのですが、そういえば、そのものズバリのマルチリンガルクックブックの実現を目指しているサイトが確かあった筈と思い出し、検索してみたところ、Perlのクックブックのレシピを色んな言語で実装しようというPLEAC - Programming Language Examples Alike Cookbookというサイトがみつかりました。

自分の記憶でも確かこのサイトです。

Common Lispのエントリもあって、現在は30%強の達成度で、SchemeはGuileでのエントリとなりますが50%弱の達成度です。

割と面白そうなので、空き地をみつけて挑戦してみることにしました。

とはいえ、できそうなところだけですが…。

16章の「プロセス管理とプロセス間通信」ってところが0%なので、なんとなくこれにあたってみることにします。

レシピ16.1 プログラムの出力を収集する

;; $output = `program args`;   # collect output into one multiline string
;; ----------------------------------------------------------------

(let ( (output (kmrcl:command-output "ls -l")))
  output)
;; command-outputはformatのように書ける。
(kmrcl:command-output "~A ~A" "/bin/ls" "-l")

;; @output = `program args`;   # collect output into array, one line per element
;; ----------------------------------------------------------------
(let ( (output (ppcre:split "\\n" (kmrcl:command-output "ls -l"))))
  output)

シェルコマンドの出力を取り込むということですが、KMRCLパッケージのcommand-outputが使えるので、それで。

配列への格納は、CL-PPCREのSPLITを使って改行文字で分解して一つのリストに纏めるということにしてみました。これには色んな方法があるとは思います。

レシピ16.2 別のプログラムを起動する

;; $status = system("vi $myfile");
(let ( (myfile "bar.txt"))
  (let ( (status (kmrcl:run-shell-command "vi ~A" myfile)))
    status))

viを起動するってのは、色々面倒なことが多いかもしれませんが、ls等であればまず問題なくいけると思います。

レシピ16.4 別のプログラムと読み書きする

;; 文字限定:出力を読む
;; ----------------------------------------------------------------
(let ( (cmd "ls -l"))
  (with-input-from-string (readme (kmrcl:command-output "ls -l"))
    (series:iterate ( (line (series:scan-stream readme #'read-line)))
    #|
     行を処理
    ...|# ))

;; 文字限定:文字列をcmdに渡す
;; ----------------------------------------------------------------
(let ( (cmd "tr 'a-z' 'A-z'")
      (tempfile (format nil "/tmp/~A" (gensym "tempfile-"))))
  (with-open-file (out tempfile :direction :output)
    #| 
    (print "foo" out)
    (print "bar" out)
    (print "こんにちは" out))
    ...|#
  (kmrcl:awhen (probe-file tempfile)
    (prog1 (kmrcl:command-output "cat ~A|~A" tempfile cmd)
           (delete-file kmrcl:it))))

別のプログラムというのは、シェルで実行するコマンドなわけですが、文字列限定ってことで書いてみました。

どうも難しい。どういう書法が定石なんでしょうか。バイナリの読み書きもどうしたもんかと。

レシピ16.11 名前付きパイプを使ってプロセスをファイルのように見せる

(defun pipe-reader (pipe &optional (output *standard-output*))
  (with-open-file (fifo pipe)
    (series:iterate ( (line (series:scan-file fifo #'read-line)))
      (write-line line output))))

(defun pipe-writer (mesg pipe)
  (with-open-file (fifo pipe :direction :output :if-exists :append)
    (write-line mesg fifo)))

(let ( (named-pipe "/tmp/named.pipe"))
  (kmrcl:run-shell-command "mkfifo ~A" named-pipe)
  ;; 別スレッドで待ち受け
  (princ "Got: ")
  (portable-threads:spawn-thread 'pipe (lambda ()
                                         (pipe-reader named-pipe #.*standard-output*)))
  ;; FIFO経由で書き込み
  (pipe-writer "Smoke this." named-pipe)
  (force-output))

パイプへ書き込む関数と読み出す関数を定義して、別スレッドで実行することにしてみました。

変なところで改行されたりされなかったりしますが、表示のさせ方を考えれば多分大丈夫なのではないかと。

まとめ

という感じで、できそうなところに挑戦してみました。

いやいや、そういう書き方は変だよ、とか、こう書くとスマートだよね、とか、これ実装してみたよ、等々ありましたら、グループで専用の掲示板を作ってみましたので、良かったら、お気軽に書き込んでみて下さい!(→cadr group) もちろんここへのトラックバックも大歓迎ですし、直接PLEACに投稿してみるというのも良いと思います。自分は、数が溜ったら投稿してみようかなと思っています。(PLEACのメーリングリストに参加して、コードをレビューしてもらって掲載という流れのようです。)

ゲスト



トラックバック - http://cadr.g.hatena.ne.jp/g000001/20071227