最奇怪的语言功能

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

请每个答案只有一个特征。

496819 次浏览

我对此有点纠结:

1;

在perl中,模块需要返回真正

在我看来,能够在C#中将范围整数转换为枚举非常奇怪。想象一下这个枚举:

enum Colour{Red = 1,Green = 2,Blue = 3}

现在,如果你写:

Colour eco;eco = (Colour)17;

编译器认为这很好。运行时也是如此。

查看这里了解更多详情。

在c

a[i++] = i;

它编译,但它很少做你认为它应该做的事情。优化更改导致产生截然不同的结果。它在不同的平台上运行不同。

然而,编译器对此非常满意。

C和C++的三角图。

int main() {printf("LOL??!");}

这将打印LOL|,因为三元组??!被转换为|

脑残语言.真的是!

我为客户端(用于实验驱动自定义硬件)编写了一种编程语言,其中包含一些自定义类型(Curl、Circuit、…),每个类型只有2个值。它们可以隐式转换为布尔值,但是(应客户端的请求)可以在运行时更改此类类型常量的确切布尔值。

例如:Curl类型有2个可能的值:CW和CCW(顺时针和逆时针)。在运行时,您可以通过简单的赋值语句更改布尔值:

ccw := true

因此,您可以更改这些类型的所有值的布尔含义。

在ruby/python/c中,您可以像这样连接字符串:

a = "foo" "bar"print a # => "foobar"

在C中,数组可以像这样索引:

a[10]

这很常见。

然而,鲜为人知的形式(确实有效!)是:

10[a]

意思和上面一样。

我肯定会给Perl提供多个可怕的例子的荣誉:

