Cython: resolve build dependencies of files that contian relative cimports

Cythonでcimportの相対インポートを使うと、setup.pyの中で依存する.pyx, .pxdを取得できなかった。
現時点の最新版(v0.1.8)でもまだ該当部分がNotImplementedとなっているので、
とりあえずモンキーパッチ的なもので解決してみる。

# setup.py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
from Cython.Build import cythonize
import re

_re_rel = re.compile('^(\.+)(.*)')

class DT(Dependencies.DependencyTree):
    def find_pxd(self, module, filename=None):
        #print 'called find_pxd', module, filename

        m = _re_rel.match(module)
        if m:
            p = self.package(filename)
            (dots, target) = m.groups()
            if len(dots) > 1:
                p = p[:1 - len(dots)]

            target = p + tuple(target.split('.'))
            module = '.'.join(target)

        return super(DT, self).find_pxd(module, filename)

Dependencies.DependencyTree = DT

setup(
    name='hoge',
    cmdclass = {'build_ext': build_ext},
    ext_modules = cythonize('hoge/*.pyx'),
)

これで通るはず。

$ python setup.py build_ext --inplace

ちゃんとテストを書いたらgithubでpull requestしようかな。

シェルスクリプトでサブコマンドを実現する

様々なコマンドを叩くスクリプトを作る場合、シェルスクリプトで書くのは最も直接的で速い方法だと思いますが、
どうしてもPython等のLLを使いたくなってしまう理由として

  • hashなどのデータ構造がない
  • サブコマンドを作る仕組みがない
  • オプションのパースが面倒
  • unit testができない

という問題があります。

オプションのパースについてはgetoptなどを使う方法もありますが、
結局while, case文を使ったhttps://code.google.com/p/sqt/source/browse/bin/sqt-bwaにあるような方法が
シンプルで良い気がしています。

一方サブコマンドを実現するシンプルなやり方は

#!/bin/bash

some_task() {
   local sample="${1?:need sample name}"
   local out="${2?:need output file name}"

   some_command $sample $out
}

"$@"

のようなスクリプトを書いて

$ ./command.sh some_task sample output

のように使うことでしょう。


最近はこの方法で即席のコマンドライン・ツールを作っていましたが、
さらに使えるサブコマンド一覧を表示できるような簡単な方法を考えてみました。


サブコマンドは以下のように作ります。

#!/bin/bash

source functions.bash

some_task() {
   local sample="${1?:need sample name}"
   local out="${2?:need output file name}"

   some_command $sample $out
}

subcommand "$@"

sourceしているfunction.bash

subcommand() {
    _ls_available_commands() {
        local fs="$(compgen -A function)"

        join -v 1 <(echo "$fs") <(echo "$__DEFAULT_FUNCTIONS") | grep -v '^_'
    }

    _show_help() {
        echo 'Available commands'
        _ls_available_commands | awk '{print "-", $0}'
        exit -2
    }

    if [ -n "$(_ls_available_commands | awk -v f=$1 'f==$0')" ]; then
        "$@"
    else
        _show_help
    fi
}

__DEFAULT_FUNCTIONS="$(compgen -A function)"

のようなファイルです。

これを作ってからスクリプティング・ライフがだいぶ快適になりました。

Pythonのyieldとfinally

pythonでyieldした後に必ずやってほしい処理を組み込めるかが気になったので確かめてみました。処理系はpython 2.6.1です。まず、以下のようなジェネレータを作ります。

# coding: utf-8

def yielder(max=10):
  print '*', 'Init yielder'
  for i in range(max):
    try:
      yield i
    except Exception, e:
      print e, '(inside)'
    finally:
      print 'exit', i

これを使う色々なコードを試してみます。

#普通のループ
for i in yielder():
  print 'use', i,

#途中でループを抜ける場合
try:
  for i in yielder():
    print 'use', i,
    if i == 5:
      raise Exception('Fault!')
except Exception, e:
  print e, '(outside)'

