IT技术博客大学习 共学习 共进步

最奇特的编程语言特征

外刊IT评论 2012-01-27 18:05:22 浏览 2,781 次

目前为止,据我个人观察,从语法角度上讲,最被人诟病的一种语言应该是LISP语言了。打开这种语言的代码,一眼望去,满目全是括弧,一层套一层。这种语言特征最大的问题是,它不符合人们通常的思维习惯。LISP语言的这个特点是个整体的语言现象,而任何一种语言其实也都有一些个别的很奇特的东西,其中有些会奇怪的让你摸不着头脑。有一个好事者在一个帖子上征集各种语言里不合常理的地方,结果收集到了320多条,问题最大最多的语言算是Javascript了,另外还有C,Java,Python,PHP等等。下面列出的是其中最有趣的几条。

  1. 在C语言里,数组可以这样索引取值:
    a[10] 

    这种写法相当常见。

    然而,还有一种很少见的写法(绝对可用!)是这样的:

    10[a] 

    这两种写法的效果是一样的。

  2. 在JavaScript里:
     \'5\' + 3 结果是 \'53\' 

     \'5\' - 3 结果是 2 
  3. 在JavaScript里,下面的语法结构
    return
    {
        id : 1234,
        title : \'Tony the Pony\'
    };

    会提示语法错误:”缺少分号”。而下面的写法却能按你预想的结果运行:

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

    更让人郁闷的是下面的写法竟然可以(至少在谷歌浏览器里是这样的):

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

    下面的例子也是同样的问题引起的,但不会报错,而你却得不到想要的结果:

    return
        2 + 2;
  4. 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
  5. Java里有趣的自动打包(auto boxing)和IntegerCache:
    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源代码里你很快能翻出下面的内容:

    int

    注意; IntegerCache.high 的值,如果你不设置它,缺省是 127。

    自动打包(auto boxing)过程中发生的事情是:除非显式的创建:比如 foo = new Integer(42) ,否则 foo 和 bar 都是从缓存中取出的整数,当比较值时,它们会返回 true。正确的比较Integer的方式是使用 .equals 。

  6. 在Java里:
    try {
        return true;
    } finally {
        return false;
    }

    在Python和JavaScript也可以这样写。这样写的结果是什么?当作一个保留的问题考考大家吧。

  7. 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) );
  8. PHP处理数字字符
    \"01a4\" != \"001a4\"

    如果两个字符串来的字符数不相等,它们不可能相等。前面的零非常重要,因为他们是字符而不是数字。

    \"01e4\" == \"001e4\"

    PHP不太喜欢字符,它会寻找任何的借口来把你提供的值当作数字。把这些十六进制的字符串稍微做些改动,PHP马上认为它们不再是字符,而是数字。它们是按科学计数法写的数字(PHP并不在意你是否用了引号),它们是相等的,因为对于数字来说,前面的零是可以忽略的。更强化这个事实的例子是,你会发现PHP认为 “01e4″ == “10000″ 是正确的,因为作为数字,它们的值是相当的。这是一个被特别提醒的语言特征,原因就是它不太合理。

  9. 在一些没有保留字、关键字的语言里,例如PL/I, 你可以写出这样有趣而且合法的代码语句:
    IF IF THEN THEN = ELSE ELSE ELSE = THEN

    (IF, THEN, ELSE 都是变量名),或

    IF IF THEN THEN ELSE ELSE

    (IF 是变量,THEN 和 ELSE 都是函数)

  10. JavaScript里八进制的转换:
    parseInt(\'06\') // 6
    parseInt(\'07\') // 7
    parseInt(\'08\') // 0
    parseInt(\'09\') // 0
    parseInt(\'10\') // 10
  11. 在C语言里,你可以把 do/while 语句和 switch 交织在一起,下面就是一个使用这种方法的内存拷贝的例子:
    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);
        }
    }
  12. 在Python中:
    >>> x=5
    >>> 1>> 1
    在Java中: int[] numbers() {
      return null;
    }
    可以被写成:int numbers() [] {
      return null;
    }

如果你觉得还没看够,请到这里,还有更多。

建议继续学习

  1. 我是如何学习计算机编程的 (阅读 181,023)
  2. 面向“接口”编程和面向“实现”编程 (阅读 13,762)
  3. 我学编程时犯的最大两个错误 (阅读 7,864)
  4. 提高编程技能最有效的方法 (阅读 6,402)
  5. 函数式编程很难,这正是你要学习它的原因 (阅读 5,303)
  6. 如果你看不见你还能编程吗? (阅读 4,903)
  7. 那些曾伴我走过编程之路的软件 (阅读 4,764)
  8. 函数式编程 (阅读 4,585)
  9. 你从未听说过的一种编程方式 (阅读 4,304)
  10. 也谈编程改革 (阅读 4,243)