考虑最小可重复的示例:
f = @(x) x
f(end)
请注意,MATLAB 语法突出显示实际上并没有以蓝色突出显示 end,这表明它没有解析为关键字,即使 Stack Overflow 语法突出显示也是如此。
输出:
f =
function_handle with value:
@(x)x
ans =
1
你甚至可以做类似的事情
f = @(x) x
a = f(end + 1)
b = f(end - 100)
c = f(2 + end)
输出:
a =
2
b =
-99
c =
3
如果你有常规功能,这不起作用
foo(end)
function x = foo(x)
end
Error: <filename> Line: 1 Column: 5
The end operator must be used within an array index expression.
由此看来,end 被强制转换为值 1,类似于布尔/逻辑 true 被强制转换为 1 的方式。我的假设是,由于函数句柄实际上是函数句柄的 1x1 数组,因此 end 关键字是替换为数组的最后一个有效索引 1。由于函数不存储为数组,因此它不适用于实际函数。
我有一个特别讨厌的错误,我试图索引到一个与函数句柄名称相似的数组中:
x = 1:5
foo = @(x) x
foos = foo(x) % [1, 2, 3, 4, 5]
out = foos(1) + 2 * sum(foos(2:end-1)) + foo(end)
% Expected: out = 1 + 2 * (2 + 3 + 4) + 5 = 24, Got: out = 1 + 2 * (2 + 3 + 4) + 1 = 20
显然,我重命名了变量以使它们更容易区分。尽管如此,这种行为似乎对我能想到的任何事情都没有用。这是每个对象(包括函数句柄)秘密作为数组的结果的产物吗?如果是这样,用户是否可以采取任何措施来防止这种情况发生,或者是否需要 MathWorks 进行修复?
不存在“秘密数组”——MATLAB 中的每个值都是一个数组。 MATLAB 对数组索引使用与函数求值相同的语法,因此存在歧义。该行为记录如下:https://uk.mathworks.com/help/matlab/matlab_oop/overload-end.html
基本上,当 MATLAB 在索引表达式中遇到
end
时,它会调用被索引对象的 end
方法来计算出适当维度中的最后一个元素。您可以为您编写的类实现您自己的 end
方法 - 仅当您编写的类是具有数组类型行为的标量实例时才有用。
奇怪的事情发生是因为“索引”到
function_handle
实际上是对函数求值。但是,在解释该“索引”表达式的参数时,适用有关计算 end
方法的常用规则,并且由于 function_handle
数组只能是标量,因此它始终返回值 1。