#途中でexitする場合
for i in yielder():
  print 'use', i,
  if i == 5:
    exit()

結果は以下のようになりました。
ループを抜ける前にfinally句が確実に実行されているようで心強い。

* Init yielder
use 0 exit 0
use 1 exit 1
use 2 exit 2
use 3 exit 3
use 4 exit 4
use 5 exit 5
use 6 exit 6
use 7 exit 7
use 8 exit 8
use 9 exit 9
* Init yielder
use 0 exit 0
use 1 exit 1
use 2 exit 2
use 3 exit 3
use 4 exit 4
use 5 exit 5
Fault! (outside)
* Init yielder
use 0 exit 0
use 1 exit 1
use 2 exit 2
use 3 exit 3
use 4 exit 4
use 5 exit 5

Macからssh接続するときの文字化け

Mac OSX同士でssh接続するときに日本語が文字化けして困っていたのですが、.bash_profileにLANG変数を設定したら読めるようになりました。UTF-8同士でも設定しておかないとダメなのか!

export LANG=ja_JP.UTF-8;

vimでなんちゃってREPL

VimmerにとってはLispを書きたいからといってemacsを立ち上げるのは面倒です。
しかし毎日Lispの勉強を続けるにはREPL環境が不可欠!というわけで
この記事などを参考にしてVimスクリプトを書いてみました。一応ちゃんと動きます。

使用イメージ


使い方

  • Ctrl + w nでREPL用の新しいウィンドウを開く
  • Ctrl + l で選択箇所が評価されてREPLウィンドウに表示


visualモードでは、選択した範囲がREPL行きになりますが、普通モードではファイル頭からカーソル位置までにしました。
ソースを~/.vimrcに貼るだけで使えると思います。評価に使うclisp, goshなどはインストールが必要です。僕はお手軽にMacPortsで入れました。

vimrcの設定

Vimスクリプトの書き方が全然分かってないので、品質はあまりよろしくない気がします。
あと、REPLのウィンドウは下に出す前提なのでset splitbelowが必要です。
キーボードのタイプをmapじゃないところに書く方法ってあるんでしょうか?

" window splitting
set splitbelow

" indents
set autoindent
aug ShellType
  au!
  au FileType * setl smartindent
  au FileType lisp,scheme setl smartindent lisp
aug END

" eval commands
aug EvalCommandType
  au FileType * let b:eval_command = "cat"
  au FileType lisp let b:eval_command = "clisp -q"
  au FileType scheme let b:eval_command = "gosh -i"
  au FileType python let b:eval_command = "python -"
aug END

vnoremap <C-l> Y :call SetCommand()<Enter> <C-w>jGoIn >>><esc>pGoOut >>><esc>pmaG:call EvalCommand()<Enter>G<C-w>p
nnoremap <C-l> mbygg :call SetCommand()<Enter> <C-w>jGoOut >>><esc>pmaG:call EvalCommand()<Enter>G<C-w>p :'b<Enter>

function! SetCommand()
  let g:eval_command = b:eval_command
endfunction

function! EvalCommand()
  execute "'a,.!".g:eval_command
endfunction

他の解決法

普通に「vim REPL」でググってみると、もっと洗練されていそうな方法も見つかりました。

  • VimShellを使う方法
  • screenコマンドを使う方法

などがあるようです。そのうちやってみよう。

javascriptで数式処理

微分さえできればいい!と目標を決めて、勢いで書いてみました。一度パーサなるものを書いてみたかったのと、数式処理システムに非常に興味があったので丁度いい題材かと思ってやってみました。やったことは

  • 数式の字句解析(tokenにする)
  • 木構造の表現に変換する
  • それを評価して値を計算させる

です。字句解析は割と簡単にできました。下に行くほど考えることが増える印象。

とりあえず式変形の機能がしょぼすぎて残念ながら実用にはなっていません。。やっぱり

  • 変数の代入機能(スコープを考えなきゃいけない。環境モデルを作る?)
  • 数式を変換して簡単化する(パターンマッチ的な何かをうまく実装できるか)

