最奇特的语言function

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

每个答案只有一个function。

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

a[10] 

这很常见。

然而,知名度较低的forms(确实有效)是:

 10[a] 

这意味着与上面相同。

在JavaScript中:

  '5' + 3 gives '53' 

  '5' - 3 gives 2 

在JavaScript中,下面的构造

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

返回undefined是一个语法错误,因为return后在换行符上隐藏的分号插入。 以下工作如你所期望的那样:

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

更糟糕的是,这个工作(至less在Chrome中):

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

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

 return 2 + 2; 

JavaScript真值表:

 '' == '0' // false 0 == '' // true 0 == '0' // true false == 'false' // false false == '0' // true false == undefined // false false == null // false null == undefined // true " \t\r\n" == 0 // true 

资料来源:Doug Crockford

C和C ++中的三字母。

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

这将打印LOL| ,因为trigraph ??! 被转换为|

有趣的是自动装箱和Java中的整数caching:

 Integer foo = 1000; Integer bar = 1000; foo <= bar; // true foo >= bar; // true foo == 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; // true foo >= bar; // true foo == 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]; else return new Integer(i); } 

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

自动装箱会发生什么情况,foo和bar从caching中检索到相同的整数对象,除非明确创build:例如foo = new Integer(42) ,因此在比较引用相等时,它们将是true而不是false。 比较Integer值的正确方法是使用.equals;

引用Neil Fraser (看那个页面的结尾),

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

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

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

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

APL(除了全部),只需要一行就可以编写任何程序。

例如康威在APL的一行生命游戏 :

替代文字http://catpad.net/michael/APLLife.gif

如果这条线不是跆拳道,那么没有什么是!

这里是一个video

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

 #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) ); 

Perl的许多内置variables:

  • $#不是评论!
  • $0$$$? – 就像同名的shellvariables一样
  • $&$' – 奇怪的匹配variables
  • $"$, – 奇怪的variables列表和输出字段分隔符
  • $! – 像errno一样的数字,但strerror(errno)作为一个string
  • $_ – 隐形variables,始终使用,从未见过
  • $#_ – 最后一个子程序参数的索引号…也许
  • @_ – 当前函数的(非)名称…也许
  • $@ – 最后提出的exception
  • %:: – 符号表
  • $:$^$~$-$= – 与输出格式有关
  • $.$% – input行号,输出页码
  • $/$\ – input和输出logging分隔符
  • $| – 输出缓冲控制器
  • $[ – 将您的数组基数从基于0改为基于42的: WHIGHTS!
  • $}什么也没有,奇怪的是!
  • $<$>$($) – 真实有效的UID和GID
  • @ISA – 当前包的直接超类的名称
  • $^T – 脚本启动时间在纪元秒
  • $^O – 当前操作系统名称
  • $^V – 这是什么版本的Perl

来自哪里的地方还有很多。 在这里阅读完整的列表。

PHP处理string中的数字值 。 看到这个以前的答案不同的问题的全部细节,但简而言之:

 "01a4" != "001a4" 

如果您有两个string包含不同数量的字符,则不能视为相等。 前导零是重要的,因为这些string不是数字。

 "01e4" == "001e4" 

PHP不喜欢string。 它正在寻找任何借口,可以发现把你的价值观作为数字。 稍微改变那些string中的hex字符,突然PHP决定这些不是string,他们是科学记数法(PHP不关心你使用引号),它们是等价的,因为数字忽略前导零。 为了加强这一点,你会发现PHP也评估"01e4" == "10000"为真,因为这些是具有相同值的数字。 这是有logging的行为,只是不太明智。

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

你还能从哪里合法地写出如此有趣的expression方式:

 IF IF THEN THEN = ELSE ELSE ELSE = THEN 

IFTHENELSE是variables名称)

要么

 IF IF THEN THEN ELSE ELSE 

IF是variables, THENELSE是子程序)

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

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

更多细节在这里 。

达夫的设备在C!

在C中,可以使用switch语句将do / while隔行。 这里是一个使用这个方法的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); } } 

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

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

在Java中:

 int[] numbers() { return null; } 

可以写成:

 int numbers() [] { return null; } 

在Python中:

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

不是一个跆拳道,而是一个有用的function。

INTERCAL可能是最奇特的语言特征的最佳汇编。 我个人最喜欢的是(几乎)与GOTO相反的COMEFROM语句。

