2013-04-09 23 views
6

Dato un nome file, come è possibile distinguere a livello di codice tra script e funzioni in MATLAB?Distinzione tra script e funzioni a livello di programmazione

Se tento di passare un argomento a uno script, ottengo Attempt to execute SCRIPT somescript as a function:. C'è un modo per rilevare questo senza tentare di eseguirlo?


Aggiornamento: Come @craq sottolineato, poco dopo questa domanda è stata pubblicata, c'era un articolo su questo su MATLAB Central: http://blogs.mathworks.com/loren/2013/08/26/what-kind-of-matlab-file-is-this/

+0

Non si ottiene un errore anche se si tenta di passare un numero errato di argomenti a una funzione? Quindi, sembra che il problema di cui stai parlando non sia specifico dello script ... –

+0

@Ilya Tuttavia, si tratta di un errore diverso. Ho appena mostrato l'errore per sottolineare che MATLAB può dire la differenza tra gli script e le funzioni, poiché riporta che questa cosa è uno script. Ma forse l'ha capito solo dopo averlo eseguito, non lo so ... – Szabolcs

+0

E 'un'eccezione con l'identificatore MATLAB: scriptNotAFunction quando ciò accade, quindi puoi rilevarlo provando lo stesso come matlab, ma se prova funziona script verrà eseguito normalmente ... –

risposta

9

non ha trovato una soluzione pulita, ma è possibile probabilmente usare try-catch (come suggerito @Ilya) e nargin

EDIT - utilizzare function da evitare qualche conflitto di denominazione; utilizzare exist per classificare ulteriormente l'ingresso (ad esempio MEX-File)

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

Mi piace meglio della mia soluzione. Consiglierei di combinare i due approcci: creare una funzione 'isFunction', ma all'interno di questo metodo si usa questo metodo piuttosto che il mio molto maldestro. – Floris

+0

Sembra buono. Prevedi potenziali problemi? Può accadere che la funzione sia definita in un file MEX e dirà, 'non sa come rispondere a nargin/nargout', ma ciò non infrange il metodo. Inoltre, perché non confronti 'err.identifier' invece di' err.message'? – Szabolcs

+0

Un problema con la tua istruzione 'catch': se uso, come nome della variabile,' m_file_in_question.m', 'strcmp' restituirà' False' poiché 'err.message' userà ancora il nome "short" (senza '.m'). Invece, cerca una corrispondenza parziale, ad es.con 'strfind' (ma riconosci che altri messaggi di errore genererebbero" questo è una funzione "valore di ritorno, che in realtà non è quello che vuoi). – Floris

2

Questo è un po 'di un hack, ma ... qui è una funzione che restituirà true se l'argomento è una funzione, e se false non è. È possibile che ci siano eccezioni in cui ciò non funzionerà - non vedo l'ora di commentare.

EDIT - cattura il caso in cui la funzione è in un file 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

Se siete disposti a utilizzare le funzioni semi-documentati, qui è qualcosa da provare:

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

Questa è la stessa funzione utilizzata in MATLAB Cody e Contests per misurare la lunghezza del codice.

+0

Hmm, cosa interessante, questo 'mtree' ... – Szabolcs

+0

costruisce un albero di analisi completo. Come con tutte le cose non documentate, e per citare l'aiuto: "Questo è un programma sperimentale il cui comportamento e l'interfaccia è suscettibile di cambiare in futuro." :) – Amro

Problemi correlati