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

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


当前回答

JavaScript是面向对象的,对吧?因此,在文字字符串和数字上运行方法应该是可行的。比如"hello". touppercase()和3.toString()。第二个是语法错误,为什么?因为解析器期望一个数字后面跟一个点是一个浮点字面值。这不是WTF, WTF是你只需要再加一个点就可以了:

3..toString()

原因是字面上的3。被解释为3.0,3.0. tostring()工作正常。

其他回答

PHP

PHP对实例变量和方法的重载处理不一致。考虑:

class Foo
{
    private $var = 'avalue';

    private function doStuff()
    {
        return "Stuff";
    }

    public function __get($var)
    {
        return $this->$var;
    }

    public function __call($func, array $args = array())
    {
        return call_user_func_array(array($this, $func), $args);
    }
}

$foo = new Foo;
var_dump($foo->var);
var_dump($foo->doStuff());

转储$var是有效的。即使$var是私有的,__get()也会被任何不存在或不可访问的成员调用,并返回正确的值。这不是doStuff()的情况,它失败于:

Fatal error: Call to private method Foo::doStuff() from context ”.”

我认为其中很多都是在c风格的语言中工作的,但我不确定。

Pass a here document as a function argument: function foo($message) { echo $message . "\n"; } foo(<<<EOF Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc blandit sem eleifend libero rhoncus iaculis. Nullam eget nisi at purus vestibulum tristique eu sit amet lorem. EOF ); You can assign a variable in an argument list. foo($message = "Hello"); echo $message; This works because an assignment is an expression which returns the assigned value. It’s the cause of one of the most common C-style bugs, performing an assignment instead of a comparison.

Python

在Python中,可变的默认函数参数会导致意想不到的结果:

def append(thing, collection=[]):
    collection.append(thing)
    return collection

print append("foo")
# -> ['foo']
print append("bar")
# -> ['foo', 'bar']
print append("baz", [])
# -> ['baz']
print append("quux")
# -> ['foo', 'bar', 'quux']

空列表是在函数定义时初始化的,而不是在调用时初始化的,因此对它的任何更改都会在函数调用之间保持不变。

MySQL的大小写敏感性

MySQL有非常不寻常的区分大小写的规则:表区分大小写,列名和字符串值不区分大小写:

mysql> CREATE TEMPORARY TABLE Foo (name varchar(128) NOT NULL);
DESCRIBE foo;
ERROR 1146 (42S02): Table 'foo' doesn't exist
mysql> DESCRIBE Foo;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| name  | varchar(128) | NO   |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+
1 row in set (0.06 sec)
mysql> INSERT INTO Foo (`name`) VALUES ('bar'), ('baz');
Query OK, 2 row affected (0.05 sec)

mysql> SELECT * FROM Foo WHERE name = 'BAR';
+------+
| name |
+------+
| bar  |
+------+
1 row in set (0.12 sec)

mysql> SELECT * FROM Foo WHERE name = 'bAr';
+------+
| name |
+------+
| bar  |
+------+
1 row in set (0.05 sec)

在SQL Server中,如果你在生产代码中使用select *,你可能会遇到一个令人讨厌的意外。无论如何,使用select *并不被认为是一个好的实践,但了解一些有趣的行为是很好的。

参见问题“select * from table”vs“select colA,colB etc from table”在SqlServer2005中有趣的行为了解更多细节

在Bash中,变量可以显示为标量和数组:

$ a=3
$ echo $a
3
$ echo ${a[@]}    # treat it like an array
3
$ declare -p a    # but it's not
declare -- a="3"
$ a[1]=4          # treat it like an array
$ echo $a         # acts like it's scalar
3
$ echo ${a[@]}    # but it's not
3 4
$ declare -p a
declare -a a='([0]="3" [1]="4")'
$ a=5             # treat it like a scalar
$ echo $a         # acts like it's scalar
5
$ echo ${a[@]}    # but it's not
5 4
$ declare -p a
declare -a a='([0]="5" [1]="4")'

KSH做同样的事情,但是使用排版而不是声明。

当你在zsh中这样做时,你得到的是子字符串赋值而不是数组:

$ a=3
$ a[2]=4          # zsh is one-indexed by default
$ echo $a
34
$ a[3]=567
$ echo $a
34567
$ a[3]=9
$ echo $a
34967
$ a[3]=123         # here it overwrites the first character, but inserts the others
$ echo $a
3412367
$ a=(1 2 3)
$ echo $a
1 2 3              # it's an array without needing to use ${a[@]} (but it will work)
$ a[2]=99          # what about assignments?
$ echo $a
1 99 3

哈哈!

整个语言本身。虽然不完全是WTF的事情,但我从来没有遇到过一种语言在我的脑海中以一种刺耳的卡通声音播放。我以前也从来没有看过代码并想要惊呼“啊啊啊啊可爱!”

这个程序显示数字1-10并终止

HAI
CAN HAS STDIO?
IM IN YR LOOP UPPIN YR VAR TIL BOTHSAEM VAR AN 10
    VISIBLE SUM OF VAR AN 1
IM OUTTA YR LOOP
KTHXBYE

Ruby

时间。Parse经常假装解析没有失败,而是返回现在

require 'time'

Time.parse '2000-01-01 12:00:00'
# -> 2000-01-01 12:00:00 +0100

Time.parse '2000-99-01 00:00:00'
# -> ArgumentError: argument out of range ...

Time.parse 'now'
# -> 2010-08-13 21:26:13 +0200

Time.parse 'yesterday'
# -> 2010-08-13 21:26:18 +0200

Time.parse 'billion years ago'
# -> 2010-08-13 21:26:37 +0200