【问题标题】:When does assignment by reference occur in MATLAB?MATLAB 中什么时候发生引用赋值?
【发布时间】:2017-07-28 14:38:56
【问题描述】:

这是一个关于 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 中,但随后它会忽略该值并将右侧值放入索引引用的位置。

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

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

【问题讨论】:

  • 我对您在 MATLAB World 中生活这么久的期望感到有些困惑。但是,ans 仅在未指定输出参数但表达式至少返回一个时才起作用。 v1(v1 &lt; 5) = 1 表达式以某种方式解析为带有标量扩展的 subasgn 调用。我不知道引用赋值是从哪里来的。

标签: matlab variable-assignment evaluation matrix-indexing language-details


【解决方案1】:

思考示例的一种方式

v1(v1 < 5) = 1;

是考虑MATLAB执行的有效函数形式。在这种情况下,这个表达式被 MATLAB 转换成这样的函数调用:

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

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

【讨论】:

    【解决方案2】:

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

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

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

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


    接下来,我想详细说明TroyEdric所说的内容。

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-03
      • 2011-01-01
      • 1970-01-01
      • 2015-05-23
      • 2014-01-06
      • 2017-02-03
      • 1970-01-01
      相关资源
      最近更新 更多