首页 文章

最奇怪的语言特征

提问于
浏览
975

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

Please only one feature per answer.

30 回答

  • 1296

    APL (other than ALL of it),能够在一行中编写任何程序 .

    例如Conway's Game of Life in one line in APL

    alt text http://catpad.net/michael/APLLife.gif

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

    这是一个video

  • 138

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

    a[10]
    

    这很常见 .

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

    10[a]
    

    这意味着与上述相同 .

  • 662

    在JavaScript中:

    '5' + 3 gives '53'
    

    '5' - 3 gives 2
    
  • 1861

    在JavaScript中,以下构造

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

    返回undefined是一个语法错误,因为在 return 之后在换行符上插入了偷偷的分号分号 . 以下工作正如您所期望的那样:

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

    更糟糕的是,这个也适用(至少在Chrome中):

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

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

    return
        2 + 2;
    
  • 204

    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

  • 289

    C和C中的三角形 .

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

    这将打印 LOL| ,因为三字符 ??! 被转换为 | .

  • 184

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

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

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

    自动装箱会发生什么,除非明确创建,否则foo和bar都会从缓存中检索相同的整数对象:例如: foo = new Integer(42) ,因此在比较参考相等时,它们将是真的而不是假的 . 比较Integer值的正确方法是使用 .equals;

  • 150

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

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

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

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

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

    可以使用C模板的奇怪之处,最好通过"Multi-Dimensional Analog Literals"来演示,它使用模板来计算"drawn"形状的区域 . 以下代码对于3x3矩形是有效的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) );
    
  • 160

    Perl的许多内置变量:

    • $# - not 评论!

    • $0$$$? - 就像shell变量一样

    • $&$' - 奇怪的匹配变量

    • $"$, - 列表和输出字段分隔符的奇怪变量

    • $! - 像 errno 作为数字但 strerror(errno) 作为字符串

    • $_ - the 隐身变量,始终使用且从未见过

    • $#_ - 最后一个子程序参数的索引号...也许

    • @_ - 当前函数的(非)名称...也许

    • $@ - 最后引发的异常

    • %:: - 符号表

    • $:$^$~$-$= - 与输出格式有关

    • $.$% - 输入行号,输出页码

    • $/$\ - 输入和输出记录分隔符

    • $| - 输出缓冲控制器

    • $[ - 将您的阵列基础从0更改为从1到基于42:WHEEE!

    • $} - 什么都没有,奇怪的是!

    • $<$>$($) - 真实有效的UID和GID

    • @ISA - 当前包的直接超类的名称

    • $^T - epoch秒中的脚本启动时间

    • $^O - 当前操作系统名称

    • $^V - 这是什么版本的Perl

    那些来自的地方还有很多 . 阅读完整列表here .

  • 134

    PHP's handling of numeric values in strings . 有关详细信息,请参阅this previous answer to a different question,但简而言之:

    "01a4" != "001a4"
    

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

    "01e4" == "001e4"
    

    PHP不喜欢字符串 . 它正在寻找任何可以找到将你的 Value 观视为数字的借口 . 稍微更改这些字符串中的十六进制字符,突然PHP决定这些字符串不再是字符串,它们是科学记数法中的数字(PHP并不关心您使用引号)并且它们是等效的,因为前导零被忽略数字 . 为了强调这一点,您会发现PHP还将 "01e4" == "10000" 评估为true,因为这些是具有等效值的数字 . 这是记录在案的行为,它不是很明智 .

  • 189

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

    还有什么地方可以合法地写下这样有趣的表达:

    IF IF THEN THEN = ELSE ELSE ELSE = THEN
    

    IFTHENELSE 是变量名称)

    要么

    IF IF THEN THEN ELSE ELSE
    

    IF 是变量, THENELSE 是子程序)

  • 292

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

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

    更多细节here .

  • 126

    Duff's device in 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);
        }
    }
    
  • 130

    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]);
    }
    
  • 134

    在Java中:

    int[] numbers() {
      return null;
    }
    

    可以写成:

    int numbers() [] {
      return null;
    }
    
  • 190

    在Python中:

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

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

  • 796

    INTERCAL可能是最奇怪的语言功能的最佳纲要 . 我个人最喜欢的是COMEFROM声明(几乎)与GOTO相反 .

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

  • 135

    不是一个语言功能,而是一个实现缺陷:一些早期的Fortran编译器通过使用常量池实现了常量 . 所有参数均通过引用传递 . 如果您调用了一个函数,例如

    f(1)
    

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

  • 150

    不知道它是否可以被认为是一种语言特性,但是,在C中,几乎任何与模板相关的编译器错误都会给全世界的许多C程序员每天提供相当数量的WTF :)

  • 574

    我会说Python的整个空白是我最强大的WTF功能 . 确实,你或多或少习惯了一段时间后现代编辑人员可以轻松应对,但即使在过去一年大部分时间进行python开发之后,我仍然相信这是一个坏主意 . 我已经阅读了它背后的所有推理但老实说,它妨碍了我的工作效率 . 不是很多,但它仍然是马鞍下的毛刺 .

    edit: 根据评论判断,有些人似乎认为我总是缩进我的代码,无论语言是什么,我是否喜欢它是缩进来定义一行代码所在的块 . 我更喜欢显式为此划界 . 除了其他原因之外,我发现明确的分隔符可以更轻松地剪切和粘贴代码 .

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

    edit 2: 一些提供评论的人似乎认为这是我讨厌的一个功能,或者我认为这使得python成为一种糟糕的语言 . 再次,不是真的 . 虽然我不赞成这一点 . 问题是关于最奇怪的语言特征,我认为这很奇怪,因为它是非常非常少(但> 0)种语言使用的东西 .

  • 872

    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);
    }
    
  • 325

    我对此有点挣扎:

    1;
    

    在perl中,模块需要返回真实的东西 .

  • 282

    我'm surprised that no one has mentioned Visual Basic' s 7 循环结构 .

    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
    

    因为坚持!在你的条件面前是太复杂了!

  • 282

    对于那些不知道的人, bc 是"arbitrary precision calculator language",我经常使用它进行快速计算,特别是当涉及的数字很大时( $ 是提示):

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

    bc 已经很长时间了standard Unix command .

    现在为"WTF feature" . 这是来自 man bc (强调我的):

    quit:当读取quit语句时,无论在哪里找到quit语句,都会终止bc处理器 . 例如,“if(0 == 1)quit”将导致bc终止 . halt:halt语句(扩展名)是一个执行语句,它导致bc处理器仅在执行时退出 . 例如,“if(0 == 1)halt”不会导致bc终止,因为没有执行暂停 .

  • 373

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

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

    而它可能是:

    print "Hello World!"
    

    也许这首先是吓唬计算机科学的学生......

  • 214

    JavaScript是面向对象的,对吧?因此,对文字字符串和数字运行方法应该有效 . 喜欢 "hello".toUpperCase()3.toString() . 原来第二个是语法错误,为什么?因为解析器期望一个点后面跟一个数字作为浮点文字 . 那不是WTF,WTF是你只需要添加另一个点来使其工作:

    3..toString()
    

    原因是文字 3. 被解释为 3.03.0.toString() 工作正常 .

  • 113

    在JavaScript中:

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

    幸运的是,stackoverflow.com的善良的人向我解释了整个事情:Why does 2 == [2] in JavaScript?

  • 322

    我最讨厌的功能是任何包含条件逻辑的配置文件语法 . 这种事情在Java世界中很普遍(Ant,Maven等等 . 你知道你是谁!) .

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

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

  • 132

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

    # BLOAT {bloatsize}
    

    这会使编译的可执行文件的大小增加 <bloatsize> 个字节 . 如果创建可执行文件的人不喜欢生成的可执行文件的小尺寸,则将其放入编译器中 . 它使得EXE看起来更大,可以与臃肿的编程语言竞争:)

相关问题