【问题标题】:Distinguish between scripts and functions programmatically以编程方式区分脚本和函数
【发布时间】:2013-04-09 18:52:26
【问题描述】:

给定一个文件名,我如何以编程方式区分 MATLAB 中的脚本和函数?

如果我尝试将参数传递给脚本,我会得到Attempt to execute SCRIPT somescript as a function:。有没有办法在不尝试执行的情况下检测到它?


更新:正如@craq 指出的,在这个问题发布后不久,MATLAB Central 上有一篇关于此的文章:http://blogs.mathworks.com/loren/2013/08/26/what-kind-of-matlab-file-is-this/

【问题讨论】:

  • 如果您尝试将错误数量的参数传递给函数,您是否也会收到错误消息?然后,看起来您正在谈论的问题不是特定于脚本的......
  • @Ilya 不过这是一个不同的错误。我只是显示错误以指出 MATLAB 可以区分脚本和函数,因为它报告这个东西是一个脚本。不过可能是跑了才弄明白的,我不知道……
  • 当发生这种情况时,它会抛出带有标识符 MATLAB:scriptNotAFunction 的异常,因此您可以通过与 matlab 相同的 try-catch 来检测这一点,但如果 try 有效,脚本将正常执行...
  • 在提出这个问题后不久,MATLAB Central 上有一篇关于此问题的文章。 cmets 引用了这个问题并得出结论,@YYC 的答案更好。 (或 YYC 和 Floris 的组合。)
  • @craq 感谢您指出这一点,我不知道那篇文章。

标签: matlab function


【解决方案1】:

没有找到干净的解决方案,但您可能可以使用try-catch(如@Ilya 建议的那样)和nargin

EDIT - 使用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

【讨论】:

  • 我比我的解决方案更喜欢它。我建议将这两种方法结合起来——创建一个isFunction 函数,但在其中使用这种方法而不是我非常笨拙的方法。
  • 看起来不错。您预见到任何潜在的问题吗?该函数可能会在 MEX 文件中定义,并且会显示为does not know how to answer nargin/nargout,但这不会破坏您的方法。另外,为什么不比较err.identifier 而不是err.message
  • catch 语句的一个问题:如果我使用 m_file_in_question.m 作为变量名,strcmp 将返回 False,因为 err.message 仍将使用“短”名称(不含.m)。相反,寻找部分匹配,例如使用strfind(但要认识到其他错误消息会生成“这是一个函数”返回值,这实际上不是您想要的)。
  • mex 问题的可能解决方案已添加到我上面的答案中...随意使用。
  • @Szabolcs:我不知道是否还有其他潜在问题,因为我不太熟悉 MATLAB 中的异常处理。不过,我希望exist() 可以帮助进一步解决一些极端情况,例如 MEX 文件。
【解决方案2】:

如果您愿意使用半文档化的功能,可以尝试以下方法:

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

这与MATLAB CodyContests 中用于测量代码长度的函数相同。

【讨论】:

  • 它构建了一个完整的解析树。与所有未记录的内容一样,引用帮助:“这是一个实验程序,其行为和界面可能会在未来发生变化。” :)
【解决方案3】:

这有点小技巧,但是……如果参数是函数,则返回 true,否则返回 false。可能有例外情况,这不起作用 - 我期待 cmets。

EDIT - 捕捉函数在 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-04
    • 2018-10-11
    • 2010-09-28
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    • 1970-01-01
    相关资源
    最近更新 更多