6

Given a file name, how can I programmatically distinguish between scripts and functions in MATLAB?

If I attempt to pass an argument to a script, I get Attempt to execute SCRIPT somescript as a function:. Is there a way to detect this without attempting to execute it?


Update: As @craq pointed out, shortly after this question was posted, there was an article about this on MATLAB Central: http://blogs.mathworks.com/loren/2013/08/26/what-kind-of-matlab-file-is-this/

5
  • Won't you get an error as well if you try to pass wrong number of arguments to a function? Then, it looks like the problem you are talking about is not script specific... Commented Apr 9, 2013 at 19:03
  • @Ilya That's a different error though. I just showed the error to point out that MATLAB can tell the difference between scripts and functions, as it reports that this thing is a script. But perhaps it only figured it out after running it, I don't know ... Commented Apr 9, 2013 at 19:06
  • It trows exception with identifier MATLAB:scriptNotAFunction when that happens, so you can detect this by try-catch same as matlab, but if try works script will execute normally... Commented Apr 9, 2013 at 19:10
  • 1
    Shortly after this question was asked there was an article on this issue on MATLAB Central. The comments reference this question and conclude that @YYC's answer is better. (Or the combination of YYC and Floris.) Commented Feb 18, 2014 at 10:36
  • @craq Thank you for pointing this out, I didn't know about that article. Commented Feb 18, 2014 at 14:27

3 Answers 3

9

Didn't find a clean solution, but you can probably use try-catch (as @Ilya suggested) and nargin

EDIT - Use function to avoid some naming conflict; use exist to further classify the input (e.g. 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
Sign up to request clarification or add additional context in comments.

9 Comments

I like it better than my solution. I would recommend combining the two approaches - create a isFunction function, but inside that use this method rather than my very clumsy one.
Looks good. Do you foresee any potential issues? It may happen that the function is defined in a MEX file and it'll say, does not know how to answer nargin/nargout, but that doesn't break your method. Also, why don't you compare err.identifier instead of err.message?
One problem with your catch statement: if I use, as the variable name, m_file_in_question.m, the strcmp will return False as the err.message will still be using the "short" name (without .m). Instead, look for a partial match, e.g. with strfind (but recognize that other error messages would generate "this is a function" return value, which is not actually what you want).
possible solution to mex question added to my answer above... feel free to use.
@Szabolcs: I don't know if there are other potential issues, for I am not really familiar with the exception handling in MATLAB. However, I hope exist() can help further address some corner cases like a MEX file.
|
3

If you are willing to use semi-documented features, here is something to try:

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

This is the same function used in MATLAB Cody and Contests to measure code length.

1 Comment

it builds a full parse tree. As with all things undocumented, and to quote the help: "This is an experimental program whose behavior and interface is likely to change in the future." :)
2

This is a bit of a hack, but... here is a function that will return true if the argument is a function, and false if it's not. It is possible that there are exceptions where this won't work - I look forward to comments.

EDIT - catching the case where the function is in a mex file...

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.