2013-04-09 14 views
6

Jak mogę programowo odróżnić skrypty i funkcje w MATLAB?Programowo programowo oddziela skrypty i funkcje.

Jeśli spróbuję przekazać argument do skryptu, otrzymam Attempt to execute SCRIPT somescript as a function:. Czy istnieje sposób na wykrycie tego bez próby jego wykonania?


Aktualizacja: W @craq wskazał, krótko po tym pytanie zostało wysłane, nie był artykuł o tym na MATLAB Środkowej: http://blogs.mathworks.com/loren/2013/08/26/what-kind-of-matlab-file-is-this/

+0

Czy nie otrzymasz również błędu, jeśli spróbujesz przekazać błędną liczbę argumentów do funkcji? Wtedy wygląda na to, że problem, o którym mówisz, nie jest specyficzny dla skryptu ... –

+0

@Ilya To jednak inny błąd. Właśnie pokazałem błąd, aby wskazać, że MATLAB może odróżnić skrypty i funkcje, ponieważ informuje, że to jest skrypt. Ale może to tylko wymyśliło, po uruchomieniu go, nie wiem ... – Szabolcs

+0

To trows wyjątku z identyfikatorem MATLAB: scriptNotAFunction, gdy tak się dzieje, więc można wykryć to przez try-catch tak samo jak Matlab, ale jeśli wypróbować działa skrypt wykona normalnie ... –

Odpowiedz

9

nie znalazles czyste rozwiązanie, ale można prawdopodobnie używać try-catch (jak sugeruje @Ilya) i nargin

EDIT - Wykorzystanie function aby uniknąć jakiś konflikt nazewnictwa; używać exist dalej klasyfikować dane wejściowe (np 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

Podoba mi się to lepiej niż moje rozwiązanie. Polecam połączenie obu podejść - stwórz funkcję 'isFunction', ale w tym przypadku użyj tej metody, a nie mojej bardzo niezdarnej. – Floris

+0

Wygląda dobrze. Czy przewidujesz jakieś potencjalne problemy? Może się zdarzyć, że funkcja jest zdefiniowana w pliku MEX i powie: 'nie wie, jak odpowiedzieć na nargin/nargout', ale to nie łamie twojej metody. Dlaczego nie porównasz 'err.identifier' zamiast' err.message'? – Szabolcs

+0

Jeden problem z twoim zdaniem "catch": jeśli użyję jako nazwy zmiennej, 'm_file_in_question.m',' strcmp' zwróci 'False', ponieważ' err.message' nadal będzie używać "krótkiej" nazwy (bez '.m'). Zamiast tego poszukaj częściowego dopasowania, np.z 'strfind' (ale rozpoznaje, że inne komunikaty o błędach generowałyby" to jest funkcja "zwracana wartość, która w rzeczywistości nie jest tym, czego potrzebujesz). – Floris

2

Jest to bit hack, ale ... tu jest funkcją, która powróci true jeśli argument jest funkcją, a jeśli false to nie jest. Możliwe, że istnieją wyjątki, w których to nie zadziała - czekam na komentarze.

EDIT - łowienie w przypadku, gdy funkcja jest w pliku 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

Jeśli są chętni do korzystania z pół-udokumentowanych funkcji, tutaj jest coś spróbować:

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

Jest to ta sama funkcja używana w przypadku MATLAB Cody i Contests do pomiaru długości kodu.

+0

Hmm, co ciekawe, to 'mtree' ... – Szabolcs

+0

tworzy pełne drzewo analizy. Podobnie jak w przypadku wszystkich rzeczy nieudokumentowanych i cytowania pomocy: "Jest to program eksperymentalny, którego zachowanie i interfejs prawdopodobnie ulegną zmianie w przyszłości". :) – Amro

Powiązane problemy