if(!$#var)

if($mystring =~ m/(\d+)/) {

动作脚本3:

当一个对象被其接口使用时,编译器无法识别从Object继承的方法,因此:

IInterface interface = getInterface();interface.toString();

给出编译错误。解决方法是转换为对象

Object(interface).toString();

PHP:

.+运算符。它有其合理的解释,但仍然"a" + "5" = 5似乎很尴尬。

Java(以及IEEE754的任何实现):

System.out.println(0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1);

输出0.9999999999999999

Algol按名称传递(使用C语法说明):

int a[3] = { 1, 2, 3 };int i = 1;
void f(int j){int k;k = j;  // k = 2i = 0;k = j;  // k = 1 (!?!)}
int main(){f(a[i]);}

PHP对字符串中数值的处理。有关详细信息,请参阅之前对另一个问题的回答,但简而言之:

"01a4" != "001a4"

如果您有两个包含不同数量字符的字符串,则不能认为它们相等。前导零很重要,因为这些是字符串而不是数字。

"01e4" == "001e4"

PHP不喜欢字符串。它正在寻找任何借口将您的值视为数字。稍微更改这些字符串中的十六进制字符,突然PHP决定这些不再是字符串,它们是科学记数法中的数字(PHP不在乎您使用了引号),它们是等价的,因为数字忽略了前导零。为了加强这一点,您会发现PHP还评估"01e4" == "10000"为真,因为这些是具有等价值的数字。这是记录在案的行为,只是不太明智。

在C或C++中,您可以使用宏获得很多乐趣。例如

#define FOO(a,b) (a+b)/(1-a)

如果FOO(bar++,4)被传入,它将增加a两次。

与其说是一个奇怪的特性,不如说是一个从类型安全的角度来看非常恼人的特性:C#中的数组协方差。

class Foo { }class Bar : Foo { }class Baz : Foo { }
Foo[] foo = new Bar[1];foo[0] = new Baz(); // Oh snap!

这是继承(双关语故意)从Java,我相信。

弱打字,一般来说。

C:

printf("%c\n", 'a' + 3);

PHP:

echo 5 + "3";

还有很多其他语言。

INTERCAL可能是最奇怪的语言特性的最佳汇编。我个人最喜欢的是来自语句,它(几乎)与GOTO相反。

COMEOF的意思正好相反GOTO,它可以采取执行从代码中的任意点状态到COMEfrom语句。中的点发生状态转移的代码通常作为参数给出来自。转移是否发生在指令之前或之后指定传输点取决于使用的语言。取决于使用的语言,多个COMEFROMs指向同一个出发点可能是无效的,不确定的,以某种定义的方式执行优先,甚至导致并行或所看到的其他并发执行在Threaded Intercal中。一个简单的例子的“COMEOF x”语句是一个标签x(不需要是实际位于其附近的任何地方对应的COMEfrom)充当“活板门”。当代码执行时到达标签控制就通过了的声明来自。这的效果是主要用于调试(和了解的控制流程程序)非常困难,因为标签附近没有标明控制会神秘地跳到程序的另一个点。

我想说Python的整个空格是我最大的WTF功能。没错,一段时间后你或多或少会习惯它,现代编辑器使它变得容易处理,但即使在过去一年中大部分时间都是Python开发之后,我仍然相信这是一个坏主意。我已经阅读了它背后的所有理由,但老实说,它妨碍了我的工作效率。不是很多,但它仍然是马鞍下的毛刺。

编辑:从评论中看到,有些人似乎认为我不喜欢缩进代码。这是错误的判断。不管使用什么语言,也不管是否被迫,我的代码都是缩进的。我不喜欢的是缩进定义了一行代码所在的块。因此我更喜欢显式分隔符,其中一个原因是,显式分隔符使剪切和粘贴代码更容易。

例如,如果我有一个缩进了4个空格的块,并将其粘贴在缩进了8个空格的块的末尾,我的编辑器(所有编辑器?)不知道粘贴的代码是属于8个空格的块还是外部块。OTOH,如果我有显式分隔符,很明显代码属于哪个块以及应该如何(重新)缩进-它通过智能地寻找块分隔符来做到这一点。

编辑2:一些提供评论的人似乎认为这是一个我讨厌的特性,或者我认为这使得python成为一种糟糕的语言。同样,事实并非如此。虽然我不太喜欢它,但这与主题无关。问题是关于奇怪语言特性的,我认为这很奇怪,因为它是非常非常少(但>0)语言使用的东西。

在JavaScript中:

 '5' + 3 gives '53'

鉴于

 '5' - 3 gives 2

在我看来,这在C++是不允许的:

class A {public:virtual string foo(){return "A::foo";}};
class B : public A {public:virtual string foo(){return "B::foo";}};
int main () {B* b = new B();// In my opinion the following should not be allowedcout << b->A::foo() << endl;  // Will print "A::foo"}

这似乎是正确的,但这意味着如果不允许子类的用户调用原始方法而不是新方法,您就无法覆盖方法。

只需考虑一个集合的子类,在将元素添加到集合本身时,您希望增加元素的数量。

一个合乎逻辑的解决方案是在添加元素之前覆盖add()方法以增加计数器,但是新集合的用户可以使用旧方法向其添加元素,从而绕过您的增量并导致您的元素计数器与集合的实际元素数不一致。

这在Java是不可能的。

不知道它是否可以被认为是一种语言功能,但是,C++几乎所有与模板相关的编译器错误每天都会向世界各地的许多C++程序员提供相当数量的WTF:)

不是真正的语言特性,而是一个实现缺陷:一些早期的Fortran编译器通过使用常量池来实现常量。所有参数都通过引用传递。如果你调用一个函数,例如。

f(1)

编译器会将常量池中常量1的地址传递给函数。如果您为函数中的参数赋值,您将在程序中全局更改值(在本例中为1的值)。引起一些头疼。

对于那些不知道的人来说,bc是一种“任意精度计算器语言”,我经常使用它进行快速计算,特别是当涉及的数字很大时($是提示符):

$ bc -lq12^34520774466823273785598434446955827049735727869127052322369317059031795\19704325276892191015329301807037794598378537132233994613616420526484\93077727371807711237016056649272805971389591721704273857856298577322\13812114239610682963085721433938547031679267799296826048444696211521\30457090778409728703018428147734622401526422774317612081074841839507\864189781700150115308454681772032

bc很长一段时间以来一直是标准Unix命令

现在是“WTF功能”。这来自man bc(强调我的):

退出:当读取退出语句时,bc处理器终止,无论在哪里找到退出语句。例如,如果(0==1)退出将导致bc终止。

停止:停止语句(扩展)是一个执行的语句导致bc处理器仅在执行时退出。例如,如果(0==1)停止不会导致bc终止,因为停止没有执行。

在早期版本的Visual Basic中,没有“返回”语句的函数只是“返回无”,没有任何类型的编译器警告(或错误)。

这导致了最疯狂的调试会话,当时我不得不每天处理这种语言。

在Python中:

>>> x=5>>> 1<x<10True>>> 1<x<3False

不是WTF,而是一个有用的功能。

我知道的最大的体面和奇怪的编程语言集合(今天1313),你会在这里找到:http://99-bottles-of-beer.net/准备好看到真正奇怪的东西;-)每个人都有自己的选择

Perl的许多内置变量:

  • $#-没有评论!
  • $0$$$?-就像同名的shell变量一样
  • $&$'-奇怪的匹配变量
  • $"$,-列表和输出字段分隔符的奇怪变量
  • $!-像errno作为一个数字,但strerror(errno)作为一个字符串
  • $_-隐身变量,总是使用,从未见过
  • $#_-最后一个子程序参数的索引号…可能
  • @_-当前函数的(非)名称…可能
  • $@-最后引发的异常
  • %::-符号表
  • $:$^$~$-$=-与输出格式有关
  • $.$%-输入行号,输出页码
  • $/$\-输入和输出记录分隔符
  • $|-输出缓冲控制器
  • $[-将数组基数从0基更改为1基,再更改为42基:呼呼!
  • $}-什么都没有,奇怪的是!
  • $<$>$($)-真实有效的UID和GID
  • @ISA-当前包的直接超类的名称
  • $^T-脚本启动时间,以纪元秒为单位
  • $^O-当前操作系统名称
  • $^V-这是什么版本的Perl

还有更多这些来自哪里。阅读完整列表这里

我不敢说XML是一种编程语言,但它不是贴近我们的心吗?:-)

在我看来,XML中最奇怪的特性是以下是一个格式良好的文档:

<_....></_....>

这是允许连续点的NT-Name的词法定义

两个字:多重继承。这毫无意义,只会制造麻烦。

编辑-我指的是C++中的MI,而不是Java和其他语言中的Mixins等。

这里有一大堆奇怪的C特性:http://www.steike.com/code/useless/evil-c/

我曾经写过一种编程语言,它有一个“strfy”运算符:

"hello world"?# => "wdo rlholle"

有用吧?

Oracle有几个SQL的WTF问题。

  1. Oracle将空字符串处理为null。

  2. 在“<>”比较中处理空值。

    create table wtf (key number primary key, animal varchar2(10));insert into wtf values (1,'dog');insert into wtf values (2,'');insert into wtf values (3,'cat');select * from wtf where animal <> 'cat';

The only row returned is the (1,'dog') row.

其他奇怪的事情:

在C++重写虚拟方法会隐藏该方法的所有其他重载。Java不会发生这种情况。这非常烦人。示例:http://codepad.org/uhvl1nJp

在C++如果一个基类有公共个虚方法foo(),一个子类有私人个方法foo(),这个私有方法会覆盖另一个!通过这种方式,您可以通过将子类对象指针转换为超类对象指针来调用类之外的私有方法。这不应该是可能的:这违反了封装。新方法不应该被视为旧方法的覆盖。例子:http://codepad.org/LUGSNPdh

在php您可以定义函数来接受类型化参数(例如,作为某个接口/类的子类的对象),烦人的是,这样您就不能在这种情况下使用NULL作为实际参数值。示例:http://codepad.org/FphVRZ3S

我最讨厌的功能是任何包含条件逻辑的配置文件语法。这种东西在Java世界很普遍(蚂蚁、Maven等。你知道你是谁!)。

您最终只能使用c**p语言进行编程,并且具有有限的调试和有限的编辑器支持。

如果您在配置中需要逻辑,那么用真实语言编写配置的“Pythonic”方法要好得多。

在java中(这是一个导致赋值的if语句)

result = (Boolean condition) ? (if Boolean is true) : (if Boolean is false);

data Nat = Z|S Nat deriving ShownattoInt Z = 0nattoInt (S a) = 1 + nattoInt a
buildNat 0 = ZbuildNat a  =  S (buildNat (a - 1))

在Haskell中……我仍然不太明白这是如何定义自然数的(我完全理解这个理论:-p)

FORTRAN不是一个真正的WTF时刻,而是一个“为什么我需要输入所有这些垃圾时刻”

IF(12 .gt. 11) THEN// Do some magicENDIF

“. gt.”把我搞晕了,当我玩了一会儿语言,直到我意识到它是“>”符号。哦,我多么喜欢不是生物专业的人,不得不每天涉足这种废话

INTERCAL(AND,OR和XOR)中的一元运算符。

作为一个NHibernate爱好者,当我从Smalltalk听到become时,我很激动。

a become: b

它从字面上将a对象更改为b,这使得编写延迟初始化代理变得微不足道,因为所有对a的引用现在都将引用b。非常整洁!

我认为这是一种奇怪的语言特征,因为据我所知,没有其他语言具有这种能力。

在JavaScript中:

2 == [2]
// Even stranger2 == [[[2]]]
// And down-right nuttyvar a = { "abc" : 1 };a[[[["abc"]]]] === a["abc"]; // this is also true

幸运的是,stackoverflow.com的好心人向我解释了整件事:为什么JavaScript中的2==[2]?

ANSISQL中nulls的三值逻辑。

Java;使所有对象实例成为互斥锁。

我一直想知道为什么最简单的程序是:

class HelloWorldApp {public static void main(String[] args) {System.out.println("Hello World!");}}

而它可能是:

print "Hello World!"

也许这首先是为了吓唬计算机科学专业的学生…

Java:

int[] numbers() {return null;}

可以写成:

int numbers() [] {return null;}

JavaScript真值表:

''        ==   '0'           // false0         ==   ''            // true0         ==   '0'           // truefalse     ==   'false'       // falsefalse     ==   '0'           // truefalse     ==   undefined     // falsefalse     ==   null          // falsenull      ==   undefined     // true" \t\r\n" ==   0             // true

图片来源:Doug Crockford

来自是我见过的最奇怪,也可能是最无用的语言特性。

亚军将是三元运算符,因为它违反了优化规则#1。它造成的伤害大于它解决的问题。它造成的伤害更大,因为它使代码可读性降低。

不是真正的语言功能,但有趣/令人敬畏的功能使用是达夫的装置

Java的访问修饰符对我来说是最近的WTF(因为我必须学习一点)。

显然包比类层次结构更亲密。我不能定义对子类可见但对包中的其他类不可见的方法和属性。为什么我要将一个类的内部共享给其他类?

但是我可以定义对包内的每个类可见的属性和方法,但对包外的子类不可见。

不管我怎么想,我还是看不出其中的逻辑。切换访问修饰符,让protected表现得像在C++中一样工作,保持包的私有修饰符不变,这是有意义的。现在它没有了。

回想起来,FORTRAN的计算goto非常奇怪。维基百科告诉我一些BASIC超过了它。

另一个著名的最爱是Algol 60的叫名字参数传递。

Perl充满了奇怪但简洁的特性。

if可以在语句之前或之后使用,如下所示:

print "Hello World" if $a > 1;if ($a > 1) { print "Hello World"; }

foreach也是如此:

print "Hello $_!\n" foreach qw(world Dolly nurse);

在Perl中,您可以:

my $test = "Hello World";substr($test, 0, 5) = "Goodbye";
print $test;

这在其他语言中可能吗?

我很惊讶你可以通过修改Perl中的@ISA数组来更改类的继承链。

package Employee;our @ISA = qw(Person);# somwhere far far away in a package long ago@Employee::ISA = qw(Shape);# Now all Employee objects no longer inherit from 'Person' but from 'Shape'

我一直想知道这个函数在JavaCore库的Math类中的用途:

static double expm1(double x);  // Returns e^x - 1.

我喜欢这种事情在JavaScript中很好的事实:

var futureDate = new Date(2010,77,154);alert(futureDate);

结果日期为2010年第0个月的第0天(即2016年11月1日)起77个月又154天

我很惊讶没有人提到Visual Basic的7循环结构。

For i As Integer = 1 to 10 ... NextWhile True ... End WhileDo While True ... LoopDo Until True ... LoopDo ... Loop While TrueDo ... Loop Until TrueWhile True ... Wend

因为在你的条件前面粘贴一个!方式太复杂了!

C的许多名称空间:

typedef int i;
void foo(){struct i {i i;} i;i: i.i = 3;printf( "%i\n", i.i);}

或与字符:

typedef char c;
void foo(){struct c {c c;} c;c: c.c = 'c';printf( "%c\n", c.c);}

交替:在许多语言中的事物之间交替:

boolean b = true;for(int i = 0; i < 10; i++)if(b = !b)print i;

乍一看:b怎么可能真的不等于它自己!?这个函数只打印奇数

Common Lisp的format函数可以选择将数字打印为罗马数字。

在INTERCAL中,这是您将获得的唯一输出形式。

有趣的自动装箱和Java中的整数缓存:

Integer foo = 1000;Integer bar = 1000;
foo <= bar; // truefoo >= bar; // truefoo == bar; // false
//However, if the values of foo and bar are between 127 and -128 (inclusive)//the behaviour changes:
Integer foo = 42;Integer bar = 42;
foo <= bar; // truefoo >= bar; // truefoo == bar; // true

补充说明

快速浏览Java源代码将出现以下内容:

/*** Returns a <tt>Integer</tt> instance representing the specified* <tt>int</tt> value.* If a new <tt>Integer</tt> instance is not required, this method* should generally be used in preference to the constructor* {@link #Integer(int)}, as this method is likely to yield* significantly better space and time performance by caching* frequently requested values.** @param  i an <code>int</code> value.* @return a <tt>Integer</tt> instance representing <tt>i</tt>.* @since  1.5*/public static Integer valueOf(int i) {if (i >= -128 && i <= IntegerCache.high)return IntegerCache.cache[i + 128];elsereturn new Integer(i);}

备注:IntegerCache.high默认为127,除非由属性设置。

自动装箱的情况是,foo和bar都是从缓存中检索到的同一个整数对象,除非显式创建:例如foo = new Integer(42),因此在比较引用相等性时,它们将是true而不是false。比较整数值的正确方法是使用.equals;

我最喜欢的C++之一是“公共抽象具体内联析构函数”:

class AbstractBase {public:virtual ~AbstractBase() = 0 {}; // PACID!
virtual void someFunc() = 0;virtual void anotherFunc() = 0;};

我在有效C++中从Scott Meyers那里偷来的。看到一个既是纯虚拟(通常意味着“抽象”)又内联实现的方法看起来有点奇怪,但这是我发现的确保对象被多态破坏的最好和最简洁的方法。

我最喜欢的C语言怪异是5[“Hello World”],但由于已经发布了,我最喜欢的怪异是Windows版本化结构初始化黑客:

void someWindowsFunction() {BITMAPINFOHEADER header = {sizeof header};
/* do stuff with header */}

那一条微妙的线完成了以下工作:

  1. 声明一个BITMAPINFOHEADER结构
  2. 简洁地设置结构的“size”成员,而无需硬编码大小常量(因为许多Window结构,包括BITMAPINFOHEADER,遵循将结构的大小指定为第一个成员的约定}
  3. 声明结构的版本(因为许多Windows结构,包括BITMAPINFOHEADER,按照结构定义仅追加的约定,通过声明的大小标识其版本)
  4. 清除结构的所有其他成员(结构未完全初始化时的C标准行为)。

一个意想不到的特性是枚举def列表中的尾随逗号和C、C#、Ruby等中的数组初始化列表。

string[] foods = { "tofu", "grits", "cabbage", }
public enum ArtPeriod {Modern,Romantic,Dada,}

在Javascript中,我认为以下内容是等价的:

a['title'] = "Syntactic sugar is good for yr teeth.";a.title = "Syntactic sugar is good for yr teeth.";

在fortran中(肯定是77,也许在95中也是如此),以#0到#1开头的未声明变量和参数(“in”组)将是#2,所有其他未声明的变量和参数将是#3来源)。这与“某些情况下可选的空格”相结合,导致了最著名的错误之一。

正如Fred Webb在1990年的alt.folklore.computers中所说:

1963年夏天,我在NASA工作。我工作的小组在任务控制中心的电脑上做初步工作系统和程序。我的办公室伙伴的工作是测试一个水星期间使用的轨道计算程序通过它运行一些已知答案的测试数据,他是得到的答案很接近,但不够准确。所以,他开始寻找算法中的数值问题,检查确保他的测试数据是正确的,等等。

几个星期后,没有结果,他遇到了DO格式为:

DO 10 I=1.10

此语句被编译器(正确地)解释为:

DO10I = 1.10

程序员的意图很明确:

DO 10 I = 1, 10

.更改为,后,程序结果正确期望的准确性。显然,程序的答案是对于亚轨道水星飞行来说“足够好”,所以没有人怀疑bug,直到他们试图获得更高的准确性后来的轨道和月球飞行。据我所知,这个特殊的bug从未因太空飞行的任何实际失败而受到指责,但这里的其他细节似乎足够接近,我确信这起事件是DO故事的来源。

我认为这是一个很大的WTF,如果DO 10 I被认为是DO10I,反过来,因为隐式声明被认为是类型REAL。这是一个很棒的故事。

另一个C主义。

int i= 0;while( i != 12 ) {/* Some commenti += 1;/* Another comment */}

为什么它不起作用?Lint会告诉你。然而,C编译器通常会轻率地忽略这一点。我也是。

这是一个真正的WTF时刻,当我发现什么是错的。

这里有一个我觉得很奇怪:

在C/C++中,您可以拥有任意数量的分号,至少在MSC++:

int main(void){cout<<"Hello World";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;return 0;;;;;;;;;;;;;;;;;;;;;;;}

PHP中的变量

PHP中的一个奇怪功能,允许您从其他变量的内容(警告、未经测试的代码)创建和分配变量:

$a = 'Juliet';$$a = 'awesome'; // assigns a variable named $Juliet with value 'awesome'
echo '$a';       // prints Julietecho '${$a}';    // prints awesomeecho '$Juliet';  // prints awesome

好吧,假设我们有这样的东西:

$bob = 'I\'m bob';$joe = 'I\'m joe';$someVarName = 'bob';$$someVarName = 'Variable \'bob\' changed';

各种间接的乐趣怎么样:

$juliet = 'Juliet is awesome!';$func = 'getVarName'
echo '${$func()}'; // prints 'Juliet is awesome!'
function getVarName() { return 'juliet'; }

我很惊讶没有人提到大多数类C语言中非常丑陋的Switch case实现

switch (someInt) {case 1:case 2: System.out.println("Forgot a break, idiot!");case 3: System.out.println("Now you're doing the wrong thing and maybe need hours to find the missing break muahahahaha");break;default: System.out.println("This should never happen -,-");}

好消息是新语言正确地实现了它。

在C#中,为什么这是不合法的?

public class MyClass<T>where T: Enum{
}

能够在Enum上添加扩展方法以及Func会非常酷,其中T将是您正在扩展的枚举,以便您可以在该枚举上获得类型推断。

回复评论:是的,你可以扩展一个实际的枚举,但这里有区别:

你可以这样做:

public static void DoSomethingWithEnum(this Enum e){//do whatever}

但是,如果您想使用与枚举类型相同的方法获取Func怎么办:

public static void DoSomethingWithEnum<T>(this T e, Func<T,bool> func )where T: Enum{//do whatever}

这样,您可以像这样调用您的方法:

DayOfWeek today = DayOfWeek.Monday;today.DoSomethingWithEnum(e => e != DayOfWeek.Sunday);

或者类似的东西。你明白的…这是不可能的,我不知道为什么…

Perl的sub没有真正的参数列表,只有@_数组。此外,sub自动平坦传递给它的参数。

我不明白为什么这是一个持久的功能;这反映了我多年前在TI-86 BASIC上做的工作,因为该语言的功能不够。

在Forth中,任何不包含空格的东西都可以是标识符(包含空格的东西需要一些工作)。解析器首先检查这个东西是否被定义,在这种情况下,它被称为,如果没有,检查它是否是一个数字。没有关键字。

无论如何,这意味着可以重新定义一个数字来表示其他东西:

: 0 1 ;

这将创建0,由1组成,无论执行时是什么。反过来,它可能导致以下结果:

0 0 + .2 Ok

另一方面,定义可以接管解析器本身——完成的事情这意味着Forth程序实际上可以在中途变成完全不同语言的程序。事实上,这是Forth中推荐的编程方式:首先你编写你想要解决问题的语言,然后你解决问题。

在JavaScript中,以下结构

return{id : 1234,title : 'Tony the Pony'};

返回#0是一个语法错误,原因是在return之后的换行符上偷偷摸摸地隐式插入了分号。不过,以下操作与您预期的一样:

return {id : 1234,title : 'Tony the Pony'};

更糟糕的是,这个也有效(至少在Chrome):

return /**/{id : 1234,title : 'Tony the Pony'};

这是同一问题的一个变体,它不会产生语法错误,只是默默地失败:

return2 + 2;

大约20年前,当我最后一次涉足MUMPS时,实现有一些奇怪的局限性。当主机MUMPS变得越来越流行时,MUMPS传统上是一种自托管语言:计算机语言、操作系统和数据库在一个包中。

MUMPS本质上是关于它的数据库。本质上,一个巨大的多维哈希表,由一个B*树支持,可以非常快速地访问。语言和数据库之间也没有任何障碍:如果你想在那里存储一些东西,你只需在变量前缀一个符号,表明它将被持久化到后备存储。

另一方面,文件系统几乎不存在,对它的支持更少。人们唯一能做的就是从文件将程序加载到内存中,然后将内存中的任何内容发送回文件。加载前最好清除缓冲区,否则它会与先存在的东西混合在一起。

因此,考虑到它的自托管特性和极端敌对的文件系统,人们可能会想知道这些程序是如何编辑的。事实上,编辑器是用MUMPS本身编写的-那么编辑器如何将程序存储在内存中而不会自行写入呢?

好吧,诀窍是能够将变量的内容作为源代码执行。然后,编辑器将自己加载到变量中,在其中执行自己,清除内存,然后在内存中加载、保存和编辑文件,一直从变量中执行。

除此之外,所有命令都可以缩写为它们的第一个字母(除了Z命令,缩写为两个字母,主要处理文件系统),以及像IFI)设置了一个变量,然后ELSEE)参考了这个变量--当然,可以被任何干预的I或程序本身覆盖。再想一想,我认为整个语言都是一个WTF。然而,它有一种奇怪的吸引力。

在C:

warning C4013: 'myfunc' undefined; assuming extern returning int

我记得由于某种原因没有看到警告(在一些遗留代码中太多了?)并且困惑于为什么从int转换会导致使用非int返回函数的编译器错误。

编译器假设这样的东西是相当出乎意料的。

在JavaScript中,第一次看到!!a(作为转换为布尔值的一种方式)。

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

一开始,有

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

请注意这里明显缺少逗号,这样你就知道这是一个要打印到的文件句柄,而不是一个要以字符串方式打印的文件句柄。

语言升级滚动,他们制作适当的OO文件句柄并将x FOO y, z, abc变成FOO->x(y, z, abc)。有点可爱。相同的打印语句有效地运行

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

大多数情况下,当您错过逗号时,或者尝试运行类似于hashof $a, $b, $c(不带括号的子程序调用)并忘记将hashof函数从其实用程序包导入到您的命名空间时,您会注意到这一点,并且您会收到一条奇怪的错误消息“Can't call方法'hashof'via包'内容字符串$a'”。

在JavaScript中:

alert(111111111111111111111) // alerts 111111111111111110000

这对我在JSON中来回传递的一些64位密钥非常有害。

VBScript的块:

With xml.appendChild(xml.createElement("category")).setAttribute("id",id).setAttribute("keywords",keywords)With .appendChild(xml.createElement("item")).setAttribute("count",count).setAttribute("tip",tip).appendChild(xml.createTextNode(text))End WithEnd With

VBScript的日期/时间文字(为什么这仍然如此罕见?):

mydate = #1/2/2010 5:23 PM#
If mydate > #1/1/2010 17:00# Then ' ...

编辑:日期文字是相对的(那么它们在技术上是文字吗?):

mydate = #Jan 3# ' Jan 3 of the current year

VB.NET,因为它是编译的,不支持相对日期文字。仅支持日期或仅支持时间文字,但缺失的时间或日期被假定为零。

编辑[2]:当然,有一些奇怪的角落案例提出了相对日期…

mydate = #Feb 29# ' executed on 2010-01-05, yields 2/1/2029

在Python中:

>>> a[0] = "hello"NameError: name 'a' is not defined>>> a[0:] = "hello"NameError: name 'a' is not defined>>> a = []>>> a[0] = "hello"IndexError: list assignment index out of range>>> a[0:] = "hello">>> a['h', 'e', 'l', 'l', 'o']

这些切片赋值也会给出相同的结果:

a[:] = "hello"a[42:] = "hello"a[:33] = "hello"

javascript中的几十种东西可以让你的眼睛流泪。

局部变量的作用域,只是一个简单的例子:

function foo(obj){for (var n = 0; n < 10; n++){var t;        // Here is a 't'...}t = "okay";     // And here's the same 't'}

在Bash中,变量可以看起来既是标量又是数组:

$ a=3$ echo $a3$ echo ${a[@]}    # treat it like an array3$ declare -p a    # but it's notdeclare -- a="3"$ a[1]=4          # treat it like an array$ echo $a         # acts like it's scalar3$ echo ${a[@]}    # but it's not3 4$ declare -p adeclare -a a='([0]="3" [1]="4")'$ a=5             # treat it like a scalar$ echo $a         # acts like it's scalar5$ echo ${a[@]}    # but it's not5 4$ declare -p adeclare -a a='([0]="5" [1]="4")'

ksh做同样的事情,但使用typeset而不是declare

当你在zsh中执行此操作时,你会得到子字符串赋值而不是数组:

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

在Common Lisp中,零维数的数组很奇怪,自然,它们具有读取语法。

? (aref #0A5)5

这是一个奇怪的特性的缺乏:Python没有#0语句(尽管存在变通方法)。

APL(除了所有),在一行中编写任何程序的能力。

例如康威的生命游戏在APL中的一条线

alt texthttp://catpad.net/michael/APLLife.gif

如果这条线不是WTF,那么什么都不是!

这是一个视频

JavaScript八进制转换“功能”是一个很好的了解:

parseInt('06') // 6parseInt('07') // 7parseInt('08') // 0parseInt('09') // 0parseInt('10') // 10

更多细节这里

mysql枚举,特别是他们混淆毫无准备的同事的生活地狱的能力。

CREATE TABLE foo (....dispatched ENUM('0','1') NOT NULL DEFAULT '0',)

然后:

UPDATE TABLE foo SET ..., dispatched = 1;

哎呀,dispatched被设置为ZERO,因为1没有被引用。这真的惹恼了那些在我的代码上工作的人;我现在使用普通的旧INT。

相关说明,即使您在枚举中添加了一个空字符串选项,例如。

blah ENUM('','A','B') NOT NULL,

如果您将无效值分配给blah,MySQL将使用一个秘密隐藏的空字符串值来表示无效值,这将很难与您自己添加的值区分开来。耶!

简单的选择,Erlang充满了它们。例如,3种形式的标点符号,

a_function(SomeVariable) ->statements_end_with_commas(),case PatternMatching of0 -> now_we_end_with_semicolon;true -> except_the_last_oneend.
%%  Function definitions end with periods!

好的,既然问题将处于间歇模式,我将加入“乐趣”

Go(又名Issue9)使用大写的可见性:

  • 如果你用大写命名某个东西,它将具有公共访问权限。

  • 如果您使用小写,它将受到包保护:

包装外可见:

func Print(v ...) {}

包装外不可见

func print( v ... ) {}

你可以在这里找到更多原始答案。

让我们投票支持所有试图取消保留字的语言(例如PL/I)。

你还能在哪里合法地写这样有趣的表达:

IF IF THEN THEN = ELSE ELSE ELSE = THEN

IFTHENELSE是变量名)

IF IF THEN THEN ELSE ELSE

IF是变量,THENELSE是子程序)

这并不奇怪或令人惊讶,但它让我总是说WTF

语法或标识符名称中的大小写敏感性。

大多数拥有它的语言似乎只是因为C拥有它而拥有它。没有充分的理由。

在Python中,函数参数的“编译时间”(或声明时间)计算可能会令人困惑:

def append(v, l = []):l.append(v)return l

print append(1)print append(2)
>>> [1]>>> [1,2]

其意图可能是:

def append(v, l = None):if l is None:l = []l.append(v)return l
print append(1)print append(2)
>>> [1]>>> [2]

这种行为对于缓存之类的事情很有用,但它可能很危险。

一个额外的特性:具有可变内容的元组:

a = (1,2,[3])a[2][:] = [4] # OKa[2] = [2] # crashes

为什么C#的List. AddRange()不允许我添加T的子类型的元素?List. Add()可以!
它所需要的只是微软部分的一个额外代码行:

public void AddRange<S>(IEnumerable<S> collection) where S : T

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

它有我见过的最奇怪的语法。而不是GoTo,你使用:(标签)。当你有: S(标签)(成功/true时的goto标签)和: F(标签)(失败/false时的goto标签)时,谁需要if's。你在检查某些条件或读取文件时使用这些函数。所以语句:

H = INPUT :F(end)

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

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

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

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

$DOG = 'SOUND'

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

你越看它,它就变得越糟糕。我找到的关于SNOBOL的最好的说法(从链接文本开始)是“语言的力量及其相当惯用的控制流特性使得SNOBOL4代码在编写后几乎无法阅读和理解。”

在FoxPro中,如果我没记错的话,每个命令都可以缩写为4个字符,其他所有内容都被忽略,所以READ、READY、READINESS都是一样的——忽略前4个字符之后的任何内容。给我解释的那个人喜欢那个功能,但我觉得它很令人毛骨悚然。

Java,

int x=010;

这将x赋值为8。

任何在Java中以零开头的整数都被假定为八进制。

这是我的两分钱。c++:

int* t = new int(15);delete t;

在SQLServer中,如果您在生产代码中使用select *,您可能会得到一个令人讨厌的惊喜。使用select *无论如何都不被认为是一种好的做法,但了解一些有趣的行为是很好的。

更多细节请参见问题SqlServer2005中的“选择*from table”与“选择colA、colB等from table”的有趣行为

引用Neil Fraser(查看该页面的末尾),

try {return true;} finally {return false;}

(在Java,但在JavaScript和Python中的行为显然是相同的)。结果留给读者作为练习。

编辑:只要我们在这个问题上,也考虑一下:

try {throw new AssertionError();} finally {return false;}

x=x+1

当我还是初学者时,这很难消化,现在函数式语言不使用它,这就更难了!

如果你不知道这有多奇怪:将等于号视为断言的声明而不是赋值行动,就像您在基本代数中所做的那样,那么这相当于说“零等于一”。

在Visual Basic 7及更高版本中,我发现实现短路逻辑评估以保持与传统Visual Basic<=6代码的兼容性有点WTF:

#0(MSDN)
#0(MSDN)

你可以把任何东西扔到Java。

class YourBoss extends Throwable {}public class Main{public void main(String[] s) throws YourBoss {try{throw new YourBoss();}catch(Exception e){}catch(Error e){}}}

C#,命名空间reslove order

举个例子。

namespace foo.bar.xyz{public class Foo{Exception e;   // you'll get compile time error here....}}

因为

namespace foo.bar.Exception{class HowDoMyWayException : ApplicationException {// because someone did this}}

在PHP中,函数名称不区分大小写。这可能会导致您认为php中的所有标识符都不区分大小写。再猜一次。变量区分大小写。WTF。

function add($a, $b){return $a + $b;}
$foo = add(1, 2);$Foo = Add(3, 4);
echo "foo is $foo"; // outputs foo is 3echo "Foo is $Foo"; // outputs Foo is 7

任何东西都会自动复数或单数化任何类和成员名称。

例如,Linq-to-Sql

在X++(Microsoft Dynamics AX)中:

1)需要在单独的行中使用分号(;)来将变量声明与语句分开(至少在4.0版本之前)

    int i;int myArray[5];;i = 1;


2)数组索引是基于1的,因此不允许使用索引0(零)从数组中读取,如

    int myArray[5];;print myArray[0];    // runtime error

这并不奇怪,但是你可以在一个分类的左边使用零索引,就像在

    int myArray[5];;myArray[2] = 102;myArray[0] = 100;    // this is strangeprint myArray[2];    // expcting 102?

发生了什么?无论赋值中使用什么值,数组都会初始化为它的默认值。上面的代码输出(零)!

Modula-2没有elseifelse if;它有elsif

在C#中,这至少应该生成编译器警告,但它没有:

public int Something{get { return Something; }set { Something = value; }}

调用时,它会导致您的应用程序崩溃,并且您无法获得良好的堆栈跟踪,因为它是StackOverflow Exception。

Java整数类的基转换静态方法。: P似乎很少有语言内置了这个功能。

我几年前使用的Fortran编译器有一个有趣的特性:(a)数字首先存储为高字节;(b)数字通过地址传递给子程序;(c)没有编译时检查长度。

所以你可以写一个这样的程序:(对不起,如果我把语法弄乱了。我已经很久没有写Fortran了。)

INTEGER*2 FUNCTION TIMESTWO (INTEGER*2 N)RETURN N*2
... THEN CALL THIS SOMEWHERE WITH A LONG INTEGER ...
INTEGER*4 I, J
I=42J=TIMESTWO(I)

J的最终值是…零!

为什么?因为传入的值是4个字节,但被调用的函数只查看前两个字节。由于前两个字节为零,它将零加倍并返回。然后将此返回值转换回四个字节。

当我第一次遇到它时,这是非常神秘的。几乎我传入某些函数的每个数字都被解释为零!

Perl的CORE::开放的标准库,其中面向对象的元素被过程接口掩盖:open ( my $fh, '>', 'foobar' );open是一个构造函数,它对my()返回的引用进行操作,并接受参数'>'和'fobar'。此外,这是一个受祝福的类型全局对象(意味着它不能在对象内部保存状态)。

关于我的perlmonks帖子IO::File vs CORE::打开的更多信息在这里:http://www.perlmonks.org/?node_id=763565

Perl的$[(已弃用),这在另一篇关于泛型perl变量的早期文章中提到,但它值得特别提及并有更好的解释。对$[的更改仅限于当前范围。更多信息和如何使用它及其含义的快速撰写;)可以在$[被尊重http://www.perlmonks.org/index.pl/?node_id=480333中找到

Haskell使用了MaybeJustMaybe a是一个返回类型Just a的类型构造函数,但是Maybe Int不会只接受Int,它要求它是Just IntNothing。所以本质上,在haskell的说法中,Just Int就像一个苹果是一个橘子一样。唯一的联系是Just 5返回一个类型Just0,它可以用函数Just和一个整数参数来构造。这是有道理的,但在理论上很难解释,这就是haskell的目的,对吗?所以Just真的是Just3吗,Maybe真的是Just5吗,再次是。

-- Create a function that returns a Maybe Int, and return a 5, which know is definitly Int'able>  let x :: Maybe Int; x = 5;<interactive>:1:24:No instance for (Num (Maybe Int))arising from the literal `5' at <interactive>:1:24Possible fix: add an instance declaration for (Num (Maybe Int))In the expression: 5In the definition of `x': x = 5
>  Just 5Just 5it :: Maybe Integer
-- Create a function x which takes an Int>  let x :: Int -> Int; x _ = 0;x :: Int -> Int-- Try to give it a Just Int>  x $ Just 5
<interactive>:1:4:Couldn't match expected type `Int' against inferred type `Maybe t'In the second argument of `($)', namely `Just 5'In the expression: x $ Just 5In the definition of `it': it = x $ Just 5

祝你好运,我希望你是对的。

在c#

Math.Round(2.5)==2

在c++

const char* wtf(){char buf[100];return buf;}string s = ... + wtf() + ...;

在s中创建有趣的值。部分字符串,部分堆栈内容,与零混合,以便s.length()!=strlen(s.c_str())。最奇怪的是,编译器在将指针返回到堆栈时绝对没有问题——如果编译器程序员在那里添加警告,他的手可能会掉下来。

在JavaScript中,undefined是一个全局变量,其默认值是原始值undefined。您可以更改undefined的值:

var a = {};a.b === undefined; // true because property b is not setundefined = 42;a.b === undefined; // false

由于undefined的可变性,通过typeof检查未定义性通常是一个更好的主意:

var a = {};typeof a.b == "undefined"; // always true

foo是什么数据类型?

SELECT TOP 1NULL AS fooINTOdbo.barFROMsys.columns --trivial

为什么一切都归零了?

SELECT CAST('' AS int), CAST('' AS datetime), CAST('' AS float)

…除了这个

SELECT CAST('' AS decimal)

对JavaScript的另一个投票:

parseInt('08') == 0

因为任何前导为0的代码都被解释为八进制(很奇怪),而无效的八进制数的计算结果为零(BAD)。我在8月份发现了这个,当时我几个月没碰过的代码自行崩溃了。事实证明,它应该在10月份自行修复。

八进制支持显然已被弃用,因此未来几代JavaScript将不会有这种仪式。

今天的所有语言:

TypeA a = (TypeA)some_operation_returning_TypeB(1,2,3); // TypeB is not inheriting TypeA

使用“Cast to TypeA失败异常”-消息(或类似)在运行时失败。这告诉我们程序员到底有多懒。他们没有办法产生消息“未能将TypeA的变量'a'与TypeB的值'some_operation_returning_TypeB(1,2,3)'赋值”。不…他们的座右铭是“犯错误的人必须受苦”。

在Perl中,对象只是blessed引用,因此在运行时更改对象的类是小菜一碟:

package Foo;sub new { bless {}, $_[0] }package Bar;package main;my $foo = Foo->new;ref($foo); # => "Foo"bless $foo, 'Bar';ref($foo); # => "Bar"

我很惊讶其他语言不能这样做。多么有用的功能!

在JavaScript中(我认为Java)你可以逃避这样有趣的字符:

var mystring = "hello \"world\"";

但是,如果您想将回车符放入字符串中,那是不可能的。您必须像这样使用\n:

var mystring = "hello, \nworld";

无论如何,对于编程语言来说,这都是正常和预期的。奇怪的是,您还可以像这样转义实际的回车:

var mystring = "hello, \world";

我一直是PHP错误的忠实粉丝,在断章取义的情况下连续使用两个冒号时抛出:

解析错误:语法错误,意外T_PAAMAYIM_NEKUDOTAYIM /path/to/file/error.php第3行

我第一次遇到这种情况时,我完全不知所措。

在MySQL中,字符串比较不区分大小写。

> SELECT * FROM blah WHERE foo = 'BAR';> SELECT * FROM blah WHERE foo = 'Bar';> SELECT * FROM blah WHERE foo = 'bAr';

不仅它们将匹配任何类似于'bar'的foo值(例如,如果foo='bar',它将匹配BAR、baR、bAR等)。

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风格语言中很多都可以工作,但我不确定。

  1. 将here文档作为函数参数传递:

    function foo($message){echo $message . "\n";}
    foo(<<<EOFLorem ipsum dolor sit amet, consectetur adipiscing elit. Nuncblandit sem eleifend libero rhoncus iaculis. Nullam eget nisi atpurus vestibulum tristique eu sit amet lorem.EOF);
  2. You can assign a variable in an argument list.

    foo($message = "Hello");echo $message;

    这之所以有效,是因为赋值是返回赋值的表达式。这是最常见的C风格错误之一的原因,执行赋值而不是比较。

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 existmysql> 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)

在JavaScript中,void不是关键字,不是类型声明,也不是变量名,也不是函数,也不是对象。void是前缀运算符,类似于---++!。您可以将其前缀到任何表达式,该表达式的计算结果将为未定义。

它经常用于书签和内联事件处理程序,如下面这个比较常见的示例:

<a href="javascript:void(0)">do nothing</a>

在这个例子中使用它的方式使它看起来像一个函数调用,实际上它只是一种获取原始undefined值的过于聪明的方式。大多数人并不真正理解JavaScript中void的真正本质,这可能会导致很多讨厌的错误和奇怪的意外事情发生。

不幸的是,我认为无效运算符是在JavaScript中获得undefined值的唯一真正有保证的方法,因为未定义,正如另一个答案中指出的,是一个可以重新分配的变量名,{}.a可以被Object.prototype.a = 'foo'搞砸

更新时间:我想到了另一种生成undefined的方法:

(function(){}())

呃,有点冗长,更不清楚返回“未定义”是它的目的。

在Java中从文本文件中读取一行。

BufferedReader in = null;try {in = new BufferedReader(new FileReader("filename"));String str;str = in.readLine();if (str != null) {...}} catch (IOException e) {...} finally {try {if (in != null) {in.close();}} catch (IOException e) {}}

呃。虽然我承认这并不奇怪…只是邪恶。:-)

更短,更习惯的版本:

try {BufferedReader in = new BufferedReader(new FileReader("filename"));try {String str = in.readLine();while (str != null) {str = in.readLine();}} finally {in.close();}} catch (IOException e) {e.printStackTrace();}

在C++,您可以:

std::string my_str;std::string my_str_concat = my_str + "foo";

但你不能做:

std::string my_str_concat = "foo" + my_str;

操作符重载通常受WTF的影响。

在javaScript中,NaN是一个全局变量。

对我来说,它绝对是INTERCAL中的PLEASE修饰符。如果PLEASE出现得不够频繁,则程序被认为不够礼貌,错误消息会这样说;如果太频繁,程序可能会被拒绝为过于礼貌。

我所知道的最奇怪的功能来自C++世界:SFINAE

最糟糕的是,它碰巧实际上是非常有用,在BOOST中广泛使用SFINAE对我来说已经足够了。

在ColdFusion中,数组从1开始。

MUMPS。有很多WTF特性,我选择了一个,if语句。(请注意,我在下面使用了相当冗长的编码风格,以适应那些不了解该语言的人;真正的MUMPS代码通常对外行来说更难以理解。)

if x>10 do myTag(x)    ; in MUMPS "tag" means procedure/functionelse  do otherTag(x)

这类似于Java中的说法:

if (x > 10) {myMethod(x);} else {otherMethod(x);}

除了在MUMPS中,else语句在语法上不是if块的一部分,它是一个单独的语句,通过检查内置变量$TEST来工作。每次执行if语句时,它都会将$TEST设置为if语句的结果。else语句实际上意味着“如果$TEST为假,则执行该行的其余部分,否则跳到下一行”。

这意味着如果x大于10,因此第一行称为myTag,并且myTag包含if语句,那么else的行为不取决于它上面一行中的if,而是取决于myTag中最后一次评估的if!由于这个“特性”,MUMPS程序员通常被教导像这样编写上面的代码是安全的:

if x>10 do myTag(x) if 1else  do otherTag(x)

第一行末尾的if 1确保$TEST在控制进行到下一行之前被正确设置。(顺便说一句,这里的行间距必须如此,else后面有两个空格,其他所有地方都有一个空格。行间距是奇数,但至少一旦你理解了模式,它是非常正交的。)

不久前,当我第一次在CS课上解释C语言时,看到指针的行为方式非常奇怪。我们只是编写程序并猜测它会做什么,直到它们得到正确的行为

C预处理器及其用法。特别是预处理器元编程和使用预处理器生成可移植代码——总的来说。

达夫的设备在C!

在C中,可以将do/同时与Switch语句交织在一起。这里有一个使用此方法的memcpy示例:

void duff_memcpy( char* to, char* from, size_t count ) {size_t n = (count+7)/8;switch( count%8 ) {case 0: do{ *to++ = *from++;case 7:     *to++ = *from++;case 6:     *to++ = *from++;case 5:     *to++ = *from++;case 4:     *to++ = *from++;case 3:     *to++ = *from++;case 2:     *to++ = *from++;case 1:     *to++ = *from++;}while(--n>0);}}

Python的一切都是真的引用的一个有趣的副作用:

>>> a = [[1]] * 7>>> a[[1], [1], [1], [1], [1], [1], [1]]>>> a[0][0] = 2>>> a[[2], [2], [2], [2], [2], [2], [2]]

我认为这实际上不是一个“语言功能”(C),我很可能在发布它时非常无知,但我不明白为什么会发生这种情况,所以我会问。如果它被证明与一些奇怪的语言功能有关…嗯,它真的让我“WTF”,所以值得这个地方。

int a = 0;int *p = &a;
printf("%d, %d, %d.\n", *p, (*p)++, *p); // Outputs "1, 0, 0.\n" on MinGW's GCC 4.4.1

为啥?

--编辑

刚得到它,没什么大不了的。我能感觉到C++大师现在在嘲笑我。我猜函数参数的求值顺序是未指定的,所以编译器可以自由地调用它们(我想我已经在Boost的留档中读到过这个)。在这种情况下,参数语句是向后求值的,可能反映了函数的调用约定。

PowerBasic(www.powerbasic.com)包含编译器指令:

# BLOAT {bloatsize}

这增加了编译的可执行文件的大小<bloatsize>字节.这被放在编译器中,以防创建可执行文件的人不喜欢生成的可执行文件的小尺寸.它使EXE看起来更大,与臃肿的编程语言竞争:)

与其说是语言功能,不如说是平台功能:在iPhone上,创建一个包含少量计算的无限循环并运行您的程序。您的手机会发热,当外面很冷时,您可以将其用作暖手器。

一些早期的动态语言(包括,如果我没记错的话,早期版本的Perl)没有弄清楚什么是好的动态,什么是坏的动态。所以他们中的一些人允许这样做:

1 = 2;

在此声明之后,以下内容将是真实的:

if(1 + 1 == 4)

在C中,sizeof运算符不评估其参数。这允许人们编写看起来错误但正确的代码。例如,给定类型T,调用malloc()的惯用方法是:

#include <stdlib.h>
T *data = NULL;data = malloc(sizeof *data);

在这里,在sizeof运算符中不计算*datadataNULL,所以如果计算它,就会发生坏事!)。

无论如何,这允许一个人编写令人惊讶的代码给新手。请注意,没有一个头脑正常的人会真正这样做:

#include <stdio.h>
int main(){int x = 1;size_t sz = sizeof(x++);printf("%d\n", x);return 0;}

这将打印1,而不是2,因为x永远不会递增。

对于一些真正的乐趣/与sizeof的混淆:

#include <stdio.h>int main(void){char a[] = "Hello";size_t s1 = sizeof a;size_t s2 = sizeof ("Hi", a);printf("%zu %zu\n", s1, s2);return 0;}

(只有当一个人对数组、指针和运算符感到困惑时,才会出现混淆。)

在PHP中,您可以使用符号和包含变量名称的字符串文字或变量引用变量,例如:

${'foo'} = 'test';echo $foo;

这将打印“test”。这种行为的奇怪之处在于,您还可以使用非字符串作为变量名,例如:

${array()} = 'test';echo ${array()};${NULL} = 'test';echo ${NULL};

现在我们有了名为rix()甚至NULL!的变量,它们都包含字符串“test”。

在JavaScript中,您可以使用双位否定(~~n)来替换Math.floor(n)(如果n是正数)或parseInt(n, 10)(即使n是负数)。n|nn&n总是产生与~~n相同的结果。

var n = Math.PI;n; // 3.141592653589793Math.floor(n); // 3parseInt(n, 10); // 3~~n; // 3n|n; // 3n&n; // 3
// ~~n works as a replacement for parseInt() with negative numbers…~~(-n); // -3(-n)|(-n); // -3(-n)&(-n); // -3parseInt(-n, 10); // -3// …although it doesn’t replace Math.floor() for negative numbersMath.floor(-n); // -4

单个按位否定(~)计算-(parseInt(n, 10) + 1),因此两个按位否定将返回-(-(parseInt(n, 10) + 1) + 1)

更新时间:这是一个jsPerf测试用例,比较了这些替代方案的性能

在Lisp中,你可以复制一个列表,你可以复制一个向量,你可以复制一个结构,你可以复制一个CLOS对象。

…但您不能复制数组或哈希表。

JCL条件执行。

//STEP02 EXEC PGM=PROG02,COND=(4,GT,STEP01) .

此功能允许您根据前面步骤的返回代码运行或不运行步骤。真的是一个很好的功能。

除了几个小功能将逻辑反转和倒转。

首先,如果条件为真,则步骤不运行。

其次,4,GT,STEP01实际上意味着“如果STEP01的返回代码大于4”

所以整件事情的意思是“如果STEP01的返回代码大于4,则不要运行这一步”。这与“如果4大于STEP01的返回代码,则运行步骤”的简单解释几乎但不完全相同。

考虑到你唯一认真看待这些事情的时间是凌晨2点30分左右,线的另一端有一个疯狂的夜班操作员,这种双重模糊性会导致严重的头痛。

在C或C++中,括号对于sizeof…的参数是可选的,前提是参数不是类型:

void foo() {int int_inst;
// usual style - brackets ...size_t a = sizeof(int);size_t b = sizeof(int_inst);size_t c = sizeof(99);
// but ...size_t d = sizeof int_inst; // this is ok// size_t e = sizeof int; // this is NOT oksize_t f = sizeof 99; // this is also ok}

我一直不明白为什么会这样!

并不是说这被大量使用,但C++的“返回引用静态大小数组”的语法很奇怪:

struct SuperFoo {int (&getFoo() const)[10] {static int foo[10];return foo;}}

ofc,在上面的case方法可以声明为静态常量

Perl。

打印"Foo\n"除非$foo;

在PHP中,字符串与函数指针一样好:

$x = "foo";function foo(){ echo "wtf"; }$x(); # "wtf"

不幸的是,这行不通:

"foo"();

C++:

void f(int bitand i){ //WTFi++;}int main(){int i = 0;f(i);cout << i << endl; //1return 0;}

在PHP中,“true”、“false”和“null”是通常不能覆盖的常量。然而,随着PHP>=5.3中命名空间的引入,现在可以在除全局命名空间之外的任何命名空间内重新定义这些常量。这可能导致以下行为:

namespace {define('test\true', 42);define('test\false', 42);define('test\null', 42);}
namespace test {var_dump(true === false && false === null); // is (bool) true}

当然,如果你希望你的tres为true,你可以从全局命名空间导入true

namespace test {var_dump(\true === \false); // is (bool) false}

在MUMPS中,你可以有一个带有偏移量的GOTO。如果你有(我的MUMPS生锈了…)

some_label if x=1 do_somethingelse  do_something_else

然后是代码

           goto some_label+1

将跳转到ELSE声明…

JavaScript日期充满了WTF。

var d = new Date("1/1/2001");
var wtfyear = d.getYear(); // 101 (the year - 1900)// to get the *actual* year, use d.getFullYear()
var wtfmonth = d.getMonth(); // 0// months are 0-based!

python2. x

>>>True = False>>>TrueFalse

你真的可以让一个人变得疯狂。

在Python中:

abs((10+5j)-(25+-5j))

返回~18.03,即毕达哥拉斯定理中点(10,5)和(25,5)之间的距离。发生这一事实是因为Python的本地语言支持2+2j形式的复数。由于复数的绝对值形式为a+bj=sqrt(a^2+b^2),我们在从一个复数中减去另一个复数时获得距离,然后对其应用abs(绝对)函数。

标记为Java中的中断和继续语句。

它们允许您通过一次中断来打破多个控制块。

C#有一个叫做“扩展方法”的特性,大致类似于Ruby混合-本质上,你可以向任何预先存在的类定义添加方法(例如,如果你愿意,你可以将“反向()”添加到String中)。仅此一项就很好-“奇怪”的部分是,你可以将这些扩展方法,以及方法体和所有内容添加到接口中。一方面,这可以方便地将单个方法添加到不属于同一继承树的整个类中。另一方面,你正在向接口添加充实的方法,本质上打破了接口的定义。

尝试,除了否则

try:     passexcept:  passelse:    passfinally: pass

如果没有捕获异常,则执行其他部分。

有道理,但起初我真的不知道它是做什么的。

示例

def show_square(string):try:n = int(string, 10)except ValueError:print "I can't do that, Dave."else:print n * n

有向图和替代标记

C(ISO/IEC 9899:1999,6.4.6/3)和C++(ISO/IEC 14882:2003,2.5)有一个很少使用的特性,被C称为“双字符”,被C++称为“替代标记”。

%:include <stdio.h>
int main() <%int a<:10:> = <%0%>;printf("Here's the 5th element of 'a': %d\n", a<:4:>);puts("Evil, eh? %:>");return 0;%>

C++还有更多,包括没有,它们需要表现为&&||!。C也有这些,但要求包含才能使用它们,将它们视为宏而不是令牌。C++头实际上是一个空文件。

值得注意的是,GCC实现了对这种奇怪语言特性的支持,但许多其他编译器在尝试编译上述代码段时会窒息而死。

我喜欢Smalltalk中缺少操作员优先级

2*3+4*5=6+4*5=10*5=50

而不是

2*3+4*5=6+4*5=6+20=26

这是由于Smalltalk的对象特性以及消息从左到右传递的事实。如果消息*以数字3作为参数发送到2,则该消息的响应为6。非常棒,如果你感到邪恶,你甚至可以猴子修补它。

在SQL

NULL不等于NULL

所以你不能做:

WHERE myValue == NULL

这将始终返回false。

NULL != NULL

Python的三元运算符

在Python中,C三元运算符(C++例子:bool isNegative = i < 0 ? true : false;)可用作语法糖:

>>> i = 1>>> "It is positive" if i >= 0 else "It is negative!"'It is positive'>>> i = -1>>> "It is positive" if i >= 0 else "It is negative!"'It is negative!'

这不是很奇怪,而是一个特性。奇怪的是与C(CONDITION? A: B)中的(IMO更合乎逻辑的)顺序相比,改变了顺序(A if CONDITION else B)。

Java泛型是一个WTF:

List<String> ls = new ArrayList<String>(); //1List<Object> lo = ls; //2

2:是非法的(???)这是令人费解的,但你必须考虑接下来会发生什么:

lo.add(new Object());String s = ls.get(0);

我们会将一个对象分配给一个String引用,哦,不!像这样,它们周围有很多陷阱。

在C中,a[b][c]c[b[a]]完全相同。

scala中,没有运算符,只有方法。所以a + b - c实际上与a.+(b).-(c)相同。在这种情况下,它等于Smalltalk。然而,与Smalltalk不同的是,优先级被考虑在内。规则基于第一个字符,因此名为*+的假设方法将优先于名为+*的方法。做了一个例外,以便任何以=结尾的方法都将具有与==相同的优先级--这意味着!!!=(非假设方法)具有不同的优先级。

所有ASCII字母的优先级都最低,但所有非ASCII(Unicode)字符的优先级都最高。因此,如果您编写了一个比较两个整数的方法is,那么2 + 2 is 1 + 3将编译并为真。如果您用葡萄牙语编写它,é,那么2 + 2 é 1 + 3将导致错误,因为它会将其视为2 + (2 é 1) + 3

而且,只是为了补充Scala中运算符的WTF,所有以:结尾的方法都是右关联的而不是左关联的。这意味着1 :: 2 :: Nil等效于Nil.::(2).::(1)而不是1.::(2).::(Nil)

反波兰表示法(RPN)。这意味着参数在函数之前。或者,换句话说,您可以通过编写2 2 +来添加2和2。

具有WTF特性的语言包括Forth、PostScript(是的,激光打印机)和Factor。

Forth的控制结构有一些奇怪的地方。首先,因为它是一种反向抛光符号语言,条件在IF之前,如:

x 0 = IF

现在,要关闭条件块,可以使用关键字THEN

x 0 = IF ." Equals zero!" THEN

现在真正的WTF开始了。IF所做的是编译一个条件前向跳转,并将跳转偏移量的地址放在堆栈上。当找到THEN时,它从堆栈中弹出该地址,计算实际偏移量,然后编译。另一方面,ELSE编译无条件前向跳转,从堆栈中弹出一个地址,在堆栈上推送一个新地址,计算弹出地址的偏移量,然后编译该偏移量。语法是这样的:

x 0 = IF ." Equals zero!" ELSE ." Not equal to zero!" THEN

第一个和第二个语句是这样编译的:

x LITERAL 0 = (0BRANCH) LITERAL offset SLITERAL" Equals zero!" (DOTQ)x LITERAL 0 = (0BRANCH) LITERAL offset SLITERAL" Equals zero!" (DOTQ) BRANCH LITERAL offset SLITERAL" Not equal to zero!" (DOTQ)

更奇怪的是,这种行为并不隐藏。它是该语言ANSI规范的一部分,可以通过构建自定义流控制结构或以有趣的方式组合它们来自由利用。例如,以Forth的WHILE循环为例:

BEGIN x 10 < WHILE x 1+ to x REPEAT

BEGINWHILE之间的部分是任意代码,因此实际上可以在单个控制结构中执行条件测试之前和之后的代码。这是设计,但以下内容虽然允许,但不是:

BEGIN DUP 2 > WHILE DUP 5 < WHILE DUP 1+ REPEAT 123 ELSE 345 THEN

它利用每个控制流字的工作方式来组合两个WHILE语句,并且在启动时,为每个出口添加不同的后循环代码。为了表明我不是在开玩笑,我只是从Internet上的代码中复制了那个小片段,并进行了一些小修改以简化它。

在MAXScript中,所有运算符都被平等对待。因此,a = b + ca设置为b,然后计算总和a+c,并丢弃结果。

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

在Javascript中,声明函数接受的参数对程序员来说只是一种方便。通过函数调用传递的所有变量都可以通过关键字“参数”访问。因此,以下内容会提醒“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");

在PHP中,您必须显式引用全局变量并显式使用this->作为类变量。使重构变得有趣。如果没有找到所有用法点,您就无法将变量/参数提升为全局或类成员。

在Java,如果x的值为NaN,则x == x返回false,x != x返回true。

模板可以用于C++奇怪的事情,最好的例子是“多维模拟文字”,它使用模板来计算“绘制”形状的面积。以下代码C++3x3矩形有效

#include"analogliterals.hpp"using namespace analog_literals::symbols;
unsigned int c = ( o-----o|     !!     !!     !o-----o ).area;

或者,再举一个3D立方体的例子:

  assert( ( o-------------o|L             \| L             \|  L             \|   o-------------o|   !             !!   !             !o   |             !L  |             !L |             !L|             !o-------------o ).volume == ( o-------------o|             !!             !!             !o-------------o ).area * int(I-------------I) );

通知7.一个有效程序的例子:

Chomsky is a room.A thought is a kind of thing.Color is a kind of value.The colors are red, green and blue.A thought has a color. It is usually Green.A thought can be colorful or colorless. It is usually colorless.An idea is a thought in Chomsky with description "Colorless green ideas sleep furiously."A manner is a kind of thing.Furiously is a manner.Sleeping relates one thought to one manner.The verb to sleep (he sleeps, they sleep, he slept, it is slept, he is sleeping) implies the sleeping relation.Colorless green ideas sleep furiously.

可以找到像这样的其他愚蠢图灵机模拟器

perl

my %h1 = map { $_ => 1 } qw/foo bar baz/;    // construct an 'is_member' type lookup tablemy %h2 = map { "$_" => 1 } qw/foo bar baz/;

第二行是语法错误,即使对于经验丰富的perl程序员来说,它看起来也会是相同的。perl的缺点总是试图做你的意思,而不是你说的。

在C++你可以从空指针调用静态方法-瞧!

class Foo {public:static void bar() {std::cout << "WTF!?" << std::endl;}};
int main(void) {Foo * foo = NULL;foo->bar(); //=> WTF!?return 0; // Ok!}

那个让我大吃一惊…

继承Ruby中的随机类:

class RandomSubclass < [Array, Hash, String, Fixnum, Float, TrueClass].sample...end

(首次出现在Ruby的隐藏特性

这让我震惊

#define _ -F<00||--F-OO--;int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO(){_-_-_-__-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-__-_-_-_}

Smalltalk:

在类Test中有一个类方法,它返回一个常量字符串:

method1^ 'niko'

您应该期望无论发生什么,此方法都会不断返回字符串“niko”。但事实并非如此。

s := Test method1

(将s设置为“niko”。)

s at: 4 put: $i.

(将s设置为“niki”。)

s := Test method1

(再次将s设置为niki。)

因此,第二行代码永久更改了方法1以返回“niki”而不是“niko”,即使该方法的源代码没有更新。

奇怪的事情——VBScript同时具有Null关键字和Nothing关键字(Null是缺少数据,Nothing是缺少对象)。为什么不只有一个关键字……?大多数其他语言似乎都可以用一个!

Visual Basic 6.0和“Classic ASP”代码(因为它使用VBScript)具有相同的奇异性。在Visual Basic新旧中,我们也有DBNull

然而,情况正在改善,因为在VisualBasic.NETNull终于消失了,因此Null未被使用,只有NothingDBNull被使用。

在C++,我发现“虚拟”MI(多重继承)允许“菱形”类层次结构“工作”是奇怪和令人厌恶的

A : Base class, e.g. "Object"B, C: both derive (virtually or not) from Object andD: derives from both B and C

问题:“正常”继承导致D是A的两种不明确的类型。“虚拟”MI将B的A和C的A折叠为单个共享基A对象。

所以,即使你的轮子是一个对象,你的左前轮是一个轮子,你的车继承了四种轮子,你的车仍然只是一种具有虚拟MI的对象。否则,你的车不是一个对象,而是四个轮子对象。

这是一种奖励糟糕的类设计,惩罚编译器编写者的语言特性,并让您在运行时想知道对象到底在哪里-以及是否有任何虚拟MI行李放错地方。

如果您确实需要类层次结构中的菱形模式,可以使用常规MI和委托给单个A基的“AProxy”来完成。

 A : Base class, e.g. "Object"AProxy: Base class, constructs with other A to bind toB : derives from AC : derives from AProxyD : derives from both B and C (passing B's A to C's AProxy at construction)

这需要更多的工作对于那些真正喜欢钻石MI的人来说,并让我们其余的人与一组更易于处理的语言特性和平相处。

在MATLAB(面向数组的交互式语言,目前为TIOBE 20)中,有一个关键字end来表示数组的最后一个元素(它对应于NumPy-1)。所以这是一个众所周知的MATLAB语法:

myVar = myArray(end)

要从数组中间获取一个元素,通常会写:

myVar = myArray( ceil( length(myArray)/2 ) )

令人惊讶的是,关键字end根本不是关键字,而是一种变量:

myVar = myArray( ceil( end/2 ) )

PHP的列表构造:

$array = array(0,1,2);list (,,$x) = $array;$x == 2; // true

在PHP中,字符串字母不能像在C中那样使用,您需要使用ord()chr()才能从数字转换为字符,而vica则相反:"a" != 97,但ord("a") == 97

虽然,有一个例外:

for ($i = 'a'; $i < 'z'; $i++) {print "$i ";}

将打印字母a到y。就像您期望的那样,就好像它是C样式数据类型一样。

但是,如果测试条件更改为<=,它将不会像您想象的那样打印a到z,而是打印a到yz!(总共打印了676个项目)

此外,如果您将“z”更改为“aa”,它在676项列表中的“z”之后出现,并再次将测试条件更改为<,您将看到仅打印出“a”!而不是您所期望的a到z。

如果您将增量器更改为$i+=2,它将再次只打印“a”!唯一的方法是按顺序使用$i++$i++,现在它像预期的那样工作。

尽管如此,这在PHP中是输出字母a-z组合的好方法,尽管实际使用它非常困难。

不知道这是不是一个功能。对一些人来说,是的,但对其他人来说,这可能是一个恼人的行为。无论如何,我认为这是值得一提的。

Python中,内置函数round()在Python 2x和Python 3x之间的行为略有不同。

对于Py 2x,

>>> round(0.4)0.0>>> round(0.5)1.0>>> round(0.51)1.0>>> round(1.5)2.0

对于Py 3x,

>>> round(0.4)0>>> round(0.5)0>>> round(0.51)1>>> round(1.5)2

我只是不熟悉Py 3x中的round()与0一起工作的方式。

Py 2xPy 3x中的round()文档。

在Ruby中,0在条件表达式中计算为true。

转变;

有时您会在perl方法的第一行看到它来读取自指针

在ColdFusion

结构(又名JavaHashMap)通过引用传递。

您会认为其他数据类型的行为类似于Java…

数组值传递,wtf!

列表只是一个普通的逗号分隔字符串!

功能:Bash、Korn shell(ksh93)和Z shell都允许订阅带有或不带美元符号的变量的数组:

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

这与美元符号一起,将产生10000的期望值:

unset arrayfor i in {1..10000}do((array[$RANDOM%6+1]++))doneunset totalfor count in ${array[@]}do((total += count))doneecho $total

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

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

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

您不能在那里使用美元符号,因为它是一个赋值(a在lhs上),尽管如果您使用间接,您可以这样做,但双重求值仍然会发生。

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

COBOL中让我恼火的一件很小的事情是没有专门的模运算。相反,你可以做一个除法,指定你只想要整数结果,并将其余的存储在不同的变量中。由于COBOL对变量非常敏感,这意味着你最终得到了一个你并不真正需要的变量,即除法的实际结果。这就是我曾经将一个变量命名为“无用”的故事——这是我能想到的最合适的名字。

在Unity,

GameObject.Find("MyObject")

将正常返回您的对象。但是,如果您这样做:

GameObject.Find("MyObject").active = false;//do other stuffif (GameObject.Find("MyObject").active){//do stuff}

然后你会得到一个空引用。在UnityiPhone中,此代码通常在编辑器中正常工作,但在从iPhone运行时会导致SIGBUS。问题是GameObject. Search()只会定位活动对象,因此即使你只是检查它是否处于活动状态,你也实际上是在调用if(null.active)。

为了使其正常工作,您必须在使其处于非活动状态之前存储它。

GameObject obj = GameObject.Find("MyObject");obj.active = false;//do other stuffif (obj.active){//do stuff}

可以说这是更好的做法,但是Unity处理非活动对象的方式通常很奇怪。它似乎卸载了大部分非活动对象(纹理等),但不是全部,所以非活动对象仍然会消耗大量内存。

我发现Javascript Date Object对110年的热爱令人愉快。试试看

<Script language ="JavaScript"><!--var now = new Date()var dia = now.getDay()var mes = now.getMonth()var fecha
//Day of the weekif(dia==0){fecha="Domingo, ";}else if(dia==1){fecha="Lunes, ";}else if(dia==2){fecha="Martes, ";}else if(dia==3){fecha="Miércoles, ";}else if(dia==4){fecha="Jueves, ";}else if(dia==5){fecha="Viernes, ";}else{fecha="Sábado, ";}
fecha = fecha + now.getDate() + " de "//Which month is it?if(mes==0){fecha=fecha + "Enero"}else if(mes==1){fecha=fecha + "Febrero"}else if(mes==2){fecha=fecha + "Marzo"}else if(mes==3){fecha=fecha + "Abril"}else if(mes==4){fecha=fecha + "Mayo"}else if(mes==5){fecha=fecha + "Junio"}else if(mes==6){fecha=fecha + "Julio"}else if(mes==7){fecha=fecha + "Agosto"}else if(mes==8){fecha=fecha + "Septiembre"}else if(mes==9){fecha=fecha + "Octubre"}else if(mes==10){fecha=fecha + "Noviembre"}else{fecha=fecha + "Diciembre"}
//Yearfecha = fecha + " del " + now.getYear()
document.write(fecha);//--></Script>

脚本是西班牙语-对不起,如果你不明白代码…这个想法是让你看到110年的结果。

J中,大多数原语(又名函数)都是一元(一个参数)或二元(两个参数,一个向左,一个向右)。但是修改原语需要3个(我认为它是唯一一个,除了外来语)。可以理解它需要3个,但它一开始看起来……错了。

vector =: i. 10   NB. Vector will be 0 1 2 3 4 5 6 7 8 9(10) (0) } vector NB. Will yield 10 1 2 3 4 5 6 7 8 9

J中,外国人(!:)是捆绑在一起的各种函数。左参数是一个类别,其中右参数通常(但不总是)是不同…东西的增量值。例如:

2!:55 NB. Close console9!:10 NB. Set print precision6!:0  NB. Actual time6!:2  NB. Execution time4!:3  NB. Loaded scripts

当然,聪明的做法是包装它们,但有些你只需要记住。顺便说一句,所有这些都是三元的,想想看,右边有两个参数,左边有一个参数。除非你给他们一个最终有效的参数,否则上述都不起作用。

Forth可以随时更改数字的基数:

HEX 10 DECIMAL 16 - .0 Ok

它也不需要是一个预定义的:

36 BASE ! 1Z DECIMAL .71 Ok

我不敢相信这个还没有在这里:JSF属性访问

在JSF UI标记中,您可以通过这样引用服务器端对象将属性的值放入接口中:

<h:inputText value="#{myObject.property}></h:inputText>

问题是Java不支持属性,因此您必须编写以get和set开头的方法,以便将UI对象链接到服务器上的“属性”。

public void setProperty(String property){...}public String getProperty(){...}

当我第一次学习JSF时,这让我感到困惑,我仍然认为它值得WTF……即使在Java实现对C#风格属性的支持之前,真的没有其他方法可以做到这一点。

任何地方的变量都被视为ColdFusion中的全局变量,无论它们放在哪里。

<cffunction name="one" returntype="void"><cfset var wtf="coldfusion"><cfinvoke method="second"></cffunction>
<cffunction name="two" returntype="void"><cfoutput>#wtf#</cfoutput></cffunction>

在PHP中:

echo 'foo' == 0;    // echos '1'echo 'foo' == true; // echos '1'echo 0 == true;     // echos '0'$foo = 'foo';echo $foo['bar']    // echos 'f'

PHP有一些最烦人的类型强制…

在Python中,每个字符串都包含空字符串。

answer = input("Enter 'Y[es] or N[o]:")if answer in 'YyNn':        # verify inputprocess(answer)

只需在上面的查询中按回车键就会将answer设置为空字符串,通过if answer in ...测试,并被处理为正确答案。更简洁地说:

>>> "ABCDEFGHIJ".__contains__("")True

像往常一样,Python在这里的行为在数学和逻辑上都是无懈可击的。正如我在很久以前的集合论课上回忆的那样:空集是每个集合的成员。

在我被它咬的少数情况下,这仍然令人惊讶,但我不会有任何其他方式。

在awk中,数组从索引1开始,这是最不令人困惑的。

在Python中,至少对我来说,这是非常wft的!我第一次看到它:

>>> "ja " * 5'ja ja ja ja ja '

你可以乘以字符串!WTF??

PS:我认为这是因为x * n意味着:n times x所以,5 times "ja ""ja ""ja ""ja ""ja ""ja ",因为你可以像这样连接字符串:

>>> "ja ""ja ""ja ""ja ""ja "'ja ja ja ja ja '

两个代码具有相同的结果(可能是相同的)

JavaScript中的变量赋值可以创建全局变量。如果变量在函数中被赋值,并且在同一范围内未声明为var,则隐式声明为全局变量。

function foo() {x = "juhu";  // creates a global variable x!var y = "kinners"}
foo();alert(x); // alerts "juhu"alert(y); // alerts undefined

请注意,在为变量赋值后也可以使用var语句:

function foo() {x = 12;var x; // x is now localreturn x;}
alert(foo()); // will alert 12;alert(x); // will alert undefined

LOLCODE!

整个语言本身。虽然不完全是WTF的东西,但我从来没有遇到过一种语言在我的脑海中以挤压卡通般的声音播放。我以前也没有看过代码并想惊呼“aaaawwww cuuute!”

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

HAICAN HAS STDIO?IM IN YR LOOP UPPIN YR VAR TIL BOTHSAEM VAR AN 10VISIBLE SUM OF VAR AN 1IM OUTTA YR LOOPKTHXBYE

在JavaScript中,方法的结果可以取决于放置的样式大括号。这是K&R风格,其中大括号放置在方法签名之后和返回语句之后:

var foo = function() {return {key: 'value'};}
foo() // returns an object here

现在,如果我将这段代码格式化为Allman风格,其中大括号总是放在新行上,结果是不同的:

var foo = function(){return{key: 'value'};}
foo() // returns undefined here

为什么?在JavaScript中,如果您自己不这样做,语言会自动在每行末尾放置分号。所以最后一段代码片段中真正发生的事情是这样的:

var foo = function(){return; // here's actually a semicolon, automatically set by JavaScript!{key: 'value'};}

因此,如果您调用foo(),方法中的第一条语句将是返回语句,它将返回undefined并且不会执行其他后续语句。

在SQL服务器(至少MS):

这将始终评估为false:

IF @someint <> NULL

给定:

DECLARE @int INT
SET @int = 6
IF @int <> NULLBEGINPrint '@int is not null'ENDELSEBEGINPrint '@int is evaluating to null'END

输出将是:

@int is evaluating to null

它必须写:

IF @someint IS NOT NULLBEGINEND

谁把英语专业的SQL队!:)

2000年Perl Journal的混淆Perl竞赛中的最佳展示条目:

#:: ::-| ::-| .-. :||-:: 0-| .-| ::||-| .:|-. :||open(Q,$0);while(<Q>){if(/^#(.*)$/){for(split('-',$1)){$q=0;for(split){s/\|/:.:/xg;s/:/../g;$Q=$_?length:$_;$q+=$q?$Q:$Q*20;}print chr($q);}}}print"\n";#.: ::||-| .||-| :|||-| ::||-| ||-:: :|||-| .:|

作者在http://mysite.verizon.net/les.peters/id2.html中完全解释了代码

C++(或Java)中没有封装。任何对象都可以违反任何其他对象的封装,乱搞其私有数据,只要它是相同类型的。例如:

#include <iostream>using namespace std;
class X{public:// Construct by passing internal valueX (int i) : i (i) {}
// This breaks encapsulationvoid violate (X & other){other.i += i;}
int get () { return i; }
private:int i;};
int main (int ac, char * av[]){X a(1), b(2), c(3);
a.violate (c);b.violate (c);cout << c.get() << endl;    // "6"}

大约20年前,我使用一种名为Coral的语言的编译器,它允许我声明writeonly变量!

不过,这是有道理的,因为它们是全局的,用作信号机制。一个进程将写入一个值,另一个进程将读取它。

ruby中的隐式变量\常量和可变常量

在Ruby…

i=truewhile(i)i=falsea=2endputs defined?(a) // returns true

以下C#代码抛出NullRe的异常,而不是print 1:

    static void SomeMethod(string format, params object[] args){Console.WriteLine(args.Length);}
static void Main(string[] args){SomeMethod("blabla", null, "Ok here"); // print 2SomeMethod("blabla", null); // exception}

以下代码在C#中生成编译器错误“无法从方法组转换为委托”。虽然背后的逻辑很合理,但我还是觉得很奇怪。

control.BeginInvoke(delegate { DoSomething(); });

在Python中:

i = 1++iprint i

打印'1'。'++i'行的计算结果为+(+i)(Python不支持增量运算符)

在JavaScript中:

2==[2]

//陌生人2 == [[[2]]

//右下角坚果var a={"abc": 1};a[[["abc"]]]] === a["abc"]; // 这也是真的

幸运的是,stackoverflow.com的好心人向我解释了整件事:超文本传输协议/stackoverflow.com/questions/1724255/why-does-2-2-in-javascript

这不是一个奇怪的功能,事实上,如果你仔细想想,它是完全有意义的,但还是给了我一个WTF时刻。

在C++(和C#)中,base的子类不能访问base实例上的私有成员和受保护成员。

class Base {protected:m_fooBar;};
class Derived: public Base {public:void Test(Base& baseInstance) {m_fooBar=1; //OKbaseInstance.m_fooBar = 1; //Badness//This, however is OK:((Derived&)baseInstance).m_fooBar = 1; //OK}};

Perl中的字符串数学非常奇怪。

$ perl -E '$string = "a"; $string++; say $string'b
$ perl -E '$string = "abc"; $string++; say $string'abd
$ perl -E '$string = "money"; $string++; say $string'monez
$ perl -E '$string = "money"; $string--; say $string'-1

英语中的虚拟语气。

哦,等等,你是说编程语言吗?然后在C中使用(macro)来绕过macro()的预处理器#define。例如,如果有人有#define free(...)(free)(...)将与free(...)不同。

在Python中:

>>> x = 4>>> y = 1000000>>> x is 4True>>> y is 1000000False>>>

不信你就试试看!

在类C语言(包括C本身)中,您可以使用“向下到”运算符:

for (x = 20; x --> 0;) {print x;}

这将打印从19到0的数字。

Java源文件可以以字符\u001a(Control-Z)结尾。

VBScript中的括号标识符

VBScript有所谓的括号标识符,它是定义在方形培根中的标识符,如下所示:

[Foo]

实际上,它们非常方便,因为它们允许您在保留字之后命名变量和例程,调用名称为保留字的第三方对象的方法,并且还可以在标识符中使用几乎任何Unicode字符(包括空格和特殊字符)。但这也意味着您可以从中获得一些乐趣:

[2*2] = 5
[Здравствуй, мир!] = [Hello, world!]
[] = "Looks like my name is an empty string, isn't that cool?"
For[For[i=0]=[0]To[To[To[0][Next[To]([For[i=0])=[For[i=0]Next

另一方面,如果您忘记了像这样的语句中的引号,括号标识符可能是一个陷阱:

If MyString = "[Something]" Then

因为If MyString = [Something] Then是一个完全合法的语法。(这就是为什么带有语法高亮的IDE是必须的!)


有关括号标识符的更多信息,请访问Eric Lippert的博客:

在Java,字符串如何处理==运算符取决于它的构造方式存在一些不一致。

String a = "Hello";String b = "Hello";System.out.println(a == b ); // prints true.String c = new String("Hello");String d = new String("Hello");System.out.println(c == d ); // prints false

这里有一个关于python的:

>>> print 077>>> print 08File "<stdin>", line 1print 08^SyntaxError: invalid token

这难道不是美吗?

尤其是当你想到人类是如何写日期的时候,这有以下效果:

datetime.date(2010,02,07) # okdatetime.date(2010,02,08) # error!

(原因是0x被解释为八进制,所以print 010打印8!)

在Matlab中,以下内容可能会令人惊讶,特别是如果您习惯了Python:

>> not true
ans =
0     0     0     0>> not false
ans =
0     0     0     0     0

这里有两个奇怪的特征。第一个是a b被解释为a('b'),所以not true被解释为not('true')。第二个奇怪的特征是任何字符的not返回0(大概是因为matlab中没有falsetrue,只有01)。

javascript:

parseInt('06'); // 6parseInt('08'); // 0

在方案中,有个保留标识符。因此,以下表达式的计算结果为1:

((lambda (lambda) lambda) (let ((let 1)) let))

请注意,给定范围内的定义有限制:任何定义都不能重新定义用于定义该范围内标识符的标识符,因此以下是语法错误:

(begin (define define 1) define)

JavaScript中的变量/函数声明:

var x = 1;function weird(){return x;var x = 2;}

奇怪()返回未定义… x被“占用”,即使赋值从未发生过。

类似的,但不是那么出乎意料

function weird2(){var x;return x();function x(){ return 2 };}

返回2。

我首先想到的是'noop',当我第一次遇到它时,我的大脑也做了同样的事情!

在php中:

easter_date-获取给定年份复活节午夜的Unix时间戳

inteaster_date([int$year])

PHP作为整个语言主要是WTF。

语言定义(见www.php.org)不是由语法或标准定义的,而是由一堆“你可以写这个示例”部分(你还能写别的吗,当然,只是猜测泛化),诚实的用户贡献说“但它做了这个古怪的事情…”。

我定期遇到我们构建的PHP解析器的故障。这是最新的:

 "abc$A[define]def"

现在,PHP是PERL的一个(非常糟糕的)副本,因此它允许使用变量的隐式替代来构造字符串。字符串中的$X表示“将$X的值插入字符串”,相当于“abc”。$X。“def”where“.”是PHP的字符串连接运算符。

字符串中的$A[7]表示,“将数组$A的第七个槽的值插入字符串”,相当于“abc”。$A[7]。“def”。

现在,语言(网站)明确说“定义”是一个关键字,你不能在任何你能找到表达式的地方使用它。那么上面包含“定义”的gem会做什么?抛出语法错误?不,这是有道理的。

不,它实际上的意思是:

 "abc" . $A["define"] . "def"

只有当你在字符串中的简单数组访问中编写一个看起来像标识符(关键字与否!)的东西时,它才会这样做。该语言中的其他任何地方都不会发生这种行为。什么,写“abc$A[”定义“]def”是不合理的,所以PHP的发明者不得不把它扔进去?让我休息一下。(为了加重重罪,有“字符串中的复杂数组访问”,当然它的工作方式不同。查看“abc{$A[”定义]}def”;根据PHP网站,这是非法的。

(原来PHP数组是关联哈希,所以按名称查找数组(嗯,哈希表)成员并不是一个可怕的想法)。

该语言充满了这样的陷阱。如果你喜欢“哎呀,看看我今天在我的子程序下发现了什么蠕动的东西”,你应该切换到PHP。

在PHP中,以下内容:

<?php $foo = 'abc'; echo "{$foo";

是语法错误。

如果你真的想要{,然后是$foo的内容,你必须使用.

<?php $foo = 'abc'; echo '{' . $foo;

我不知道这是否仍然正确,但我们偶然发现VS FORTRAN(66或77)不支持递归。递归是偶然的,我们的默认F77支持得很好,但是当我们将源代码带到IBM-Whatta Mess时。

C++1x Lambda:

[] (int x) { std::cout << x << std::endl; } ();

这些可能会被滥用于一些奇怪的语法:

[](){}();[]{[]{}();}();

这是完全有效C++1x。

处理(processing.org)是一种基于Java的语言。简单来说,处理编译器是Java预处理器,它将特定于处理的语法转换为Java。

由于语言的设计,它有一些惊喜:

处理的类被编译成Java内部类,这会引起一些烦恼,比如不是真正私有的私有变量

class Foo {private int var = 0; // compiles fine}
void setup() {Foo f = new Foo();print(f.var); // but does not causes compile error}

此外,缺失的Draw()函数会导致不调用事件处理程序:

// void draw() {} // if you forgot to include thisvoid mousePressed() {print("this is never called");}

Perl有yada yada操作符...)。

Perl 6传统的所谓“yada yada”运算符是标记未实现代码的快捷方式:

if ($condition) { ... }

if ($condition) { die "not yet implemented" }

在Java(实际上,我最近在不同的SO帖子上写过):

    int x = 1 + + + + + + + + + + + + + 1;System.out.println(x);

在C++,能够创建受保护的抽象虚拟基础纯虚拟私有析构函数。

这是一个纯虚拟私有析构函数,继承自受保护的抽象虚拟基。

IOW,一个析构函数,只能由类的成员或朋友调用(私有),并且在声明它的基类(抽象基类)中分配0(纯虚拟),并且稍后将在以受保护的方式共享多继承基类(虚拟基类)的派生类中定义/覆盖。

学习PowerShell时发现:

试着猜测结果数组的样子:

$a = 1, 2$b = 1, 2+3$c = 1, 2*3

答案:

1, 21, 2, 31, 2, 1, 2, 1, 2

哎哟!它动摇了我对PowerShell和它背后的人的信心。

在MOD_REWRITE

RewriteRule ^([a-zA-Z0-9_-]+)\.php$ $1/ [R,NC]RewriteRule ^([a-zA-Z0-9_-]+)/$ $1\.php [NC,L]

将导致:

"file.php > file > file.php > file > file.php > file >  ..."

最后:

Error 500 Too Many Redirects

(一般来说,我发现编辑. htaccess文件与构建正常运行的正则表达式一样乏味。)

绝对最差的WTF必须是Cobol的ALTERED GOTO。

语法非常简单:“ALTER label1 TO GOTO label2”,但调试运行时意大利面条的结果令人难以置信。

SQLite允许您使用所需的任何数据类型声明列。它会查找一些特定的子字符串(“INT”、“REAL”、“TEXT”等)来确定亲和力。

这使得在类型声明中撒谎成为可能:

CREATE TABLE Quirks (X    FLOATING POINT,  -- = INTEGER affinity because of the "INT"Y    STRING,          -- = NUMERIC affinity);

Atari BASIC:

您可以在不编写循环的情况下用字符填充字符串:

10 DIM A$(100)20 A$(1)=" ":A$(100)=" ":A$(2)=A$

perl:

可以写一个完全由标点符号组成的程序

这是怎么工作的?!

从技术上讲,WTF不是一种语言,而是一种架构。

http://www.6502.org/tutorials/6502opcodes.html#JMP

6502组装,间接JMP:

请注意,没有与间接跳跃相关的进位,因此:

间接跳跃绝不能使用

向量从最后一个字节开始

的一页

例如,如果地址3000美元包含40美元,$30FF包含80美元,3100美元包含50美元,JMP($30FF)的结果将是控制权转移到4080美元而不是您预期的5080美元,即6502从$30FF中取出地址的低字节,从3000美元中取出高字节。

因此,在代码中添加一个字节可能会使您的间接跳跃偏离目标。

C#中的“动态”。

对于必须与RAD或python受害者一起工作的每个人来说,这一天都被毁了,因为智能感知、类型安全和决定论在第一次使用“动态”关键字时立即死亡。

php

来自在线文档:
string implode ( string $glue , array $pieces )-用字符串
连接数组元素注意:由于历史原因,implode()可以按任一顺序接受其参数。

所以这个工作:implode($someArray, $glue)

希望他们能在PHP 6中消除这些历史怪癖。

这是我的最爱之一,你可以做一个println在Java没有main()。

这将编译并运行,给出println,但也是一个异常(java.lang.NoSuchmododError: main)

class Test {static {System.out.println("I'm printing in Java without main()");}}

在php

var_export('false' == 0);       // true
var_export('false' == true);    // true
var_export('false' == false);   // false

编辑

正如@Kobi提到的,它可能会发生,因为语言将任何值解释为“TRUE”,除了“FALSE”,但在PHP的情况下不会,那里的事情比你想象的更奇怪!

这个案例在PHP手册的“字符串转换为数字”一章中有完整的记录,其中说:

如果字符串以有效开头数字数据,这将是值使用。否则,值将为0(0)

下面是例子:

print (int) 'zero';    // 0print (int) 'false';   // 0// butprint (int) '1 - one'; // 1

附注:我看到这种隐式类型转换的危害大于有用性。

JavaScript是面向对象的,对吧?所以在文字字符串和数字上运行方法应该可以工作。就像"hello".toUpperCase()3.toString()。原来第二个是语法错误,为什么?因为解析器期望一个数字后跟一个点是浮点文字。这不是WTF,WTF是你只需要添加另一个点就可以使它工作:

3..toString()

原因是文字3.被解释为3.0,而3.0.toString()工作正常。

这个古老的PHP最爱本身并不全是 WTFish,但是范围解析错误是许多开发人员看到的事情之一,值得给予一些WTF的爱:

$class = new StdClass();$class::test();
PHP Parse error:  syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM on line 3

在Ruby中,你可以用heldocs做一些奇怪的事情。考虑:

a = <<ONEThis is one. #{<<TWO}This is two. #{<<THREE}This is three.THREETWOONE
p a # => "This is one. This is two. This is three.\n\n\n"

NSIS(Nullsoft脚本安装系统)有StrCmp指令:

StrCmp str1 str2 jump_if_equal [jump_if_not_equal]

比较(不区分大小写)str1和str2。如果str1和str2相等,Gotosjump_if_equal,否则Gotosjump_if_not_equal。

StrCmp $0 "a string" 0 +3DetailPrint '$$0 == "a string"'Goto +2DetailPrint '$$0 != "a string"'

锦上添花:jump_if_equaljump_if_not_equal也可以是负数。但我猜你已经从正数前面的+符号中知道了。我不记得这是强制性的,还是只是一个可怕的惯例。

这基本上结合了最糟糕的BASIC和最糟糕的Assembler。

整个Malbolge编程语言:http://en.wikipedia.org/wiki/Malbolge

Java,

String s = null;System.out.println(s + "hello");

这将输出“nullhello”。

Commodore BASIC的命令快捷方式。基本上大多数命令都有缩写形式,通常是第一个字母+(Shift+第二个字母)。但是因为C64上的字符集默认都是大写的,所以这些命令看起来像是奇怪的符号。这是一个简短的hello world示例:

Commodore BASIC截图

也许有人有一个更好的例子,实际上有更多的肉,但对于长程序来说,这看起来完全荒谬。

以下是缩写列表:http://www.c64-wiki.com/index.php/BASIC_keyword_abbreviation

Perl可以自动将基数26转换为基数10,如果你早上能和自己一起生活…

$ perl -E "say lc (@a='a'..'asdf')"30530

在ColdFusion中,文本值会出于各种目的自动转换为各种数据类型。我遇到了一个奇怪的问题,“00A”和“000”返回相等。原来ColdFusion将“00A”解释为时间,转换为某种数字时间格式,并将其转换为0。“000”被转换为0。所以它们被认为是等价的。就在那时,我了解了字符串的比较函数。

到目前为止,我遇到过的最奇怪的功能是BASIC方言中的“返回n”语句(不记得是哪一个,这是大约28年前的事了)。“n”是可选的,默认为1。它可以是一个正数或负数,指示相对于调用GOSUB的哪一行是下一个被执行的。

例如,以下将输出“30”:

10 GOSUB 20020 PRINT "20"30 PRINT "30"100 END200 RETURN +2

我在将一个用这种奇怪的BASIC语言编写的程序翻译成FORTRAN语言时遇到了这个问题。BASIC程序经常使用这个特性,根据各种条件返回不同的语句,我花了一段时间才理解逻辑流程。一旦我理解了它,我就能够编写一个更简单的程序版本。不用说,更简单的FORTRAN版本比原来的BASIC程序有更少的错误。

在PHP中:

for ($s="a";$s<="z";$s++) echo $s.' ';

这将写入:

a b c d e .. .w x y z aa ab ac ad .. ay az ba bb bc ... by bz ca cb ... yz za zb ... zx zy zz

我最喜欢的小C++语法技巧是,您可以将URL(有一些限制)直接放入代码中:

int main( int argc, char *argv[] ){int i=10;
http://www.stackoverflow.comreturn 1;}

这编译得很好。

语法突出显示有点破坏笑话,但它仍然很有趣。

ruby

Time.parse经常假装解析没有失败,而是返回now

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

其余的都没有关于惊人的Ruby触发器运算符:

p = proc {|a,b| a..b ? "yes" : "no" }
p[false,false]    => "no"p[true,false]     => "yes"p[false,false]    => "yes"   # ???p[false,true]     => "yes"p[false,false]    => "no"

是的,程序状态存储在解释器的解析树中。像这样的事情就是为什么要花很长时间才能做出兼容的Ruby实现。但我原谅你,Ruby<3

条件语句中的“…”和“…”并不总是范围运算符:

(0..20).each do |x|if ((x%10) == 5)..((x%10) == 5)print "#{x} "endend
(0..20).each do |x|if ((x%10) == 5)...((x%10) == 5)print "#{x} "endend

这将输出:

5 155 6 7 8 9 10 11 12 13 14 15

…在每次传递中检查两个语句,…只检查每次传递中的“on”或“off”语句(取决于触发器状态)。它们是从awk和ses中窃取的。

Matz在“Ruby编程语言”中写道:“触发器是Ruby的一个相当模糊的特性,可能最好避免……”

在找函数?为什么不是语言?

我喜欢PHP,但它似乎总是这样构建“哦,s***t!我忘了这个!让我们在函数中添加另一个参数”,结果如下:

str_replace($搜索,$替换,$主题,…)
strstr($title,$search,…)

注意额外的下划线和参数的不同顺序。

这是别的东西

$a = array( 'a', 'b', 'c', 'd');
print_r($a); //Prints array( 0 => 'a', 1 => 'b',    2 => 'c', 3 => 'd');unset($a[2]); //Destroys the element 2 of the listprint_r($a); //Prints array( 0 => 'a', 1 => 'b',    3 => 'd');

Python 2. x演示了一个糟糕的列表理解实现:

z = 4s = [z*z for z in range(255)]print z

这段代码返回254。列表理解的变量与上定义的冲突。

Python 3. x已经处理了这个特性,但是闭包仍然使用外部变量的动态链接,并且在函数式风格的python程序员中带来了许多WTF

def mapper(x):return x*xcontinuations = [lambda: mapper(x) for x in range(5)]print( [c() for c in continuations])

这段代码显然返回[16,16,16,16,16]

在C:

int main() {int i = 0;int array[] = {1,2};
return (i[array] + 1 == array[i]);}

这个程序将返回1(true)。

很久以前,我曾经用但是子句构建了一种语言。

Fortran对不同列的特殊含义。(如果你从小就有穿孔卡片,可能是完全自然的。)

这样做的一个副作用是,例如,变量名在第72列之后被截断。结合IMPLICIT NONE,当这样的变量名在第72列附近开始时,它会静默引入一个新变量。

你会需要

  1. 意识到这一点

  2. 一个编辑器,它以不同的方式突出显示注释部分(第72列之后)颜色比之前的部分…

php

$ php -r '::'Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM

WTF?http://en.wikipedia.org/wiki/Scope_resolution_operator

为什么不unexpected T_SCOPE_RESOLUTION_OPERATOR

在JavaScript中:

var something = 12;
function nicelyCraftedFunction(){something = 13;// ... some other code// ... and in Galaxy far, far away this:if( false ) // so the block never executes:{var something;}}nicelyCraftedFunction(); // call of the function

通常您会期望something变量的值为13。但不是在JavaScript中-变量有函数范围,因此稍后的声明会影响上游的所有内容。

在使用C/C++/Java符号(如JS)的语言中,您会期望变量具有块范围,而不是像这样…

因此,编译器甚至可以从最终生成的字节码中删除的死代码块仍然会对正常执行的其余代码产生副作用。

因此something将仍然是12-在调用函数后不会更改。

s a="a="a="""a""",@a=""""2N""", a=""""c="""_(""""22""""? @a),@a"",@a, a=""a"", a(c)=""S+""_c, e=$T(@@a@(c))",@a

这是COS(缓存对象脚本)中一个很好的单行代码。这里要注意的有趣的是5种不同的代码间接模式*G

我喜欢在C中潜入八进制值:

int values[8] = { 123, 154, 103, 310, 046, 806, 002, 970 };

在Haskell中:

let 2 + 2 = 5 in 2 + 2

产量5。

再一次Haskell:

在Haskell中,您可以处理任意大小的文件,就好像它是一个简单的String一样。只有在实际使用字符串时,该文件才会被读取。由于Haskell令人难以置信的惰性,这样的程序将在恒定空间中运行,而不管文件的大小:

main = interact (>>= \x -> if x == '\n' then "\r\n" else [x])

(此程序将文件从stdin转换为stdout并将LF替换为CRLF,interact函数输入将整个stdin转换为函数并将输出移动到stdout。)

这种懒惰也可能导致问题,因为如果您关闭一个文件句柄,无论懒惰的Haskell是否已经解析了其中的所有数据,您都无法完全舒缓。

在(MRI/C)Ruby和MacRuby(但在JRuby中不是)中导致年份翻转的整洁的系统相关溢出如何,然后是更大数量的本地时间错误。不是一个常见的问题,但很奇怪:

$ ruby -versionruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]$ irb>> Time.at(67767976233550799)=> Tue Dec 31 23:59:59 -0500 2147483647>> Time.at(67767976233550800)=> Wed Jan 01 00:00:00 -0500 -2147483648>> Time.at(67768036191694799)=> Wed Dec 31 23:59:59 -0500 -2147481749>> Time.at(67768036191694800)ArgumentError: localtime error...Maybe IRB bug!!

不过,这可能特定于64位环境。

在Java

String("aaa")==String("aaa") //false//you need to useString("aaa").equals(String("aaa")) // true

由于我没有看到任何人提到它… RPG 2或3(报告程序生成器…又名火箭推进垃圾)是迄今为止我使用过的最螺旋的语言。它几乎没有对程序流的控制(文件顶部的回车,底部的退出)和编程语句是根据使用固定字体在特定列中定义的字符定义的(想想PUNCH CARDS!!)。

要真正FUBAR,您必须尝试使用DYL-280编程。它将RPG流程和逻辑与COBOL语法相结合。

RPG:wikipedia.org /wiki/IBM_RPG

以DYL-280为例:http://99-bottles-of-beer.net/language-dyl-280-224.html

对于那些不知道的人来说,PostScript实际上是一种编程语言。我对它有点疯狂-我写了一个PostScript程序,可以将Mandelbrot分形计算到非常高的详细级别。它真的是可打印的PostScript,尽管它会使很多打印驱动程序崩溃……

不管怎样,从PostScript开始……这里有一个:您实际上可以创建一个标识符为……无的变量。

()cvn 5 def%将数字5分配给…无

PostScript是一种基于堆栈的语言。()在堆栈上放置一个空字符串。cvn将其转换为名称(如果你打印它,因为PS中的所有名称都以斜杠开头)。然后5 def将值5分配给它。(%是注释字符)

你不能直接找回它,例如,如果我说“/print”,这不会打印数字5。但你可以间接找回它:

()cvn load print%this将打印数字5

还有什么…PostScript将字典作为本机类型,您可以使用数组引用作为字典的键……但关键是REFERENCE,而不是数组。所以:

/myDict100字典def

[0]dup myDictexch 42把myDictexch get==%打印42

myDict1[1] 42 put myDict1[1]get%抛出一个未定义的错误

编辑:哦,是的,还有一件有趣的事情……在Ghost Script提示符下尝试以下操作:

1 array dup dup 0 exch put ==

D'oh!

以下是Perl调试器中的一些混乱:

  DB<1> sub foo { +(1..20) }DB<2> @bar = foo(); # list of 1, 2, 3, 4...20DB<3> x scalar @bar # size of list0  20DB<4> x scalar foo();0  ''

没错。当你这样调用方法时,来自scalar的标量上下文向下传播到子例程调用中,将看起来无害的..变成完全不同的运营商。(这是“触发器”运算符,而不是范围运算符)。

在Perl中(没有“使用严格”或“使用警告”):

if(true==undef){print "True\n";}else{print "False\n";}if(undef){print "True\n";}else{print "False\n";}if(true){print "True\n";}else{print "False\n";}

打印:

TrueFalseTrue

JavaScript:

( {} == {} ) == false

在C中,

 int x = 1;int y = x++ + ++x;printf("%d", y);

是模棱两可的,打印的内容取决于编译器。编译器可以在计算++x之前或语句末尾存储x++的新值。

大约在1977年,我在Lisp中添加了“格式”函数,那时“printf”甚至还没有存在(我从与Unix相同的来源复制:Multics)。它一开始很天真,但却充满了一个又一个的功能。当Guy Steele投入迭代和相关功能时,事情失控了,这些功能被Common Lisp X3J13 ANSI标准所接受。以下示例可以在Common Lisp语言,第2版第22.3.3节中的表22-8找到:

(defun print-xapping (xapping stream depth)(declare (ignore depth))(format stream"~:[{~;[~]~:{~S~:[->~S~;~*~]~:^ ~}~:[~; ~]~ ~{~S->~^ ~}~:[~; ~]~[~*~;->~S~;->~*~]~:[}~;]~]"(xectorp xapping)(do ((vp (xectorp xapping))(sp (finite-part-is-xetp xapping))(d (xapping-domain xapping) (cdr d))(r (xapping-range xapping) (cdr r))(z '() (cons (list (if vp (car r) (car d)) (or vp sp) (car r)) z)))((null d) (reverse z)))(and (xapping-domain xapping)(or (xapping-exceptions xapping)(xapping-infinite xapping)))(xapping-exceptions xapping)(and (xapping-exceptions xapping)(xapping-infinite xapping))(ecase (xapping-infinite xapping)((nil) 0)(:constant 1)(:universal 2))(xapping-default xapping)(xectorp xapping)))

在JavaScript中:

1 / 0; // Infinity1 / -0; // -Infinity

else在Python的for循环中。

从Python留档:

for n in range(2, 10):for x in range(2, n):if n % x == 0:print n, 'equals', x, '*', n/xbreakelse:# loop fell through without finding a factorprint n, 'is a prime number'

输出:

2 is a prime number3 is a prime number4 equals 2 * 25 is a prime number6 equals 2 * 37 is a prime number8 equals 2 * 49 equals 3 * 3

Delphi不关心像“word”这样的类型转换,并且会在数组arr[0…65535]之外读取,其中pos=65535:arr[word(pos + 10)]

Tcl中的连接是添加两个字符串,它变成一个字符串:

set s1 "prime"set s2 "number"set s3 $s1$s2puts s3

输出是

原始编号

C/C++:

快速逆平方根算法利用了IEEE浮点表示(从维基百科复制的代码):

float InvSqrt(float x){union {float f;int i;} tmp;tmp.f = x;tmp.i = 0x5f3759df - (tmp.i >> 1);float y = tmp.f;return y * (1.5f - 0.5f * x * y * y);}

在C#中:a=cond? b: c;如果'b'和'c'是"赋值不兼容",你永远不会得到结果,即使'a'是对象。它是MS中经常使用和最愚蠢实现的运算符。有关比较,请参阅D语言中的实现(关于类型推断的注释)。

这可能已经提到了,但是-

PHP对八进制值的处理:

$a = 07; // 7 (as it should be)$b = 08; // 0 (would be an error in any sensible language)$c = 018; // 1 (again, should have been an error)$d = 0A; // error (as it should be)

看这里:http://bugs.php.net/bug.php?id=29676

还要注意bug上的评论——Derick称它为一个特性(如引用“修复”所示),而不是bug他声称它会“在脚本中使用数字的所有情况下显着减慢PHP”——但是,为什么PHP会为0A引发错误?

我认为人们可以写一本关于PHP的怪异之处的书……

我在试图找出一个完全没有意义但无论如何都有效的MACRO时遇到了这个。这适用于Objective-c,但也可能适用于其他风格的C(或至少是gcc编译器)

NSString *oneString = @"This " @"is " @"just " @"one " @"normal " @" string";

等于

NSString *oneString = @"This is just one normal string";

对于C风格的字符串也是如此

char* str = "this " "also " "works";

在PHP中,可以这样做:

System.out.print("hello");

在PHP中:

<?php$o = new stdClass;echo count($o);?>

…指纹1。从来没有想过为什么。

在C#中,您可以在接口上使用new运算符。

Go的伪常量Iota:

type ByteSize float64const (_ = iota;   // ignore first value by assigning to blank identifierKB ByteSize = 1<<(10*iota); MB; GB; TB; PB; YB;)

来自任何人?

Objective-C对字符串使用@。示例:@“这是一个字符串。”

Tcl在解释器中虚拟化时间钩子的感觉非常奇怪:http://www.tcl.tk/cgi-bin/tct/tip/233.html

基本上,它允许您让解释器使用其他时间数据来源,例如首先在模拟器中运行硬件测试,然后只需替换计时器功能并针对真实事物运行相同的测试。

我的C++最爱之一:

#include <iostream>using namespace std;int main(){cout <<  3 << 5  << endl;cout << (3 << 5) << endl;return 0;}

当然,这很容易解释,但它已经开始编程的学生摸不着头脑!

在PowerShell中,您可以重命名变量:

> $a = "some value"> $b = "a"> $c = "d"> Rename-Item variable:$b $c> $dsome value

间接间接!取那个php

文字工作,也是:

> Rename-Item variable:d e> $esome value

在俄亥俄州立大学,他们使用一种名为Resolve/C++的杂种C++语言教授编程。Resolve/C++对一切都使用契约设计方法论。它要求您在编译的注释中对组件和方法进行数学建模,从而迫使您在方法和对象之间保持要求/确保关系。

以下类似于这个答案,它是关于数组的。

在Powershell中,像其他动态语言一样,字符串和数字在某种程度上是可以互换的。然而,Powershell无法下定决心。

PS> $a = "4"    # stringPS> $a * 3      # Python can do this, too444PS> 3 * $a      # Python doesn't do it this way, string repetition is commutative12PS> $a + 3      # Python gives a mismatched types error43PS> 3 + $a      # Python would give an error here, too7

如果变量是整数而不是字符串,则操作是可交换的。

PS> $a = 4      # integerPS> $a * 312PS> 3 * $a12PS> $a + 37PS> 3 + $a7

有疑问时,做一个演员:

PS> $a = "4"PS> $b = 3PS> [int] $a * [int] $b12

您也可以使用[float]

php(再次?)

第一:(unset)型铸造。

$a = 1;$b = (unset)$a;var_dump($a); // 1var_dump($b); // NULL

用法:

第二:= NULLunset()函数之间的区别。

$c = 10;$d = &$c;$c = NULL;var_dump($c); // NULLvar_dump($d); // NULL

$e = 10;$f = &$e;unset($e);var_dump($e); // NULLvar_dump($f); // 10 - WTF?

C#的默认继承模型赢得了我的投票:

public class Animal{public string Speak() { return "unknown sound" ; }}
public class Dog : Animal{public string Speak() { return "Woof!" ; }}
class Program{static void Main( string[] args ){Dog aDog = new Dog() ;Animal anAnimal = (Animal) aDog ;
Console.WriteLine( "Dog sez '{0}'" , aDog.Speak() ) ;Console.WriteLine( "Animal sez '{0}'" , anAnimal.Speak() ) ;
return ;}}

运行该程序会得到以下结果:

狗叫:汪汪!动物说“未知的声音”

获得这种行为应该需要程序员走出程序员的方式。子类实例并没有因为它被上转换为它的超类型而停止它的本来面目。相反,你必须明确请求预期的(几乎总是期望的)结果:

public class Animal{public virtual string Speak() { return "unknown sound" ; }}
public class Dog : Animal{public override string Speak() { return "Woof!" ; }}

Call/cc。Call/cc将表示程序其余部分的函数传递给它的主体。

C++最令人烦恼的parse:

struct S{S() {} //default constructor};
int main() {
S s(); // this is not a default construction, it declares a function named s that takes no arguments and returns S.}

“Piet是由David Morgan-Mar设计的一种深奥的编程语言,其程序是看起来像抽象艺术的位图。”

打印Piet的Piet程序

打印Piet的Piet程序

这个C程序在x86和x86-64上打印不同的结果:

#include <stdio.h>int main (void){long a = -1;unsigned b = 1;printf ("%d\n", a > b);return 0;}

早期的FORTRAN,空白并不重要。(反Python!)

DO 20 I = 1, 10

含义:从这里循环到第20行,I从1到10变化。

DO 20 I = 1. 10

含义:将1.10分配给名为DO20I的变量。

有传言说这bug坠毁了一个太空探测器。

在c

int a;

(&a)[0]=10;/*将值10赋给a*/

(&a)[0]等价于*(&a+0),这给了我们*(&a),它只不过是a。

对于那些从未使用过COBOL的人来说,这是一行常见的代码,但它并没有做你可能会想到的事情

第三十次事先知情同意

#:

var a = Double.Parse("10.0", CultureInfo.InvariantCulture); // returns 10var b = Double.Parse("10,0", CultureInfo.InvariantCulture); // returns 100

在不变文化中,逗号不是小数点符号,而是群分隔符。

据我所知,对于一些地区的新手程序员来说,这是一个常见的错误。

好吧,这个也是我一直以来最喜欢的难以找到的bug……将以零开头的整数视为八进制数。这导致了一个只能在早上8到10之间显示的bug:

有一次,我帮助构建了一个自动化回归测试,并在晚上通过cron执行。它几乎适用于20人团队中的每个人——预计每隔一段时间就会有一个开发人员抱怨自动测试失败,但是当手动运行时,一切都很好。甚至没有一次可以手动复制。

好吧,原因是,我们做了一些计算(在bash中)统计数据的基础上的日期命令的输出,这只失败了从8:00到9:59在早上,因为我们会读取小时值为“08”(这是一个非法的八进制值,而“01”-“07”是有效的八进制值,并从“10”起一切都被视为十进制再次)…

C++模板机制是图灵完备的:只要您在运行时不需要输入,您就可以在编译时进行任意计算。任意。或者您可以轻松编写一个永远不会编译但语法正确的C++程序。

VB.NET的设计者做了几件非常愚蠢的事情来保持与Visual Basic 6.0的向后兼容性。当然,这还不足以让它实际上与兼容,只是足以让事情变得更加违反直觉。但最糟糕的是,你不必初始化变量,因为它们已经是,除非在极少数情况下它们不是。

    For i As Integer = 1 To 3TryDim k As Integerk += 1MsgBox(k)Catch ex As ExceptionMsgBox(ex.ToString)End TryNext

这将打印1 2 3。

拥有一个你不能百分之百信任的功能不是一个功能,而是一个bug。说它是设计的,只是让它成为一个设计bug,而不是一个实现bug。

PL/SQL允许将变量和函数名声明为关键字。以下是可编译的PL/SQL:

create or replacefunction functionreturn number  asreturn number;beginfunction.return := 4;return   return;end function;/

这创建了一个名为function的函数。后来:

SQL> select function from dual;
FUNCTION----------4

在JavaScript中,2.0 - 1.1 = 0.8999999999999999。这是规范中浮点数实现的结果,因此它将始终是这样的。

php回调

http://www.php.net/manual/en/language.operators.execution.php

PHP支持一种执行运算符:反引号 (``). 注意,这些不是单引号!PHP将尝试将反引号的内容作为shell命令执行;输出将被返回(即,它不会简单地转储到输出;它可以被分配给一个变量)。

$output = `ls -al`;echo "<pre>$output</pre>";

在代码中“很容易”发现“而不是”。

这也很有趣:

经过很多麻烦,我得出结论,反向勾号运算符(和shell_exec)的返回值为0。我的问题是,我正在处理一个超过500,000行的文件,收到的响应超过100,000行。短暂的停顿后,我被grep关于管道关闭的错误淹没了。

我不知道是否有人提到过。

在Java,它可以返回一个值。它将停止异常的传播并覆盖正常的返回语句。

Java你可能会期待

byte b = 0;b++;

等于

byte b = 0;b = b + 1;

但事实并非如此。事实上,您得到的是编译器错误,作为加法的结果是int类型,因此不能分配给字节变量b。当使用复合算子++时,这里的编译器自动插入转换。所以

b++;

成为

b = (byte) b + 1;

Java缓存整数对象实例128至127的范围内。如果您不知道这一点,以下内容可能有点出乎意料。

Integer.valueOf(127) == Integer.valueOf(127); // true, same instanceInteger.valueOf(128) == Integer.valueOf(128); // false, two different instances

RSL编程语言用于一个奇怪的银行系统。有用于数组的内置类TArray。但是如果您从中继承,每个实例变量都将成为数组的元素。

class (TArray) DerivedArrayvar someField = 56;end
var a = DerivedArray();PrintLn(a.Size);     // => 1PrintLn(a[0]);       // => 56