などが欲しいところです。まあ、これはまたの機会に考えようと思います。機会も何も自分の気分次第なんですが。今の設計はアドホックすぎるので、拡張が面倒そうというのが正直なところです。しかしjsは柔軟で素晴らしい言語だな〜と改めて思いました。


コードはjsdo.itに公開しています↓

jsDeferredの実行順序とハック

jsDeferredjavascriptの非同期処理をエレガントに書けるライブラリで、処理の順序を意識したプログラムが簡単になります。最近気に入ってます。直列実行、並列実行などいろいろな機能がありますが、僕はコールバックにdeferred機能を持たせる使い方をする事が多いです。また、使っているうちにちょっとしたハックを思いついたので、使い方を解説しつつそれについて書いてみます。

jsdeferredを使わない普通のコールバック

まず、100msec後にfnを呼び出すようなlater関数をつくります。

function later(fn){
  setTimeout(fn, 100);
}

そして、これを使って以下のような関数を作るとしましょう。

function a1(fn){
  console.log("a1", "begin");
  fn(); 
  console.log("a1", "end");
}

function b1(){
  console.log("b1", "begin");
  later(function(){
    console.log("b1", "later");
  });
  console.log("b1", "end");
}

ブラウザのコンソールでa1(b1)を実行すると以下のような実行順序になります。

>>> a1(b1)
a1 begin
b1 begin
b1 end
a1 end
b1 later

"b1 later" が後回しになり、"a1 end"の方が先に実行されました。
jsdeferredを使うと、簡単にこの順序を逆にすることができます。

jsdeferredを使って順序を変える

コールバック(b2)の方にDeferredオブジェクトを返すと、それがcallされるまで処理が止まります。
何が起こっているかは...ソースの最初の方を読んだほうが理解が早いと思います。実際かなり勉強にもなりました。

function a2(fn){
  console.log("a2", "begin");
  fn().next(function(){
    console.log("a2", "end");
  });
}

function b2(){
  var d = new Deferred;
  
  console.log("b2", "begin");
  later(function(){
    console.log("b2", "later");
    d.call();
  });
  console.log("b2", "end");

  return d;
}

すると、こうなります。

>>> a2(b2)
a2 begin
b2 begin
b2 end
b2 later
a2 end

さらに変更

では、こんな風にすることはできないでしょうか?

>>> a3(b3)
a3 begin
b3 begin
b3 later
a3 end
b3 end

具体例がないと分かりにくい気もしますが、例えばbのlaterが呼ばれた後に呼び出し元のaでいろいろ処理を挟みたいが、最後にbのendを実行してほしいという場合です。以下のように書いたらその動きになるかと思いましたが、最後の"b3 end"の処理が上書きされてしまって実行できませんでした。

function a3(fn){
  console.log("a3", "begin");
  fn().next(function(){
    console.log("a3", "end");
  });
}

function b3(){
  var d = new Deferred;
  
  console.log("b3", "begin");
  later(function(){
    console.log("b3", "later");
    d.call();
  });
  d.next(function(){
    console.log("b3", "end");
  });

  return d;
}

jsDeferredの場合、普通のメソッドチェーンと違ってd.next()で返るオブジェクトはd自体ではなく、新しいDeferredオブジェクトなので注意が必要です。callするときは元のdをcallします。

jsdeferredをハック

そこで、実験的にjsdeferredのnextが呼び出している_post関数をいじってa側の処理を挟みこむようにしてみました。バージョンは0.3.4を使っています。一応変更してからテストも通ったので、多分問題ないのではないかと思います。

//before (line 188~)
  _post : function (okng, fun) {
    this._next =  new Deferred();
    this._next.callback[okng] = fun;
    return this._next;
  },

//after
  _post: function(okng, fun){
    var next = this._next;
    this._next = new Deferred();
    this._next.callback[okng] = fun;
    this._next._next = next;
    return this._next;
  },

今回の実験コードはgistに載せています。