在你看来,你遇到过的最令人惊讶、最怪异、最奇怪或最“WTF”的语言特性是什么?

请每个回答只回答一个特征。


当前回答

特点:Bash, Korn shell (ksh93)和Z shell都允许使用带或不带美元符号的变量下标数组:

array[index]=$value
array[$index]=$value

加上美元符号,会得到10000的期望值:

unset array
for i in {1..10000}
do
    ((array[$RANDOM%6+1]++))
done
unset total
for count in ${array[@]}
do
    ((total += count))
done
echo $total

陌陌性:如果你从RANDOM中移除美元符号,总数将随机变化,甚至大于10000。

类似地,这将产生3而不是2:

a=1; ((r[a++]++)); echo $a

你不能在这里用美元符号,因为这是赋值运算(a在lhs上)虽然你可以用间接的方法,但是双重求值还是会发生。

原因:对于美元符号,变量展开在算术求值之前执行,因此只执行一次。如果没有美元符号,它将执行两次,一次是计算查找的索引,另一次是计算赋值的索引(因此,实际上,循环中第一步的赋值可能看起来像array[4] = $array[6] + 1,这完全打乱了数组)。

其他回答

当我在大学的时候,我用一种叫做SNOBOL的语言做了一点工作。整个语言虽然很酷,但却是一个大WTF。

它的语法是我见过的最奇怪的。而不是GoTo,你使用:(标签)。当你有:S(label)(成功/true时的goto标签)和:F(label)(失败/false时的goto标签)并且你在一行中使用这些函数检查某些条件或读取文件时,谁还需要if呢?所以这个表述是:

H = INPUT :F(end)

将从文件或控制台读取下一行,如果读取失败(因为到达EOF或任何其他原因),将转到标签“end”。

然后是$ sign操作符。它将使用变量中的值作为变量名。所以:

ANIMAL = 'DOG'
DOG = 'BARK'
output = $ANIMAL

将在控制台上显示'BARK'值。因为这还不够奇怪:

$DOG = 'SOUND'

将创建一个名为BARK的变量(参见上面分配给DOG的值),并赋予它一个“SOUND”的值。

你看得越多,情况就越糟。我所发现的关于SNOBOL的最好的陈述(来自链接文本)是“该语言的强大功能及其相当惯用的控制流特性使得编写后的SNOBOL4代码几乎不可能阅读和理解。”

可能已经说过了(也许这对一些人来说并不奇怪),但我认为这很酷:

在Javascript中,声明函数接受的参数只是为了方便程序员。通过函数调用传递的所有变量都可以通过关键字“arguments”访问。所以下面会提醒“world”:

<script type="text/javascript">

function blah(){
alert(arguments[1]);
}

blah("hello", "world");

</script> 

注意,虽然这些参数看起来像是存储在数组中(因为您可以以与数组元素相同的方式访问对象属性),但事实并非如此。arguments是一个对象,而不是数组(因此,它们是存储在数值索引下的对象属性),如下例所示(typeOf函数来自Crockford的JavaScript补救页面):

argumentsExample = function(){
    console.log(typeOf(arguments));

    anArray = [];
    console.log(typeOf(anArray));

    anObject = {};
    console.log(typeOf(anObject));
}

function typeOf(value) {
    var s = typeof value;
    if (s === 'object') {
        if (value) {
            if (typeof value.length === 'number' &&
                    !(value.propertyIsEnumerable('length')) &&
                    typeof value.splice === 'function') {
                s = 'array';
            }
        } else {
            s = 'null';
        }
    }
    return s;
}

argumentsExample("a", "b");

我不知道这是否是真的,但我们偶然发现VS FORTRAN(66或77)不支持递归。递归是偶然的,我们的默认F77支持它很漂亮,但当我们把源代码IBM - Whatta混乱。

特点:Bash, Korn shell (ksh93)和Z shell都允许使用带或不带美元符号的变量下标数组:

array[index]=$value
array[$index]=$value

加上美元符号,会得到10000的期望值:

unset array
for i in {1..10000}
do
    ((array[$RANDOM%6+1]++))
done
unset total
for count in ${array[@]}
do
    ((total += count))
done
echo $total

陌陌性:如果你从RANDOM中移除美元符号,总数将随机变化,甚至大于10000。

类似地,这将产生3而不是2:

a=1; ((r[a++]++)); echo $a

你不能在这里用美元符号,因为这是赋值运算(a在lhs上)虽然你可以用间接的方法,但是双重求值还是会发生。

原因:对于美元符号,变量展开在算术求值之前执行,因此只执行一次。如果没有美元符号,它将执行两次,一次是计算查找的索引,另一次是计算赋值的索引(因此,实际上,循环中第一步的赋值可能看起来像array[4] = $array[6] + 1,这完全打乱了数组)。

Perl文件句柄样式的操作符调用。

一开始是有的

print "foo", "bar", "baz"; # to stdout
print STDERR "foo", "bar", "baz";

注意没有逗号,这样你就知道这是要打印到的文件句柄,而不是要以字符串化方式打印的文件句柄。这是一个肮脏的黑客。

语言升级开始了,他们制作了适当的OO文件句柄,并将x FOO y, z, abc转换为FOO->x(y, z, abc)。有点可爱。相同的print语句有效地运行

STDERR->print("foo", "bar", "baz");

大多数情况下,当你错过一个逗号时,或者尝试运行hashof $a, $b, $c(不带括号的子例程调用)之类的东西时,你会注意到这一点,而忘记从它的实用程序包中将hashof函数导入到你的命名空间中,你会得到一个奇怪的错误消息,关于“无法通过字符串$a的包内容调用方法'hashof'”。