这是关于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中,但随后忽略该值并将将右侧值放入索引引用的位置。
我不知道如果不对表达式进行两次评估,或者在幕后做其他魔术,它怎么能做到这一点。我不觉得自己掌握了评估的顺序/规则。
感谢您对“真正”发生的事情有所了解。
答案 0 :(得分:1)
考虑你的例子的一种方式
v1(v1 < 5) = 1;
是考虑MATLAB执行的有效函数形式。在这种情况下,这个表达式由MATLAB转换为函数调用,如下所示:
v1 = subsasgn(v1, substruct('()', {v1 < 5}), 1);
换句话说,当MATLAB看到索引的赋值形式(即变量出现在=
的左侧)时,内部会转换为函数调用,它们都接受原始值,并覆盖它。 (MATLAB&#34;就地优化&#34;意味着这通常是有效的,并且不会重复内存)。 substruct
封装了索引形式的所有细节。如果您要分配struct
字段的一部分或类似的内容,这可能会变得非常复杂。
答案 1 :(得分:0)
我认为这种说法是错误的,而这正是引起混淆的原因:
获取索引值并将其存储在
中ans
是什么让你认为在写入之前需要读取特定的内存?这些是独立的行动。
但是,当我们考虑范围时,您所说的内容可能有意义。让我们假设解释器在遇到括号(很像函数)时,使用自己的ans
变量创建自己的范围,然后在完成其工作后将其丢弃。然后,我们在封闭范围内看不到这些效果。
据我所知,这里的不同之处在于如何在执行之前将代码解释为内置函数。
v1(v1 < 5)
被解释为subsref
,然后隐式分配给ans
。这相当于明确地编写ans = v1(v1 < 5);
。这里ans
是索引表达式的结果。v1(v1 < 5) = 1
被解释为subsasgn
。这里的输出只是赋值操作后的输入。关于运营商优先级,请参阅this文档页面。