2013-04-09 66 views
6

給定一個文件名,如何以編程方式區分MATLAB中的腳本和函數?以編程方式區分腳本和函數

如果我嘗試將參數傳遞給腳本,我會得到Attempt to execute SCRIPT somescript as a function:。有沒有辦法檢測到這一點,而不嘗試執行它?


更新:作爲@craq指出,短期內,這一問題被張貼後,有一個關於這個MATLAB的中央文章:http://blogs.mathworks.com/loren/2013/08/26/what-kind-of-matlab-file-is-this/

+0

如果您嘗試將錯誤數量的參數傳遞給函數,您是否也會得到錯誤?然後,它看起來像你說的問題不是腳本特定的... – 2013-04-09 19:03:28

+0

@Ilya雖然這是一個不同的錯誤。我只是指出了錯誤,指出MATLAB可以區分腳本和函數,因爲它報告這個東西是一個腳本。但也許它只是在運行後纔算出來的,我不知道... – Szabolcs 2013-04-09 19:06:12

+0

它使用標識符MATLAB來拋出異常:scriptNotAFunction當發生這種情況時,所以你可以通過try-catch來檢測這一點與matlab相同,但如果嘗試工作腳本將正常執行... – 2013-04-09 19:10:36

回答

9

沒有找到一個乾淨的解決方案,但你可以可能使用try-catch(如@Ilya建議)和nargin

編輯 - 使用function避免一些命名衝突;使用exist到輸入進一步分類(如MEX文件)

function is_script = is_a_script(varargin) 
% is_a_script(varargin) returns one of the following: 
% 1: if the input is a script 
% 0: if the input is a function 
% -1: if the input is neither a function nor a script. 

is_script = 0; 
switch(exist(varargin{1})) 
    case 2 
     % If the input is not a MEX or DLL or MDL or build-in or P-file or variable or class or folder, 
     % then exist() returns 2 
     try 
      nargin(varargin{1}); 
     catch err 
      % If nargin throws an error and the error message does not match the specific one for script, then the input is neither script nor function. 
      if(strcmp(err.message, sprintf('%s is a script.',varargin{1}))) 
       is_script = 1; 
      else 
       is_script = -1; 
      end 
     end 
    case {3, 4, 5, 6} % MEX or DLL-file, MDL-file, Built-in, P-file 
     % I am not familiar with DLL-file/MDL-file/P-file. I assume they are all considered as functions. 
     is_script = 0; 
    otherwise % Variable, Folder, Class, or other cases 
     is_script = -1; 
end 
+0

我比我的解決方案更喜歡它。我建議結合這兩種方法 - 創建一個'isFunction'函數,但在裏面使用這種方法而不是我笨拙的方法。 – Floris 2013-04-09 19:55:14

+0

看起來不錯。你有沒有預見到任何潛在的問題?它可能發生在MEX文件中定義的函數,它會說'不知道如何回答nargin/nargout',但這並不會破壞你的方法。另外,爲什麼不比較'err.identifier'而不是'err.message'呢? – Szabolcs 2013-04-09 21:07:47

+0

你的'catch'語句的一個問題是:如果我使用'm_file_in_question.m'作爲變量名,'strcmp'將返回'False',因爲'err.message'仍然使用「short」名稱(沒有'.m')。相反,尋找部分匹配,例如與'strfind'(但認識到其他錯誤信息會產生「這是一個函數」返回值,這實際上不是你想要的)。 – Floris 2013-04-09 21:18:19

2

這是一個黑客位的,但是......這裏是一個將返回true如果參數是一個函數的函數,如果false不是。有可能會出現這種情況,例如無效 - 我期待意見。

編輯 - 捕捉其中函數是一個MEX文件的情況下...

function b = isFunction(fName) 
% tries to determine whether the entity called 'fName' 
% is a function or a script 
% by looking at the file, and seeing if the first line starts with 
% the key word "function" 
try 
    w = which(fName); 
    % test for mex file: 
    mx = regexp(w, [mexext '$']); 
    if numel(mx)>0, b = true; return; end 

    % the correct thing to do... as shown by YYC 
    % if nargin(fName) >=0, b = true; return; end 

    % my original alternative: 
    fid = fopen(w,'r'); % open read only 
    while(~feof(fid)) 
     l = fgetl(fid); 
     % strip everything after comment 
     f = strtok(l, '%'); 
     g = strtok(f, ' '); 
     if strcmpi(g, 'function'), b=true; break; end 
     if strlen(g)>0, b=false; break; end 
    end 
    fclose(fid); 
catch 
    fprintf(1, '%s not found!\n'); 
    b = false; 
end 
3

如果你願意用半記錄功能,下面是一些嘗試:

function tf = isfunction(fName) 
    t = mtree(fName, '-file'); 
    tf = strcmp(t.root.kind, 'FUNCTION'); 
end 

這是MATLAB CodyContests中用於測量代碼長度的相同函數。

+0

嗯,有趣的是,這個'mtree' ... – Szabolcs 2013-05-06 21:27:22

+0

它構建了一個完整的分析樹。就像所有事情都沒有記錄一樣,並引用幫助:「這是一個實驗性的程序,其行爲和界面在未來可能會改變。」 :) – Amro 2013-05-06 21:34:26