2015-08-26 112 views
11

我知道這不是匿名函數,但是我試圖通過匿名函數做一個遞歸函數。遞歸函數的原型顯然是階乘函數。問題在於,難以區分範圍內的的匿名功能。我設法到目前爲止做的是以下幾點:遞歸匿名函數Matlab

[email protected](cn,n,f)eval('if n>1; f(cn*n,n-1,f);else;ans=cn;end'); 
[email protected](n)f(1,n,f); 

或者:

[email protected](cn,n,f)eval('if n>1; f(cn*n,n-1,f);else;disp(cn);end'); 
[email protected](n)f(1,n,f); 

什麼不是很滿意的是,你還當直接分配不能使用此功能,a=f(3)仍然會產生一個錯誤,因爲eval沒有得到價值。

所以我的問題是,你真的可以做一個遞歸函數,通過匿名函數,例如,以某種方式計算階乘,例如, a=f(3)只依賴原生matlab函數(或者你可以在命令行中創建的函數,就像我在我的例子中那樣)? PS:我知道這沒有任何實際用途,它只是一個挑戰,你可以彎曲和濫用Matlab的語法。

+0

你的意思是匿名函數嗎?函數句柄似乎是對我更廣泛的一類對象。但我不是專家,所以我真的在問。 –

+0

@AndrasDeak我當然知道,謝謝你指出這一點! – flawr

+0

目前還沒有Matlab的存取權限,但是你是否嘗試過這樣做?如果n> 1; F(CN * N,N-1,F);其他; CN; end'? – patrik

回答

5

我們現在發現了兩種可能性,都依賴於使用單元陣列。請注意,這可能不適用於八度。

關鍵是實施案例區分。我發現的第一個,可以發現here.

此方法使用matlabs布爾值,true可以評估爲1,而false可以評估爲0

if_ = @(pred_, cond_) cond_{ 2 - pred_ }(); 

在這裏,我們必須提供一個條件作爲第一個參數,和一個2元素單元陣列作爲第二個參數。每個單元格元素應該是一個函數句柄,如果條件爲真/不正確,則調用它。我們的階乘函數應該是這樣的:

fac = @(n,f)if_(n>1,{@()n*f(n-1,f),@()1}) 
[email protected](n)fac(n,fac); 
factorial_(10) 

由於@AndrasDeak如下評價:這裏最重要的是,我們有功能而不是的單元陣列。這提供了短路,因爲n*f(n-1,f)不被評估,除非我們調用相應的功能@()n*f(n-1,f)

second method被@beaker發現是較爲靈活:

iif = @(varargin) varargin{2*find([varargin{1:2:end}], 1, 'first')}(); 

這使得使用的事實,你可以使用varargin(可變的參數量),即使在匿名函數。當你調用這個函數時,你必須改變條件,如果條件成立,應該執行什麼。這個甚至允許switch結構或if ... else if ... else if ... (...) else ...結構。被調用時,它將查找第一個條件爲真(find([varargin{1:2:end}], 1, 'first'))並調用相應的函數。我們的階乘函數的例子是這樣的:

fac = @(n,f)iif(n>1,@()n * f(n-1,f),true,@()1); 
[email protected](n)fac(n,fac); 
factorial_(10) 

編輯:有趣的事實:我們正在與線

[email protected](n)fac(n,fac); 

做什麼也被稱爲應用Y-combinator。其實我們可以這樣寫:

Y = @(f)@(x)f(x,f); 
factorial_=Y(f); 
+1

我建議在兩種情況下都強調'@()'是爲了保護參數不受評估的影響。例如,當你調用'mean(rand(3))'時,matlab首先評估'rand(3)',然後將該矩陣傳遞給'mean'函數。如果你會省略'@()'部分,'iif'會嘗試評估當時沒有意義的功能。主要觀點:'iif'函數在第一個'true'參數中出現短路,但不是。 –