功能手柄内部发生逻辑短路 [英] Logical short-circuit inside a function handle

查看:124
本文介绍了功能手柄内部发生逻辑短路的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a function handle that operates on 2d arrays of arbitrary size:

R2T = @(DL1,DL2) arrayfun(@(DL1,DL2)...
                 1/(fzero(@(x)fFitObj1(x)./fFitObj2(x)-...
                 DL1./DL2,[minLim maxLim])) ...
                 ,DL1,DL2) - C1;

以下是其功能的自下而上的细分:

Here's a bottom-up breakdown of what it does:

  • 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)-另一个包装器,当DL1, DL2作为矩阵提供时,该包装器允许fzero正确地逐个元素操作.
  • R2T = @(DL1,DL2) arrayfun(...) - C1;-另一个允许从外部提供DL1, DL2的包装器.
  • fzero(@(x)fFitObj1(x)./fFitObj2(x)-DL1./DL2,[minLim maxLim]) - This bit looks for a zero of the considered function on the interval [minLim maxLim], where fFitObj1 and fFitObj2 are function handles available from before, C1 is some known constant and DL1, DL2 are provided.
  • @(DL1,DL2)1/(fzero(...)) - a wrapper for fzero that allows DL1 and DL2 to be provided from outside.
  • arrayfun(@(DL1,DL2)...,DL1,DL2) - another wrapper which allows fzero to correctly operate element-by-element when DL1, DL2 are provided as a matrix.
  • R2T = @(DL1,DL2) arrayfun(...) - C1; - yet another wrapper that allows to provide DL1, DL2 from outside.

我的问题是有时矩阵DL1, DL2可能包含NaN值,在这种情况下fzero返回以下错误:

My problem is that sometimes the matrices DL1, DL2 may contain NaN values, in which case fzero returns the following error:

Error using fzero (line 242)
Function values at interval endpoints must be finite and real.

这就是为什么我自然会想到可用的具有短路功能的操作,所以我尝试将any(isnan([DL1,DL2]))合并到其中,这样即使输入NaN也不会对fzero进行评估-但是无论我如何尝试(例如,定制的三元运算符),似乎已被评估,并且代码错误.

This is why I naturally thought of the available operations with short-circuiting, so I tried to incorporate a any(isnan([DL1,DL2])) into this so that fzero won't even be evaluated if its inputs would be NaN - but whatever I try (e.g. a custom-made ternary operator) the fzero seems to be evaluated and the code errors.

期望的结果:我想对fzero实施延迟评估,使其仅在输入有效(在这种情况下为NaN)时才出现,并返回NaN否则,如下面的修改所示.

The desired result: I'd like to implement a lazy evaluation of the fzero to only occur when the inputs are valid (in this case, not NaN), and return NaN otherwise as demonstrated in the Edit below.

相关资源:

以下是说明问题的代码(MATLAB 2014a):

Here's a piece of code that illustrates the problem (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情况下所需的结果是:

The desired result, in case B is:

 ans =

   -99   -99
   -99   NaN

推荐答案

已经

As already mentioned in the comments: Doing this inline is madness and you are much better off using a separate function / .m file.

它将是

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

例如,您可以通过类似的方式执行此操作:

You could do this for example in a similar way to this:

function out = R2TComputation(DL1, DL2, minLim, maxLim, C1)
...%Compute whatever R2T would compute.

要获得与原始匿名函数相同的界面,只需创建

To get the same interface as your original anonymous function has, you can simply create

R2T = @(DL1, DL2) R2TComputation(DL1, DL2, minLim, maxLim, C1)

,它将在创建此句柄R2T时捕获minLimmaxLimC1的当前值.

which will capture the current values of minLim, maxLim and C1 at the time you create this handle R2T.

另一种选择是使用 嵌套函数 而不是外部的.它可以访问父函数的变量,但仍然可以使用ifelse和所需的所有其他基本工具.唯一的缺点:不能从其他文件中访问它.

Yet another option would be to use a nested function instead of the external one. It would have access to the parent function's variables, yet still be able to use if, else and all the other basic tools you need. Only downside: It is not meant to be accessed from within other files.

... % Main function stuff
     function out = R2T(DL1, DL2)
         if ...
            out = ...
         ...
     end
... % Use R2T ...


但是,为了自由起脚,这里是if-else的嵌入式版本,我本着


However, for the sake of freedom of shooting oneself in the foot, here is an inline version of if-else, which I wrote in the spirit of Loren's blog post and I do not recommend using, as there are hardly any benefits of using a single expression instead of the corresponding if-else statements.

ifelse = @(cond, varargin) varargin{1+~cond}(); %Only for the insane

如果您希望它执行惰性评估,则需要

If you want it to do lazy evaluation, you need to pass an anonymous function with zero parameters, which ifelse will then evaluate (That's what the last two parentheses () in ifelse are for):

ifelse(true, 42, @()disp('OMG! WTF! THIS IS CRAZY!!111'))

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

If you simply wrote the function call to disp as an argument to ifelse without @(), the function would be called before we even access ifelse. This is because MATLAB (as most other languages) first computes the return value of the function, which is then passed to ifelse as a parameter.

在您的情况下,结果代码将是:

In your case the resulting code would be:

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;

这篇关于功能手柄内部发生逻辑短路的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