2

这是一个关于 MATLAB 语言的问题。我正在阅读 MathWorks 的“Onramp”教程,我注意到一种奇怪的“通过引用分配”行为(因为没有更好的术语),这与我的期望背道而驰。

v1 = [4 6 1 3 4 9 5];

我认为在下面,它首先评估括号表达式,生成一个逻辑数组 [1 0 1 1 1 0 0],然后索引v1以获得结果。到目前为止,一切都很好。

>> v1(v1 < 5)

ans =

     4     1     3     4

下面是让我吃惊的地方。如果运行它,您将看到ans(默认结果变量,一种匿名变量)获取的值[4 1 3 4]是语句左侧的值。我希望分配只写入ans,而是通过引用传递并写入引用数组v1

>> v1(v1 < 5) = 1

v1 =

     1     6     1     1     1     9     5

当然,这与其他语言类似。在print a[3]语法中意味着我们得到 的值a[3],但在a[3] = 1语法中意味着我们为 赋一个新值a[3]。从这个意义上说,唯一的“新”部分是 MATLAB 允许比大多数语言更高级的索引表达式。

这里令人困惑的是,MATLAB 清楚地以两种方式计算表达式。它获取索引值并将它们存储在 ans 中,但随后它会忽略它并将右侧的值放入索引引用的位置。

如果不对表达式进行两次评估,或者在幕后做其他魔术,我看不出它怎么能做到这一点。我不觉得我掌握了评估的顺序/规则。

感谢您对“真正”发生的事情的任何见解。

4

2 回答 2

1

思考你的例子的一种方法

v1(v1 < 5) = 1;

是考虑MATLAB执行的有效函数形式。在这种情况下,此表达式由 MATLAB 转换为如下函数调用:

v1 = subsasgn(v1, substruct('()', {v1 < 5}), 1);

换句话说,当 MATLAB 看到一个带索引的赋值形式(即变量出现在 的左侧=)时,它在内部被转换为一个函数调用,该函数调用既接收原始值,又覆盖它。(MATLAB 的“就地优化”意味着这通常是有效的,并且不会重复内存)。封装了索引形式的substruct所有细节。如果您要分配给 a 字段的一部分struct或类似的东西,这可能会变得非常复杂。

于 2017-03-08T09:00:25.790 回答
0

我认为这个断言是错误的,这就是造成混乱的原因:

获取索引值并将它们存储在ans

是什么让您认为在写入特定内存之前需要先读取它?这些是独立的操作。

但是,当我们考虑范围时,您所说的可能是有道理的。让我们假设解释器在遇到括号时(很像一个函数),使用自己的变量创建自己的范围,ans然后在完成工作后将其丢弃。然后,我们在封闭范围内看不到这些效果。


接下来,我想详细说明特洛伊埃德里克所说的话。

据我所知,这里的区别在于代码在执行之前如何被解释为内置函数。

  • 您的第一个示例 ,v1(v1 < 5)被解释为subsref后跟隐式分配给ans。相当于ans = v1(v1 < 5);显式地写。这ans是索引表达式的结果。
  • 您的第二个示例 ,v1(v1 < 5) = 1被解释为subsasgn。这里的输出将只是赋值操作后的输入。

关于运算符优先级,请参阅文档页面。

于 2017-03-08T11:46:30.903 回答