2009年2月27日金曜日

newLISPの特徴、軽くまとめ

去年から少しずつ弄っていたnewLISPですが、 人様に見せるようなものは出来なかったのでとりあえず使ってみて分かったことだけでも書いておきます。 これからnewLISPを使ってみようかと思っている人の参考にでもなれば、と。

リンク

マニュアル・リファレンス

  • newLisp (newLISPのメモリ管理方法(ORO)についての翻訳)

サンプル・ライブラリ

日本語の情報源

今のところほとんど見つかりませんが...

特徴

  • 開発はC言語 (GUI部分はJava)
  • ライセンスはGPLv3
  • 主にスクリプト言語として利用する
    newLISP is a Lisp-like, general-purpose scripting language.
  • newLISP-GS: JavaベースのGUIライブラリが付属
    付属のエディタはこのGUI-Serverを呼び出している
  • プラットフォームは Windows *BSD Linux Solaris OSX …とにかくたくさん。
    Linux/Tru64 UNIX/*BSD/Mac OSX/SunOS/Solaris/AIX/Win32(MinGW)/OS2
  • 64ビット対応
  • IPv4とIPv6の切り替えが可能 (開発中)
  • 実行ファイルは200kバイトくらいとかなり小さい
  • 単体の実行ファイルが作れる - newlisp.exeとソースを結合する方法
  • HTTP/CGIサーバ専用モード - HTTP-only server mode

ライブラリ

とりあえず確認したライブラリ ※当方使ったことないです。OpenGLは面白いかも。
C-Libraries, Modules
  • MySQL SQLite GTK-server OpenGL freeGLUT GNU-GMP OpenSSL zlib FTP Postscript POP3 SMTP

言語の特徴

  • newLISP と CL/Scheme の比較を参照 (訳してみたもの)
  • ラムダ式はリストと同様に扱える。
  • 動的スコープ / 動的束縛
    この辺はEmacsLispに似ている。
  • ドット対が存在しない。
  • 関数の引数は足りなくても余分にあってもよい。足りない引数はnilに束縛される。
    これはnewLISP特有のものではなく、Interlispの特徴でもある。
    Lispの進化 957行目参照
    ((lambda (x y z) (list x y z)) 0 1 2 3 4 5) => (0 1 2)
  • Implicit indexing (暗黙のインデックス機能)
    リストや文字列などのシーケンスにアクセスする機能。
    ("newLISP" 0) => "n"
  • 関数の引数は基本的に値のコピーが渡される
    バージョン10 から一部破壊的な関数に置き換わっている
    マクロも引数を評価しない点では参照渡しとほぼ同等。
  • コンテキスト
    LISP-1(関数と変数の名前空間が共有)であるnewLISPに複数の名前空間を提供する機能
    CommonLispのパッケージの概念と似ているかもしれない
    これを使えばマクロ定義においての外部からの変数束縛を避けることが出来る。
    ハッシュの代用にもなる。
  • 共有ライブラリの呼び出しが可能
    (import "printf" "libc.so.6")
    (printf "%s World" "HELLO")  ;=> "HELLO World"
  • Perl互換正規表現 (PCRE: Perl-Compatible Regular Expressions)
  • Unicode対応 (UTF-8)
  • XMLサポート
  • ネットワークAPI多数 (TCP, UDP)
  • Prolog風パターンマッチ関数が利用できる
    (match '(* 2 ? 4) '(0 1 2 3 4)) ;=> ((0 1) 3)
    (unify '(p X Y a) '(p Y X X)) ;=> ((Y a) (X a))
  • 組み込み関数は350個くらい。
  • 以下は全て同じ文字列を表す。バックスラッシュが少し見やすくなるかも。
    • "C:\\home\\lxuser\\newlisp"
    • {C:\home\lxuser\newlisp}
    • [text]C:\home\lxuser\newlisp[/text]

主に不満な点

  • http://lisperblog.blogspot.com/2008/11/blog-post_18.html
  • 関数名に予約されていて変数に使えない名前がある。これはたまにイラッとくる。 例: fn sym name args
  • エラーが貧弱。(デバッガはあるらしいが)
  • 「リスト遊び」がしにくい。(ドット対がないためconsがほぼlistと同じ)
  • マクロが書きにくい。(名前空間共有、`,@がない、macroexpandがない)
  • シーケンスを扱う関数全てがunicode対応というわけではない。
  • (= nil '()) => nil
  • lambdaの代わりにfnが使えるとか、condのように複数条件分岐が使えるifとか、("foo" 0) => "f"とか、arcの機能がちらほら。歴史的に考えてnewLISPの方が先なんだろうけど。

ChangeLog

  • 2009/02/27 - 初版
  • 2011/02/22 - 内容の整理整頓
  • 2011/09/13 - Twitterのリンクを追加

2009年2月25日水曜日

[xyzzy]check-parens

(defun check-parens ()
  "バッファの括弧の釣り合いを調べる."
  (interactive)
  (handler-case
      (let ((home (point)))
        (goto-char (point-min))
        (while (forward-list))
        (goto-char home)
        (message "だいたいあってる")
        t)
    (simple-error (c)
      (message "このへん間違ってるかも")
      (ding)
      nil)))
(compile 'check-parens)
使い方 lisp-mode、lisp-interaction-modeで M-x: check-parens

これをもうちょっと弄ってbefore-save-buffer-hookとかに引っ掛ければ便利そう。

とか思いつつも最近は括弧の閉じ忘れをすることがなくなったので、ほとんど使って いない状況です。

元ネタ: http://calypso.tux.org/pipermail/xemacs-beta/2009-January/015729.html

2009年2月24日火曜日

[Emacs]tabba.elのせいだったのか

tabbar-modeを使うと基本的に「M-x b」等は通常操作と同じ一つ前に開いたバッファにもどります。ただ、kill-bufferしたときだけグループ化された前のファイルに戻ります。

Elisp/タブでバッファを切り替える

どうりでkill-bufferしたとき元のバッファに戻らないわけだ。。 パッチも紹介されているが、どうやらフック関数のコメントアウトだけなのでelispで修正できる範囲のよう。

(remove-hook 'kill-buffer-hook 'tabbar-buffer-kill-buffer-hook)

直った直った。すっきりした。

ちなみにtabbar.elの設定

(require 'tabbar)
(tabbar-mode (if window-system 1 -1))
(remove-hook 'kill-buffer-hook 'tabbar-buffer-kill-buffer-hook)
(when tabbar-mode
  (global-set-key [?\C-x ?\C-.] 'tabbar-forward)
  (global-set-key [?\C-x ?\C-,] 'tabbar-backward))

2009年2月22日日曜日

今日の無題

  • ブログトップが真っ白なんですが… --- この記事更新したら直った。なんだったんだろう?

xyzzyのべんりすぷ(汎用編)

もともとこのブログを作った趣旨が「xyzzyでこんな関数作ったよ、見てね」 のつもりだったのに、最近まですっかり忘れていたような気がする今日この頃です。

Xyzzy Wikiに投稿するのもありなんですが、あまりに雑多すぎて分類に困りそうなのでブログの方にしました。(気が小さいなんて言えないです…)

普段使っている関数群なので、そこそこ枯れていると思います。
http://paste.lisp.org/display/75922

以下軽く解説

keyboard-quit
ほとんどquitと同じですが、マークがクリアされます。
kill-region(C-w)のうっかりタイプを防ぐ効果があります。(それでもたまに誤爆しますが)
リージョンを反転表示するrv-regionとの併用がおすすめ。
;; 載せるの忘れてた…
(global-set-key #\C-g 'keyboard-quit)
;; [ツール]->[共通設定]->[マーク行の行番号を反転]にチェック
(setq *inverse-mark-line* t)
shell-goto-bol
shell-modeにて、(point)がプロンプト文字($とか>とか#とか)より右側にあるなら そこまでバック、それ以外は普通の(goto-bol)を呼び出します。
comit-delchar-or-maybe-eof
同じくshell-modeにて、(point)がバッファの末尾ならプロセスをkillします。
current-word
Google検索など、interactiveで文字列を受け取る関数に使えます。
(defun google (str)
  (interactive "sGoogle: " :default0 (current-word t))
  (long-operation
    (shell-execute (concat "http://www.google.com/search?q="
                           (si:www-url-encode (map-internal-to-utf-8 str)))
                   t)))
no-filenames-error
*scratch*バッファでC-x C-sとタイプしてしまったイライラを軽減します。
保存はC-x C-wでいいよね。
(define-key ctl-x-map #\C-w 'emacs-write-file)
add-menu-revert
xyzzy Part7 >>804 より、文字コードを指定してバッファを開き直す項目をコンテキストメニューに追加します。 revert-bufferのGUI版みたいなものです。 ファイル名を持たないバッファだとエラーになるけど、まあいいかな。
backward-delete-word
主にミニバッファでディレクトリをひとつ上にするときに使います。
もっと豪華なものが欲しいですか?

今回はここまで。もう少し続きます。

2009年2月21日土曜日

今日の無題

地方県民はUSTREAMで我慢すればいいや、と思っていた結果がこれですか。。。ぐはぁ(泣)
今回の発表のUSTREAMでの中継/動画アップロードにつきまして 前回のTT#1では、発表者全員より撮影許可を頂けましたので、内容全編を中継/アップロード致しましたが、今回は、すべての発表者の方に撮影承諾を頂けておりませんので、一部内容の中継/アップロードができません。 Shibuya.lisp TT#2 ライトニングトークの発表内容決定!

2009年2月17日火曜日

progvの途中

(let ((buffer-read-only nil))
  (declare (special buffer-read-only))
  (hogehoge))

Emacsのような動的束縛を使うなら上のように書くのがたぶん一般的なんだろうけど、動的束縛といえばprogvなんてものがあることに気づいたので以前自分で書いたものを引っ張ってきてみた。

(defmacro progv (symbols values &body body)
  (let ((label (gensym "progv-form"))
        (var (eval symbols))
        (val (eval values)))
    `(labels ((,label () ,@body))
       ((lambda (,@var)
          (declare (special ,@var))
          (funcall (function ,label)))
        ,@val))))

body部を変数束縛の外で実行する点では間違っていないと思う(たぶん)。 で、実行してみたところトップレベルではうまく動いているよう。

(defun hoge ()
  (let ((*x* 3))
    (progv '(*x*) '(4)
           (list *x* (symbol-value '*x*)))))
(hoge)
;=> (3 4)

ただしprogvを含む関数をコンパイルすると駄目になった。中を覗いてみると、

(si:closure-body (compile 'hoge))
=>
;; *制御文字の置き換えあり*
(lambda ()
  (system:*byte-code "^B^A^@廚^]^T^A^@^[^@Q^\^A
^A^\^A廛^U^B"
                     #(*x*
                       (lambda ()
                         (system:*byte-code "^@^B^@^E^@^A^@・・"
                                            #(*x*)))
                       (lambda #1=(*x*)
                         (declare (special . #1#))
                         (funcall #'#:progv-form350)))))

labelsの展開がうまくいってないらしく、内部関数名"#:progv-form350"が残っている。 ここまで辿ったけどコンパイルの動作がサッパリなのでここでお手上げ。

labels使わないでprogv実装しろってことかなあ。

2009年2月14日土曜日

今日の無題

あの時の話、聞かせてください!:第1回 電波少年の“なすび”に会いたい! - R25.jp

なんと懐かしい…見ていたのは小・中学時代だったかな。

当たった懸賞の品に一喜一憂する姿とか、「当選の舞」とか、ぼさぼさ頭にチョ ンマゲ姿とか、ポスターか何かを見て下部のなすマークが大きくなったり(!?)と か、とにかく見ていて面白かった。日曜日の深夜が楽しみだったよ。

現在のインタビュー時の写真を見て「変わんないなー」とにんまり。 当時の電波少年のホームページ(あったんだ)を読みふけって、懐かしさのあまり もう一度にんまりしてしまった。

なすびさんも元気そうで何よりですね。 この人のポジティブ思考は見習うべきかも。

電波少年的懸賞生活 - 日本テレビ

[xyzzy]autoloadされたモジュールの一覧

xyzzyではロードされたモジュールの一覧はmodulesで参照できるわけですが、 autoload関数で指定された関数は呼び出されるまでロードされません。 そういうモジュール一覧を参照出来ないかと思ってこんなものを作りました。 利用する箇所が見当たらないので、ネタということで。

http://paste.lisp.org/display/75440

まあ、autoload-function-pを弄っただけなんですが。 find-all-symbolsを使っているのでコンパイルしないと重いです。

ところで"hh-call"って何なんでしょう?$XYZZY/lispディレクトリ内には見つか らないし、検索してみても答えは出ず。。。HTML-Helpをcallするとか?

2009年2月10日火曜日

[xyzzy]HexlのPatch

勉強不足以上に実践不足が否めないと思う今日この頃。 テストが終わった(笑)のでちまちまとアウトプットをしていこうと思います。

まあ、たいしたものではないですが。

Hexl@xyzzyのpatch

NANRIさん配布のHexlに対するpatchです。今更な気がするのでひっそりと。 →http://xyzzy.s53.xrea.com/wiki/index.php?patch%2Fpatch%2Fhexl.l 先生、"patch/patch/hexl.l"ってなんですか…

;; Hexlにあると便利そうなおまけ
(defun hexl-coloring-hook ()
  "hexl-modeの表示に色を付ける."
  (make-local-variable 'regexp-keyword-list)
  (setq regexp-keyword-list (compile-regexp-keyword-list
                             '(("^\\w\\{8\\}:" nil 2)
                               ("  .+$" nil :comment)))))
(add-hook 'hexl-mode-hook 'hexl-coloring-hook)
;; バイナリファイルは自動的にhexl-mode
(pushnew '("\\.exe$" . hexl-mode) *auto-mode-alist* :test 'equal)

xyzzylispだけでhexl-modeを再現は一度挑戦して挫折したなあ。

Hexlのように"ADDRESS: BYTE TEXT"の形式でバッファ表示させようとしたけど、関数のコンパイルをしても1Mのファイル読み込みに10秒かかったところでアウト。バイト単位の読み込みはまずかったのかもしれない。でも実践CLにもMP3のID3パーサが紹介されているくらいだからlispでバイナリファイルを扱うのは無茶ではないんだと思う。

もしかしてMP3ファイルのヘッダ部分だけ読み込んでいるのかもしれないが


2009-02-11T18:15:41+09:00追記

NANRIさんからのコメントで、Yamamoto Shinjiさんが移植されたhexl.lがあるこ とを教えてもらいました。ありがとうございます。

ファイルのヘッダ部分を見ると、移植元のhexl.elのコードは1994年らしいです。

;; Copyright (C) 1989, 1994 Free Software Foundation, Inc.

一方、NANRIさん移植のhexl.lは2001年もの。

;; Copyright (C) 1989, 1994, 1998, 2001 Free Software Foundation, Inc.

さすがにこれだけ移植元の年数が違うと、hexl.elのコード自体もそれなりに変 更が加えられているみたいでした。

また、Yamamotoさんのhexl.lを試したのですがhexl-beginning-of-line (Control-a)の挙動がおかしいらしく、テキスト部のカーソル(reverse-region)が 追いつかないバグが残っているようです。

(setq hexl-exec-directory "C:/usr/local/emacs-22.3/bin/")
(require "hexl")

そんなわけで、コメントをいただいて恐縮ですがしばらくは使い慣れたHexlを弄ろうかと思います。