3

Java 不支持这种结构:

if ((int ext_pos = fname.lastIndexOf('.')) >= 0)
    fname = fname.substring(0,ext_pos);

(编译时出现语法错误)。

然而,其他一些语言支持这样的东西,例如,在 Perl 我可以写

if (defined (my $foo = $bar{$baz})) { ... do stuff with $bar ... }
# $bar does not exist here

显然,这比其他任何东西都更像是语法糖,因为人们可以用 Java 将它重写为

{
    int ext_pos = fname.lastIndexOf('.');
    if (ext_pos >= 0)
        fname = fname.substring(0,ext_pos);
}

以增加 3 行代码为代价。

这个构造怎么称呼?

(额外问题:哪些语言支持它?为什么 Java 和 C++ 不支持它?)

4

4 回答 4

5

您必须将声明移到 if 语句条件之外。声明是语句,不能用作表达式

int ext_pos;
if ((ext_pos = fname.lastIndexOf('.')) >= 0)
    fname = fname.substring(0,ext_pos);

在您指出的某些语言(Perl)中,您可以这样做。这是因为这些语言中的赋值也可以被视为一个表达式,因此嵌套在其他表达式中。

(我不确定这个结构叫什么)

于 2013-06-27T17:09:59.357 回答
2

Java 允许在表达式中赋值,但不允许变量声明(感谢 biziclop 的更正!)。C++ 传统上具有相同的限制,但我发现另一篇 stackoverflow 帖子描述了 C++03 标准中的条件中如何允许声明。语法是有限的,但这是允许的(在 GCC 4.2.1 上测试):

int x = 1;
if (int y = x)
  cout << "y = " << y << endl;

请注意,正如 biziclop 指出的那样,这具有将范围限制在条件范围内的良好属性y。如果您尝试y在条件之外使用,您将收到错误消息:

int x = 1;
if (int y = x)
  cout << "y = " << y << endl;
cout << y; // error: ‘y’ was not declared in this scope

我不认为它实际上有一个名字——它只是允许在表达式中声明。我认为拥有自己的专业术语并不常见。

至于语言支持。JavaScript有点支持这一点,因为它允许在表达式中赋值,并且如果你在 JavaScript 中引用一个未声明的变量,它只是假设它是全局的。

if (x = 1) alert(x) // x is global, assigned 1
alert(x) // since x is global it's still in scope and has value 1

基本上,声明是表达式的任何语言都允许您这样做。在大多数函数式编程语言(例如 Haskell、ML、Lisp)中,基本上一切都是一个表达式,因此您可以在条件中声明新的变量绑定(但它们在条件主体中不可用)。这是Clojure中的一个示例:

(println          ; print the result of the conditional
  (if (let [x 1]  ; declare local binding x = 1
        (== x 2)) ; check if x == 2
    "is two"      ; true branch result
    "isn't two")) ; false branch result
于 2013-06-27T18:32:22.790 回答
0

虽然 Java 不喜欢在 if 语句中实例化一个变量,但它会让你设置一个。

int ext_pos;
if ((ext_pos = fname.lastIndexOf('.')) >= 0) {
    fname = fname.substring(0, ext_pos);
}

正确编译。我知道这与您的解决方案非常相似,但我只是想指出这一点。

同样,Matthew Crumely 回答了一个关于在 if 条件语句中使用另一种方法设置变量的问题。简而言之,他指出这可能会给其他查看您的代码的人造成一些代码混乱。即使它确实是有意的,使用错误的“=”或“==”也很容易看起来像一个菜鸟错误。

我对他们为什么这样做的真正猜测是为了使代码易于阅读。

于 2013-06-27T17:26:39.180 回答
0

这是block符号。请参阅Java 规范第 14.2 节。根据规范:

通过从第一个到最后一个(从左到右)的顺序执行每个局部变量声明语句和其他语句来执行一个块。如果所有这些块语句正常完成,则该块正常完成。如果这些块语句中的任何一个由于某种原因突然完成,那么该块也因为同样的原因而突然完成。

第 14.3 节展示了一个包含此语法的示例,您也可以在整个规范中找到此语法。

于 2013-06-27T17:40:44.097 回答