为什么元胞数组中的尾随逗号是有效的 Matlab 语法?

Why is a trailing comma in a cell array valid Matlab syntax?

今天我很惊讶地发现

A = {1,2,3}

B = {1,2,3,}

都是 MATLAB 中的有效语法。我本以为第二条语句会产生错误。据我所知,它们生成相同的元胞数组(all([A{:}]==[B{:}]) returns true)。

是否有允许第二种语法的原因?这是解析器中的错误吗? AB真的一样吗?

有趣的是,以下是不允许的:

C = {1,2,3,,,}

这些是更多的猜测,而不是答案。

可以检查 Symbol reference 并发现 逗号 , 可以用作

命令或语句分隔符

To enter more than one MATLAB command or statement on the same line, separate each command or statement with a comma:

for k = 1:10, sum(A(k)), end

在行

B = {1,2,3,}

因此在 3 之后需要一个语句,只有 },这意味着 元胞数组结束 ,一个有效的语句。


分号;官方有3种用法:

数组行分隔符

When used within square brackets to create a new array or concatenate existing arrays, the semicolon creates a new row in the array:

A = [5, 8; 3, 4]

输出抑制

When placed at the end of a command, the semicolon tells MATLAB not to display any output from that command. In this example, MATLAB does not display the resulting 100-by-100 matrix:

A = ones(100, 100);

命令或语句分隔符

Like the comma operator, you can enter more than one MATLAB command on a line by separating each command with a semicolon. MATLAB suppresses output for those commands terminated with a semicolon, and displays the output for commands terminated with a comma.

In this example, assignments to variables A and C are terminated with a semicolon, and thus do not display. Because the assignment to B is comma-terminated, the output of this one command is displayed:

A = 12.5; B = 42.7, C = 1.25;

所以在行

x = {1,2,3,;5,6,7}

它在 3, 之后跟在有效语句 Array Row Separator 之后。之后需要一个新语句,在本例中是双 5。有效。


现在考虑案例

x = {1,2,3,;;;;4,5,6;;;}

如上3,后面的语句Array Row Separator,后面的语句推测null statement - NOP 借用了一些用C 编写的底层程序核心,其基本意思是:什么都不做。所以在 3,; 之后跟了三次 "do nothing",然后才有下一条语句。 没有意义,正如 Matlab 告诉您的那样:不需要额外的分号。 - 但是有效。

它还允许你做一些毫无意义的事情,比如:

if true
    ;
end

这就是大概也是

的原因
C = {1,2,3,,,} 

returns 一个错误,因为逗号 , 不是 空语句 ,但在第一个逗号之后有一个预期的语句。


底线:它看起来很奇怪,但实际上对我来说似乎是合乎逻辑的,因为 Matlab 在内部使用了大量 C 代码并考虑到 null 语句,所有提到的都是有效语法。


其他语言呢?

像 Python 中的 x = [1,2,3,;;;;4,5,6;;;] 这样使用的分号是无效的,即使在预期的 Matlab 克隆 numpy 中也是如此,除非包含在这种不常见的语法中 a = np.matrix('1,2,3;4,5,6')

a = np.matrix('1,2,3,;;;;4,5,6;;;')

也会引发错误,因为 ; 在任何情况下都被解释为 数组行分隔符 ,这会使编译器抱怨行大小不一致。

然而,

x = [1,2,3,]

PythonIronPython 中也是有效语法,在 VBScriptLua 中也是如此,在 中提到。所有这些语言有什么共同点?它们都是(或多或少)在运行时解释的脚本语言。不仅仅是 Matlab。因此,OP 的兴奋仍然没有理由。

如果要从其他代码生成代码,允许尾随标点符号很方便。

例如,Lua允许尾随逗号,因此很容易生成Lua代码。

您不必在生成代码中有特殊情况来省略最后的逗号,您只需为每个项目打印 ITEM-THEN-COMMA。

如前所述,许多语言允许在列表中使用一个额外的元素分隔符。但这与 运行 时间解析无关。甚至 C 也允许。它与易用性有关。这是一项旨在帮助用户的功能。例如,在 C 中你可以定义一个 enum 如下:

enum E {
   a,
   b,
   c,
};

c 后的逗号不是必须的,但是允许的。它使得在这样的列表中添加和删除元素变得更容易,并且更容易以编程方式生成这样的列表( 是正确的!)。

因此,在大多数(如果不是全部)编程语言中,允许在末尾添加一个逗号是很常见的,MATLAB 支持它也是有意义的。列表开头的附加逗号意义不大,但我猜他们支持它,因为它也没有坏处。

连续多个逗号没有意义,这意味着还有未指定的其他元素。

那么多个分号是怎么回事呢?由于 [1;;2] 是合法的语法。这确实与其他语言的做法有很大不同。

不过和MATLAB对换行符的使用是一致的。在 MATLAB 中,换行符很重要。使用[]定义数组时,换行符表示新的数据行:

M = [ 1, 2, 3,
      4, 5, 6,
      7, 8, 9,
    ];

相同
M = [1,2,3; 4,5,6; 7,8,9];

(请注意有时在每行末尾使用逗号会很方便。)

(另请注意,我在这里使用 [] 进行连接,完全相同的逻辑适用于 {}。)

但是因为MATLAB想尽可能多的允许,只要保持不歧义,上面的是一样的:

M = [ 1, 2, 3,
      4, 5, 6,


      7, 8, 9,
    ];

如果允许空行没有坏处,为什么不允许呢?

由于每个换行符对应一个分号,所以上面等同于:

M = [ 1, 2, 3,;...
      4, 5, 6,;...
              ;...
              ;...
      7, 8, 9,;...
    ];

相同
M = [ 1, 2, 3,; 4, 5, 6,; ; ; 7, 8, 9,; ];

因此 MATLAB 必须能够解析它,无论它是否有意义。


反驳

争论点是 ,; 都被定义为语句分隔符,但不知何故假定 ;;; 是一个有效的语句而 ,,, 不是.这根本不是真的:

disp(0),,,disp(1)
disp(0);;;disp(1)

都是有效的 MATLAB 语法(R2017a 解析都没有错误)。

此外,答案令人困惑expressions and statementsdisp(0) 是一个声明。该语句中的 0 是一个表达式。在M=[1,2,3]中,逗号分隔的是表达式,不是语句。那里的逗号不能用作语句分隔符。

事实上,在 MATLAB 中,逗号和分号具有多种含义,具体取决于上下文。语句末尾的逗号和分号(包括空语句)不同于连接表达式 ([1,2;3,4]) 中的逗号和分号。逗号还可以分隔函数调用括号内的表达式,其中不允许使用分号。

为了说明这一点:

1,,,4

有效,而

[1,,,4]

不是。逗号在这两个语句中有不同的作用。

简而言之,该答案中使用的逻辑完全不正确。