Matlab中“结束”的语义是啥?
Posted
技术标签:
【中文标题】Matlab中“结束”的语义是啥?【英文标题】:What are the semantics of 'end' in Matlab?Matlab中“结束”的语义是什么? 【发布时间】:2014-05-25 20:18:18 【问题描述】:在 Matlab 中使用end
关键字作为访问或扩展数组的快捷方式很常见,如
>> x = [1,2,3];
>> x(1:end-1)
ans =
1 2
>> x(end+1) = 4
x =
1 2 3 4
但是,我惊讶地发现以下方法也有效
>> x(1:min(5, end))
ans =
1 2 3 4
我认为end
可能是一种特殊形式,例如:
,在索引操作中可以是特殊情况,所以我创建了一个类来检测这一点
classdef IndexDisplayer
methods
function subsref(self, s)
disp(s);
end
end
end
您可以在下面的示例中看到:
的特殊情况
>> a = IndexDisplayer;
>> a(1:3)
type: '()'
subs: [1 2 3]
>> a(:)
type: '()'
subs: ':'
但是,当我使用 end
索引时,我只看到了
>> a(end)
type: '()'
subs: [1]
这里end
替换为1
。 1
来自哪里?我的第一个猜测是索引表达式x(end)
中的任何end
都将被替换为对length(x)
的调用,所以我也尝试覆盖length
classdef IndexDisplayer
methods
function subsref(self, s)
disp(s);
end
function len = length(self)
len = 10;
end
end
end
但是,这给了
>> a = IndexDisplayer;
>> length(a)
ans =
10
>> a(end)
type: '()'
subs: [1]
所以这个理论是不可能的。谁能解释end
的语义?
【问题讨论】:
【参考方案1】:我也觉得这很奇怪。尽管如此,我经常使用(利用?)这种行为来缩短语句。例如,在this answer 中,要获取向量的k
th 元素以外的所有元素,我想到的一个干净的解决方案是,
vector(setdiff(1:end,k))
这个end
替换了对numel(vector)
的调用。对于标量k
,这是vector(1:end ~= k)
或vector([1:k-1 k+1:end])
的替代方案。这在当时看来是完全合理的,尽管我提请注意这种用法的奇怪之处。这真的是不好的做法吗?也许吧,但我已经接受了它的价值并继续前进。
正如 Sam Roberts 在他的回答中所做的那样,我没有就其工作原理或规则提供任何见解,但从概念上讲,我认为这是一个上下文问题。也就是说,当end
发生时,我会假设它评估为具有最直接范围的 array 的索引(或维度下标),并通过嵌套语句“向上”查找以做出确定。不确定这是否是正确的措辞,但它似乎是解释end
操作的有用方式。
我还没有被这种解释所困扰。
【讨论】:
我只是在这里闲逛。只是想在您发布帖子 3 天后将您指向 the comment by OP(以防您错过):这是官方未记录的行为。 @AndrasDeak 我确实看到了,谢谢。我应该说我只会在交互式 MATLAB 命令提示符中使用这样的语句,而不是在编写您希望将来使用的函数或脚本时。【参考方案2】:首先,我认为您的语法 x(1:min(5, end))
完全有效,这是一种错误,或者至少是一个意想不到的功能。当我在 MathWorks 时,我记得有人指出了这一点,并且相当多的开发人员不得不花一些时间来弄清楚发生了什么。我不确定他们是否真的同意这是一个问题。
解释end
的(预期)语义:end
实现为函数ind = end(obj, k, n)
。 k
是包含end
的表达式的索引,n
是表达式中索引的总数。
因此,例如,当您调用a(1,end,1)
时,k
为 2,因为end
在参数 2 中,n
为 3,因为有 3 个参数。
ind
作为可替换表达式中end
的索引返回。
您可以为自己的类重载 end
(与重载 colon
、size
、subsref
等的方式相同)。
扩展您的示例:
classdef IndexDisplayer
methods
function ind = end(self,k,n)
disp(k)
disp(n)
ind = builtin('end', self, k, n);
end
end
end
>> a = IndexDisplayer;
>> a(1,end,1)
2
3
更多信息请参见here。
【讨论】:
很有趣,谢谢。我想对象的默认end
只是返回1
?我很想知道它在x(1:min(5,end))
的情况下是如何工作的。您是否会沿着调用树向上走,直到找到为其定义了 end
函数的对象?
我不确定x(1:min(5,end))
到底发生了什么,我不确定除非您可以访问 MATLAB 的内部,否则您是否能明确找到答案。当end
在这样的表达式中时,它如何选择要分派到哪个end
函数对我来说并不明显。例如,如果将min
重新定义为一个数组,end
似乎指的是数组的结尾min
,而不是x
的结尾,我真的无法解释为什么。您可能需要询问 MathWorks,尽管我不确定除了几个开发人员之外的任何人都能给您一个完整的解释。
如果你幸运的话,@Edric 可能会听到这个 batcall 并比我更好地解释事情......
PS 您还问过对象的默认 end
是否只返回 1。对象只是一个标量数组(大小为 (1,1)),所以是的,当仅在一个对象上调用时,它将返回 1。但如果在不同大小的对象数组上调用,它将返回适当的值 - 除非您为该类重载了 end
。在具有Data
属性的类的文档中有一个示例,其中end
被重载以返回有关Data
而不是对象本身的信息。这样做时,在对象数组上调用时,您必须非常小心才能获得正确的行为。
Mathworks 技术支持人员基本上确认这是未记录的行为,不应依赖(特别是,它可能会在更高版本的 MATLAB 中消失或改变行为)。我暂时将其标记为已接受。以上是关于Matlab中“结束”的语义是啥?的主要内容,如果未能解决你的问题,请参考以下文章