2014-02-27 29 views
2

是否有內置的方法來自動傳播調用函數nargout到被調用的函數? (或一個調用的函數,以找出調用函數的nargout?)如何傳播(或反思)nargout?

例如,說

% foo.m 
function [X, Y] = foo() 
    [X, Y] = bar(); 
end 

% bar.m 
function [X, Y] = bar() 
    X = 1; 
    if upstream_nargout() < 2 
     Y = 0; 
    else 
     Y = big_nasty_time_consuming_monster(); 
    end 
end 

當然,一個總能定義foo像這樣

% foo.m 
function [X, Y] = foo() 
    if nargout < 2 
     X = bar(); 
    else 
     [X, Y] = bar(); 
    end 
end 

...或定義bar與一個額外的參數攜帶來電者的nargout,但我想知道是否有一個合理的方式來實現相同的效果,而不訴諸於此。

回答

2

varargoutnargout工作如下:

% foo.m 
function varargout = foo() 
    [varargout{1:nargout}] = bar(); 
end 

% bar.m 
function varargout = bar() 
    varargout{1} = 1; 
    if nargout > 1, 
     fprintf('bar: computing second output\n'); 
     varargout{2} = rand(); % OR big_nasty_time_consuming_monster(); 
    end 
end 

然後:

>> X = foo 
X = 
    1 
>> [X,Y] = foo 
bar: computing second output 
X = 
    1 
Y = 
    0.5647 

註釋:foo在問題後面的版本 「當然,一個總是可以這樣定義富」 會肯定有效,但是這種替代方案允許您在foo中調用bar而不是另一個if/else。當我讀到這個問題時,就是這個問題的關鍵。

+0

謝謝!雖然我明白了爲什麼'varargout'(我不知道 - 這是我對基本MATLAB的無知程度)在這裏會很有用,我對你的提議的某些細節有些困惑。但是,在瞭解了'varargout'之後,在我對你想法的簡單回憶中,'foo'的主體應該是單行'[varargout {1:nargout}] = bar();',實際上,這至少在這個人爲簡單的例子中,一行「天真的foo」似乎在我嘗試時可以工作。我確信有很好的理由避免這種天真的做法,但我無法弄清楚。 – kjo

+0

你的意思是沒有'cell'初始化行的一行?運行沒有輸出參數的'bar'(在命令行中只是'foo') - 如果沒有'cell'分配,它將無法工作。 – chappjc

+0

我嘗試了所有我能想到的打破「天真foo」的想法,希望能夠獲得執行背後原理的線索。你在評論中提出的建議是我嘗試過的幾件事情之一,但是我沒有試過,也沒有試過任何其他嘗試打破了「天真的虛榮」......(FWIW,我正在使用R2013b。) – kjo

1

我看不出有任何理由要nargout傳播求助者,這應該符合您的要求:

function [X, Y] = foo() 
    if nargout < 2 
     X = bar(); 
    else 
     [X, Y] = bar(); 
    end 
end 

function [X, Y] = bar() 
    X = 1; 
    if nargout < 2 
     Y = 0; 
    else 
     Y = big_nasty_time_consuming_monster(); 
    end 
end 

如果你真的需要卡列斯nargout使用evalin('caller','nargout'),但我絕不會結合nargin/nargout與evalin('caller',你可以很容易地產生碼這是不可能進行調試。