10

私はPythonで動作します。最近、fnという素晴らしい小さなパッケージが見つかりました。私は関数の構成のためにそれを使用してきました。例えばPythonの関数の構成の改善

、代わりに:

baz(bar(foo(x)))) 

FNと、あなたが書くことができます:私はこれを見たとき

(F() >> foo >> bar >> baz)(x) . 

、私はすぐにClojureの考え:

(-> x foo bar baz) . 

しかし、 Clojureでは、入力がどのように左にあるのか注意してください。私はこれがpython/fnで可能かどうか疑問に思います。

+2

、私にはこれが本物のコードで行うには悪いことのように思えます。 –

+0

あなたが求めているのであれば、その正確な構文をPythonで動作させる方法はありません。さまざまな方法でそれを近似することができます。構文上重要なことは何ですか? – BrenBarn

+0

左から右への流れを維持する。現在、合成された関数の議論は終わりです。 F()>> x >> foo >> bar >> bazなどと書くことができれば、より明確になります。 –

答えて

9

あなたは、正確な構文を複製することはできませんが、似た何かを作ることができます。

def f(*args): 
    result = args[0] 

    for func in args[1:]: 
     result = func(result) 

    return result 

が動作しているようです:

>>> f('a test', reversed, sorted, ''.join) 
' aestt' 
2

することができますが、あなたが、その正確な構文を取得することはできませんF(x)(foo, bar, baz)のようなものを入手してください。ここでは簡単な例です:それは、後に別の機能を再利用することができ、引数を格納するので

class F(object): 
    def __init__(self, arg): 
     self.arg = arg 

    def __call__(self, *funcs): 
     arg = self.arg 
     for f in funcs: 
      arg = f(arg) 
     return arg 

def a(x): 
    return x+2 
def b(x): 
    return x**2 
def c(x): 
    return 3*x 

>>> F(2)(a, b, c) 
48 
>>> F(2)(c, b, a) 
38 

これはBlenderの答えとは少し異なっています。

これは通常の関数アプリケーションのようなものです。関数を前に指定し、後で指定する引数を残す代わりに、引数を指定して、後で指定する関数を残します。面白いおもちゃですが、なぜ本当にこれが欲しいのか考えにくいです。

1

あなたはClojureの構文に少し近づくことができます少しハックで、fnを使用する場合:

>>> def r(x): return lambda: x 
>>> (F() >> r(x) >> foo >> bar >> baz)() 

は、私はちょうどxを返します構成チェーンの最初に別の機能を追加する方法を参照してください。呼び出されると。この問題は、引き続き引数を取らずに合成関数を呼び出さなければならないことです。

私は@ Blenderの答えは、PythonでClojureのスレッド関数をエミュレートしようとしている最善の策だと思います。

0

私は、これは、単純な入力のために働くように見えるこの

def _composition(arg, *funcs_and_args): 
    """ 
    _composition(
     [1,2,3], 
     (filter, lambda x: x % 2 == 1), 
     (map, lambda x: x+3) 
    ) 
    #=> [4, 6] 
    """ 
    for func_and_args in funcs_and_args: 
     func, *b = func_and_args 
     arg = func(*b, arg) 
    return(arg) 
0

を思い付きました。複雑な入力には手間がかかりません(例:((42, 'spam'), {'spam': 42}))。

def compose(function, *functions): 
    return function if not functions else \ 
      lambda *args, **kwargs: function(compose(*functions)(*args, **kwargs)) 

def rcompose(*functions): 
    return compose(*reversed(functions)) 

def postfix(arg, *functions): 
    return rcompose(*functions)(arg) 

例:

行動を演算子オーバーロードは面白いですが
>>> postfix(1, str, len, hex) 
'0x1' 
>>> postfix(1, hex, len) 
3 
関連する問題