2016-11-26 54 views
0

我正在修補強化學習,嘗試使用函數式編程來實現簡單的環境。Python函數式編程列表理解功能組合和while循環

我有功能step: State, Action -> Stateaction_space: State -> [Action, ...]

我找了初始State

s = State() 
e = [s] 
while action_space(s): 
    a = best(action_space(s)) 
    s = step(s, a) 
    e.append(s) 

實現的功能step迭代組成的函數式編程的方式所以我想我需要的是建立理解[f(x) and c(x), f(f(x)) and c(f(x)), f(f(f(x))) and c(f(f(x)), ...]的方式,但沒有必要的評估。

在此先感謝。

+0

而你的問題是?鑑於這個令人困惑的spec爲我寫代碼?無論如何,我相信你想要的是使用['functools.reduce'](https://docs.python.org/3.5/library/functools.html#functools.reduce),這是Python的摺疊操作。 – Bakuriu

+0

@Bakuriu其實,這是[展開](https://en.wikipedia.org/wiki/Anamorphism)。 – phg

+0

@Bakuriu我要求的方向或至少一些關鍵字來尋找。我認爲我正在尋找的解決方案恰恰與'reduce'相反。雖然'reduce'需要2個元素並且返回一個,但是我需要的函數會帶上1個(最後一個)元素並返回2個 - 它是一個函數後的函數。我猜'expand'可能是它的名字。 – FPFTW

回答

1

對於這種情況,理解是不可能的,但您可以創建一個生成器。再進,我也建議你定義最佳功能,以這樣的方式,他們返回的東西falsy(如FalseNone),只要最後一個(行動)的說法是falsy。它會簡化你的代碼。

然後,你可以定義這個發生器:

def unfold(s): 
    while s: 
     yield s 
     s = step(s, best(action_space(s))) 

這有懶惰的優勢。您可以使用它像這樣:

e = [s for s in unfold(State())] 

或者只是:

e = list(unfold(State())) 

功能更強大的編程方法可能是這個遞歸函數:

def unfold(s): 
    return [s] + unfold(step(s, best(action_space(s)))) if s else [] 

e = unfold(State()) 

如果你發現一個命名的需要功能煩人,那麼你可以去這個把戲:

e = (lambda unfold:lambda s:unfold(unfold,s))(
     lambda unfold, s: [s] + unfold(unfold, step(s, best(action_space(s)))) if s else [] 
    )(State()) 

雖然這很不明顯。第一個函數立即用另一個函數作爲參數調用(第二行上的函數):實際的展開函數,其獲取的名稱是第一個函數的參數名稱。

然後該第一函數返回接受狀態參數另一個函數(lambda s:unfold(unfold,s)),並調用展開它。我們也立即調用該函數,並將其傳遞給初始值State()

請注意,展開也傳遞給遞歸樹,以保持它的範圍。

+0

我想它很接近。它給出了正確的結果,但它不是純粹的函數式編程。 – FPFTW

+0

增加了一些替代功能,它們是功能性程序設計*。 – trincot

+0

哦,非常感謝@trincot – FPFTW