COMEFROM与GOTO大致相反,它可以从代码中的任意点执行状态到COMEFROM语句。 状态转移发生的代码中的点通常作为COMEFROM的参数给出。 是否在指定转移点的指令之前或之后发生转移取决于所使用的语言。 根据所使用的语言,引用相同出发点的多个COMEFROM可能是无效的,不确定的,以某种定义的优先级执行的,甚至可能导致并行或以其他方式同时执行,如在Threaded Intercal中所见。 “COMEFROM x”语句的一个简单例子是一个标签x(它不需要物理地位于其对应COMEFROM附近的任何位置),充当“陷阱门”。 当代码执行到达标签时,控制权传递给COMEFROM后面的语句。 这样做的效果主要是为了使debugging(并理解程序的控制stream程)非常困难,因为在标签附近没有任何迹象表明控件会神秘地跳到程序的另一个点上。

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

 f(1) 

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

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

C:的许多名字空间

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

或与字符:

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

我会说整个Python的空白的东西是我最大的WTFfunction。 的确,在一段时间之后,你或多或less地习惯了这种方式,而现代编辑可以很容易地处理这个问题,但是即使在过去的一年中大部分时间都是Python的开发之后,我仍然相信这是一个糟糕的想法。 我已经阅读了所有的理由,但是说实话,这阻碍了我的生产力。 不是太多,但它仍然是马鞍下的毛刺。

编辑:由评论来看,有些人似乎认为我不喜欢缩进我的代码。 这是一个不正确的评估。 不pipe语言是什么,我是否被强迫,我总是缩进我的代码。 我不喜欢的是缩进定义了一行代码在哪里。我更喜欢明确的分隔符。 除了其他原因,我发现明确的分隔符可以更容易地剪切和粘贴代码。

例如,如果我有一个块缩进4个空格,并将其粘贴在缩进8个空格块的末尾,我的编辑器(所有编辑器?)不知道粘贴的代码是属于8空间块还是外部块。 OTOH,如果我有明确的分隔符,那么明确哪些代码块属于哪个块,以及它应该如何(重新)缩进 – 这是通过智能地查找块分隔符来实现的。

编辑2:一些提供评论的人似乎认为这是我讨厌的一个特性,或者我认为这使Py​​thon成为一种糟糕的语言。 再次,不是真的。 While I don't like it all that much, that's beside the point. The question is about the strangest language feature, and I think this is strange, by virtue of it being something very, very few (but >0) languages use.

I struggled a bit about this:

 1; 

In perl, modules need to return something true .

I'm surprised that no one has mentioned Visual Basic's 7 loop constructs.

 For i As Integer = 1 to 10 ... Next While True ... End While Do While True ... Loop Do Until True ... Loop Do ... Loop While True Do ... Loop Until True While True ... Wend 

Because sticking an ! in front of your conditional is way too complicated!

For those who don't know, bc is an "arbitrary precision calculator language", and I use it quite often for quick calculations, particularly when the numbers involved are large ( $ is the prompt):

 $ bc -lq 12^345 20774466823273785598434446955827049735727869127052322369317059031795\ 19704325276892191015329301807037794598378537132233994613616420526484\ 93077727371807711237016056649272805971389591721704273857856298577322\ 13812114239610682963085721433938547031679267799296826048444696211521\ 30457090778409728703018428147734622401526422774317612081074841839507\ 864189781700150115308454681772032 

bc has been a standard Unix command for a long time.

Now for the "WTF feature". This is from man bc (emphasis mine):

quit : When the quit statement is read, the bc processor is terminated, regardless of where the quit statement is found. For example, "if (0 == 1) quit" will cause bc to terminate.

halt : The halt statement (an extension) is an executed statement that causes the bc processor to quit only when it is executed. For example, "if (0 == 1) halt" will not cause bc to terminate because the halt is not executed.

I always wondered why the simplest program was:

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

Whereas it could be:

 print "Hello World!" 

Maybe this is to frighten computer science students in the first place …

JavaScript is object oriented, right? So running methods on literal strings and numbers should work. Like "hello".toUpperCase() and 3.toString() . Turns out that second one is a syntax error, why? Because the parser expects a number followed by a dot to be a floating point literal. That's not the WTF, the WTF is that you only have to add another dot to make it work:

 3..toString() 

The reason is that the literal 3. is interpreted as 3.0 , and 3.0.toString() works fine.

在JavaScript中:

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

Luckily the kind folks at stackoverflow.com explained the whole thing to me: Why does 2 == [2] in JavaScript?

My biggest most hated feature is any configuration file syntax which includes conditional logic. This sort of thing is rife in the Java world (Ant, Maven, etc. You know who you are!).

You just end up programming in ac**p language, with limited debugging and limited editor support.

If you need logic in your configuration the "Pythonic" approach of coding the configuration in a real language is much much better.

powerbasic (www.powerbasic.com) includes the compiler directive:

 # BLOAT {bloatsize} 

this increases the size of the compiled executable by <bloatsize> bytes. this was put in the compiler in case people creating the executable don't like the small size of the generated executable. it makes the EXE seem bigger to compete with bloated programming languages:)