boost.lambda をパクってみた in Python

C++ には boost.lambda という変態ライブラリがあります。

だいたい ここらへん を参照するとよくわかると思います。

_1 * 2

とか書くと一つ目の引数を二倍する関数になるわけです。

そういえば scala でも

0 to 20 map(_*2)

なんて書くと簡単にコレクションの全要素を二倍できます。

まあ scala ですしね。

Python でこんな事できたらなーなどとちょっと思ったわけです。Python なので簡単です。

pyexpression

というわけで こんなもの を作りました。誰得です。

これを使うと

from pyexpression import _1

# _1 は引数の一番目 (1 origin)
map(_1 * 2, range(5)) # => [0, 2, 4, 6, 8]

という具合に書けます。

引数はキーワード引数もサポートしていて

from pyexpression import _1, _k

f = _1 * 2 + _k.val

f(10, val=20) # => 10 * 2 + 20

という感じです。

呼び出し可能オブジェクトの場合、挙動が上書きされてしまって呼び出すことができないのでリテラルオブジェクトにしてあげる必要があります。

from pyexpression import _1, Literal

@Literal
def add(x, y):
    return x + y

map(add(_1, 10) + 20, range(5)) # => [30, 31, 32, 33, 34, 35]
if とか

boost.lambda における if_ 相当のものもパクっておきました。

from pyexpression import if_, _1, _2

b = if_(_1)[
        10
    ].elif_(_2)[
        20
    ].else_[
        30
    ]

b(1, 2, 3) # => 10
b(0, 1, 3) # => 20
b(0, 0, 3) # => 30

ちょっと書きにくいです。

まとめ

Python で boost.lambda をパクってみました。

型がないので呼び出し可能がどうとかいう判定がめんどくさいなーと思いました。

lambda と Conditional Expressions 使えばいいじゃないかというツッコミは無粋だと思います。