3
這個想法有多糟糕?類monad
實現了with
接口來放入和退出範圍,所以我可以編寫一個泛型函數庫,例如m_chain,它們指向函數unit
和bind
,這些函數可以在運行時放入實現。 (不管這個代碼做了什麼,或者它是個好主意。)python:突變`globals`動態地把東西放在範圍內
其他想法我嘗試過所有圍繞包含單元/綁定作爲參數或kwarg的結構傳遞,或者將m_chain放入類,以self.unit和self.bind的形式實現它,派生類提供它們。但它增加了代碼和語法的複雜性,並將單元/綁定綁定到monad在python中表示的方式。使用範圍這只是感覺好多了。
class monad:
"""Effectively, put the monad definition in lexical scope.
Can't modify the execution environment `globals()` directly, because
after globals().clear() you can't do anything.
"""
def __init__(self, monad):
self.monad = monad
self.oldglobals = {}
def __enter__(self):
for k in self.monad:
if k in globals(): self.oldglobals[k]=globals()[k]
globals()[k]=self.monad[k]
def __exit__(self, type, value, traceback):
"""careful to distinguish between None and undefined.
remove the values we added, then restore the old value only
if it ever existed"""
for k in self.monad: del globals()[k]
for k in self.oldglobals: globals()[k]=self.oldglobals[k]
def m_chain(*fns):
"""returns a function of one argument which performs the monadic
composition of fns"""
def m_chain_link(chain_expr, step):
return lambda v: bind(chain_expr(v), step)
return reduce(m_chain_link, fns, unit)
identity_m = {
'bind':lambda v,f:f(v),
'unit':lambda v:v
}
with monad(identity_m):
assert m_chain(lambda x:2*x, lambda x:2*x)(2) == 8
maybe_m = {
'bind':lambda v,f:f(v) if v else None,
'unit':lambda v:v
}
with monad(maybe_m):
assert m_chain(lambda x:2*x, lambda x:2*x)(2) == 8
assert m_chain(lambda x:None, lambda x:2*x)(2) == None
似乎合法。我對一些答案會是什麼感興趣。我挖掘效果,讓您根據需要調整和調整功能的變化。如果有一個缺點,我沒有看到一個。我可能會小心地提供m_chains函數將要使用的函數的默認定義,或者如果它們沒有設置,則拋出一個有意義的異常,但否則我會看到一些像這樣的體面的應用程序。 – 2012-07-21 17:08:21