我有一个可以处理任意大小的二维数组的函数句柄:

R2T = @(DL1,DL2) arrayfun(@(DL1,DL2)...
                 1/(fzero(@(x)fFitObj1(x)./fFitObj2(x)-...
                 DL1./DL2,[minLim maxLim])) ...
                 ,DL1,DL2) - C1;
以下是其功能的自下而上的分割:
  • fzero(@(x)fFitObj1(x)./fFitObj2(x)-DL1./DL2,[minLim maxLim])-该位在[minLim maxLim]间隔上寻找要考虑的函数的零,其中fFitObj1fFitObj2是以前可用的函数句柄,C1是一些已知的常量,并且提供了DL1, DL2
  • @(DL1,DL2)1/(fzero(...))-fzero的包装,允许从外部提供DL1DL2
  • arrayfun(@(DL1,DL2)...,DL1,DL2)-另一个包装器,当以矩阵形式提供fzero时,它允许DL1, DL2正确地逐元素操作。
  • R2T = @(DL1,DL2) arrayfun(...) - C1;-另一个允许从外部提供DL1, DL2的包装器。

  • 我的问题是,有时矩阵DL1, DL2可能包含NaN值,在这种情况下fzero返回以下错误:
    Error using fzero (line 242)
    Function values at interval endpoints must be finite and real.
    
    这就是为什么我自然会想到可用的operations with short-circuiting的原因,所以我尝试将any(isnan([DL1,DL2]))合并到其中,以便即使输入的是fzero也不会对NaN进行评估-但无论我如何尝试(例如,定制的三元运算符), fzero似乎已被评估并且代码错误。
    所需的结果:我想对fzero实现一次惰性评估,使其仅在输入有效时才发生(在这种情况下,不是NaN),然后返回NaN,否则,如下面的编辑所示。
    相关资源:
  • http://www.mathworks.com/matlabcentral/newsreader/view_thread/147044

  • 编辑:
    这是一段说明问题的代码(MATLAB 2014a):
    clear variables; clc;
    
    LIM = [0 5];
    fFitObj1 = @(x)x.^2; fFitObj2 = @(x)1;
    C1 = 100;
    
    [DL1A,DL2A,DL1B] = deal(ones(2));
    DL1B(4) = NaN; DL2B = DL1B;
    
    R2T = @(DL1,DL2) arrayfun(@(DL1,DL2)...
                     1/(fzero(@(x)fFitObj1(x)./fFitObj2(x)-...
                     DL1./DL2,LIM)) ...
                     ,DL1,DL2) - C1;
    
    R2T(DL1A,DL2A) %//case A, runs fine
    %{
    // ans =
    //
    //   -99   -99
    //   -99   -99
    %}
    R2T(DL1B,DL2B) %//case B, errors due to NaN
    %{
    // Error using fzero (line 242)
    // Function values at interval endpoints must be finite and real.
    //
    // Error in @(DL1,DL2)1/(fzero(@(x)fFitObj1(x)./fFitObj2(x)-DL1./DL2,LIM))
    //
    //
    // Error in @(DL1,DL2)arrayfun(@(DL1,DL2)1/(fzero( .....
    %}
    
    在情况B下,期望的结果是:
     ans =
    
       -99   -99
       -99   NaN
    

    最佳答案

    就像mentioned in the comments一样:内联是疯狂,最好使用单独的功能/.m文件。

    这将是

  • 更快
  • 更容易阅读
  • 易于编写
  • 更容易调试

  • 例如,您可以使用类似的方式来执行此操作:
    function out = R2TComputation(DL1, DL2, minLim, maxLim, C1)
    ...%Compute whatever R2T would compute.
    

    要获得与原始匿名函数相同的接口(interface),只需创建
    R2T = @(DL1, DL2) R2TComputation(DL1, DL2, minLim, maxLim, C1)
    

    在创建该句柄minLim时,它将捕获maxLimC1R2T的当前值。

    还有一种选择是使用nested function而不是外部的。它可以访问父函数的变量,但仍然可以使用ifelse和您需要的所有其他基本工具。唯一的缺点:不能从其他文件中访问它。
    ... % Main function stuff
         function out = R2T(DL1, DL2)
             if ...
                out = ...
             ...
         end
    ... % Use R2T ...
    

    但是,为了自由起脚,这是if-else的内联版本,我本着Loren's blog post的精神写的,我不建议您使用,因为使用单个表达式几乎没有任何好处而不是相应的if-else语句。
    ifelse = @(cond, varargin) varargin{1+~cond}(); %Only for the insane
    

    如果您想让它执行lazy evaluation,则需要使用零参数的pass an anonymous function,然后将对ifelse进行评估(这就是()中最后两个括号ifelse的含义):
    ifelse(true, 42, @()disp('OMG! WTF! THIS IS CRAZY!!111'))
    

    如果您只是简单地将函数调用disp编写为ifelse的参数而没有@(),则该函数将在我们甚至访问ifelse之前被调用。这是因为MATLAB(与大多数其他语言一样)首先计算函数的返回值,然后将其作为参数传递给ifelse

    在您的情况下,结果代码将是:
    R2T = @(DL1,DL2) arrayfun(@(DL1,DL2)...
                     ifelse(~any(isnan([DL1, DL2])), ...
                            @() 1/(fzero(@(x)fFitObj1(x)./fFitObj2(x)-DL1./DL2,LIM)), ...
                            NaN), ...
                     DL1, DL2) - C1;
    

    10-08 14:03