Python-mode(2.6系対応)インストールのメモ

Emacsには標準でPythonモードが入ってるんけど,2.6の構文を認識しないので書きづらい.

というわけで2.6に対応したモードをインストールする.

インストール

どこにPython-modeの2.6対応版があるかと思ったんだけど,

とりあえず標準パッケージに含まれてる事を期待してみる.

まず標準ソースコードを落として展開する.

$ cd src
$ curl -O http://www.python.org/ftp/python/2.6.2/Python-2.6.2.tar.bz2
$ tar xvf Python-2.6.2.tar.gz2
$ cd Python-2.6.2

でelファイルを漁ってみる.

$ find . | grep .el$
./Misc/python-mode.el

ビンゴ!

で,これをいつものようにsite-lispに移す.

$ cp ./Misc/python-mode.el /to/site/lisp/

あとは.emacsファイルにこれを追加.

(setq auto-mode-alist (cons '("\\.py$" . python-mode) auto-mode-alist))
(setq interpreter-mode-alist (cons '("python" . python-mode)
				   interpreter-mode-alist))
(autoload 'python-mode "python-mode" "Python editing mode." t)

以上で勝手に呼び出される.

インデント問題

自分のCarbonEmacsだけなのかわかりませんが,新しいPython-modeを呼び出したら,

インデントがスペースからタブに変わってた!しかもwidthが8....fuck!!!

あり得ないので以下の設定を追加.

(add-hook 'python-mode-hook
          (function (lambda ()
		      (setq py-indent-offset 4)
                      (setq indent-tabs-mode nil))))

これでおk

参考文献

python2.6からwith文つかえる!

with文が便利.

例えば,openとかリソースを開いて閉じる作業の場合,こう書く

import sys

if __name__ == '__main__':
    """
    main section
    """
    try:
        with open (sys.argv[1], 'r') as fp:
            for line in fp:
                sys.stdout.write (line)
    except IOError, inst:
        sys.stderr.write (str (inst) + '\n')
        sys.exit ()

with文のブロック内処理の開始前にopenの作るオブジェクトの__enter__メソッドを実行する.

そして,ブロック内処理の終了後,例外の有無に関わらず__end__メソッドを実行する.

上の実例の場合,__end__メソッド内部でcloseが呼ばれるので自分でcloseをする必要がない!

すばらしい.

しかも,自前でも__enter__と__end__を実装したクラスをつくれば,withに渡せる.



ほかにもスレッドのロック機構にも使われてるらしい.いいね!

elispでちょこっとpythonを生成する

動的型付け言語だと,関数の型チェックを事前に行いたくなったりする.

なわけで,emacsで関数の型をチェックさせる部分を自動で吐かせるスクリプトを書いてみた.

役立つかわからないけど.

(defun filtercar (func lst)
  (let ((result '())
	(rest lst))
    (while rest
      (let ((func-result (funcall func (car rest))))
	(if func-result
	    (progn
	      (push (car rest) result))))
      (setq rest(cdr rest)))
    result))

(defun alistp (lst)
  (catch 'break
    (while lst
      (if (consp (car lst))
	  (setq lst (cdr lst))
	(throw 'break nil)))
    t))

(defun string-consp (cns)
  (if (and (stringp (car cns)) (stringp (cdr cns)))
      t
    nil))

(defun assoc-keys (alist)
  (mapcar (lambda (a) (car a)) alist))

(defun eval-minibuffer-with-checker (checker default-prompt default-init 
					     error-prompt error-init)
  (let ((result (condition-case nil
		    (eval-minibuffer default-prompt default-init)
		  (error nil))))
    (while (or (not result) (not (reduce (lambda (a b) (and a b))
					 (mapcar (lambda (cns) (string-consp cns)) result))))
      (setq result (condition-case nil
		       (eval-minibuffer error-prompt error-init)
		     (error nil))))
    result))

(defun reduce (func lst)
  (if (= (length lst) 1)
      (car lst)
    (let ((prec-result (funcall func (car lst) (cadr lst)))
	  (rest (cddr lst)))
      (while rest
	(setq prec-result (funcall func prec-result (car rest)))
	(setq rest (cdr rest)))
      prec-result)))

(defun py-function-with-type ()
  (interactive)
  (let ((func-name (read-from-minibuffer "function name : "))
	(arg-lst (eval-minibuffer-with-checker #'alistp
					       "write arguments alist ((val type) ...) : " "'"
					       "something wrong, rewrite arguments alist ((val type) ...) : " "'")))
    (insert (concat "def " func-name " ("
		    (reduce (lambda (a b) (concat a ", " b))
			    (assoc-keys arg-lst))
		    "):\n"))
    (while arg-lst
      (insert (concat "if type (" (caar arg-lst) ") != " (cdar arg-lst) ":\n"))
      (insert (concat "raise TypeError ('argument " (caar arg-lst) " is type mismatch. it must be type " (cdar arg-lst) "')\n"))
      (setq arg-lst (cdr arg-lst)))))

使うときは,pythonのバッファで"M-x py-function-with-type"と打つ.

すると,ミニバッファが立ち上がって,関数名と引数と型のリストを入力するよう促される.

引数と型のリストはこういう感じ.

'(("val1" . "int") ("val2" . "int") ("val3" . "str"))

でこんな感じで生成される.

def func-name (val1, val2, val3):
    if type (val1) != int:
        raise TypeError ('argument val1 is type mismatch. it must be type int')
    if type (val2) != int:
        raise TypeError ('argument val2 is type mismatch. it must be type int')
    if type (val3) != str:
        raise TypeError ('argument val3 is type mismatch. it must be type str')

ちなみに自動でインデントされません!まだまだ改善が必要か.

配列初期化問題

詰まった事.

javascriptで配列を初期化するとき,こう書いた.

// 実行環境 : v8 console
// 長さ10の配列を全て整数10で初期化する
var array = (new Array (10)).map (function (elem) { return 10;});
print (array);
,,,,,,,,,

うまくいかない.

そこで内部仕様をみてみる.

print ((new Array (0)).map); 
function map(f, receiver) {
  if (!(typeof(f) === 'function')) {
    throw MakeTypeError('called_non_callable', [ f ]);
  }
  var length = this.length;
  var result = new $Array(length);
  for (var i = 0; i < length; i++) {
    var current = this[i];
    if (!(typeof(current) === 'undefined') || i in this) {
      result[i] = f.call(receiver, current, i, this);
    }
  }
  return result;
}

なるほど.要素が'undefnied'型の場合は何もしないわけか.

そりゃそうだ,本来なら,その値が関数呼び出しの引数になるわけだから.

というわけで,map,filter,forEachメソッドは全部そんな感じだろう.気をつけなければいけない.

正解はこんな感じか.

var array = (function (array) {
    for (var i = 0; i < 10; i++) {
        array[i] = 10;
    }
    return array;
} (new Array (10));

はやく全ての処理系でリスト内包使えるようにならないかな.

Kick start Programming OCaml

静的型付け非純粋関数型言語OCamlを始めてみる,なメモ.

じつはあまり静的型付け言語はすきじゃなかったりする...おおおおおおおおお



MacOSX SnowLeopardに処理系を入れ,emacsをセットアップする.

インストール

OCamlの日本語ページからダウンロードできるパッケージを選択する.

ぼくはocaml-3.11.1を選択.

$ cd src
$ curl -O http://caml.inria.fr/pub/distrib/ocaml-3.11/ocaml-3.11.1.tar.gz
$ tar xvf ocaml-3.11.1.tar.gz
$ cd ocaml-3.11.1
$ ./configure
$ make world.opt
$ sudo make install

というかんじ.

$ ocaml

が実行できればおk.

emacsの設定

ocamlパッケージ付属のocaml-modeは使いづらいらしいのでTuaregModeを導入する.

$ cd site-lisp
$ curl -O http://www-rocq.inria.fr/~acohen/tuareg/mode/tuareg-mode-1.45.6.tar.gz
$ tar cvf tuareg-mode-1.45.6.tar.gz
$ cd tuareg-mode-1.45.6

で,とりあえず,中に入ってる.elファイルをコンパイルしようとしたんだけどエラーが出る.

ad-substitute-tree: Lisp nesting exceeds `max-lisp-eval-depth'

調べてみると,関数内での関数呼び出しの制限らしい.それを考慮して.emacsに項書き足す.

;; expand max-lisp-eval-depth
(setq max-lisp-eval-depth 10000)

;; tuareg-mode (for ocaml)
(push "/Users/yamaneko/.emacs.d/lisp/tuareg-mode-1.45.6" load-path)
(autoload 'tuareg-mode "tuareg" "Major mode for editing Caml code" t)
(add-to-list 'auto-mode-alist '("\\.ml$" . tuareg-mode))

で,これでbyte-compile-fileすると,sym-lock.el以外はなんとかコンパイルできる.うう...

とりあえず,これでプログラムを書ける状態になった.

参考文献

emacsでdiredバッファだけを消去

emacsを使ってると1時間程度でdiredのバッファでバッファリストが埋まる事がある.

そんなわけでこんなのを書いた.

(defun filtercar (func lst)
  (let ((result '())
	(rest lst))
    (while rest
      (let ((func-result (funcall func (car rest))))
	(if func-result
	    (progn
	      (push (car rest) result))))
      (setq rest(cdr rest)))
    result))

(defun get-buffers-by-mode (buffer-list mode-name)
  (filtercar (lambda (buf) 
	       (string= (symbol-name (cdr (assq 'major-mode (buffer-local-variables buf))))
			mode-name))
	     buffer-list))


(defun delete-dired-buffers ()
  (interactive)
  (mapcar #'(lambda (buf) (kill-buffer buf))
	  (get-buffers-by-mode (buffer-list) "dired-mode"))
  nil)

(run-with-idle-timer (* 10 60) 
		     1 
		     (lambda () (delete-dired-buffers)))

ははは,バッファがゴミのようだ.

書き忘れ

去る8/29にLightweightLanguageTVをみにいってきました.そういえば.

オライリーガチャポン3回も引いてしまった.

あのビジネスはすばらしい..



帰りの抽選会でこんなものいただいちゃいました!

仮想化技術Xen-概念と内部構造

仮想化技術Xen-概念と内部構造

ちょっとXenに興味わいてきた.



何はともあれ,運営の方々おつかれさまでした.