Странные возможности языков программирования

четверг, 27 января 2011, Александр Краковецкий

Очень познавательное обсуждение на StackOverflow - какие специфические возможности языков программирования вы знаете? Вот небольшой обзор топовых возможностей.

Язык С и С++

В языке С доступ к массиву может быть осуществлен двумя способами:

a[10]

и

10[a]

А все потому, что a[10] означает *(a+10), а 10[a] - *(10+a).

Вот такая функция выведет "LOL|", так как "??!" конвертируется в "|".

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

JavaScript

На первом месте проблемы с перегрузкой операторов:

'5' + 3 получаем '53'
'5' - 3 получаем 2

Проблема в том, что в первом случае используется конкатенация строк, а во втором – операция вычитания.

Похожие проблемы наблюдаются в PHP, поэтому нужно правильно использовать операторы сравнения "==" и "===".

На втором месте не корректная обработка двоеточия после return:

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

Такой код будет работать корректно:

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

И даже такой (по крайней мере в хроме):

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

Похожая проблема будет наблюдаться здесь:

return
    2 + 2;

На третьем месте (не)логическая система:

''        ==   '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

Еще один перл JavaScript:

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

После того, как посмотришь решение, можно понять, в чем проблема, но все же зачем так травмировать разработчиков?

Правильные варианты:

parseInt('08',10); // 8
Number('08'); // 8

Java

Просто феерический пример, связанный с автобоксингом и кэшем Integer:

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

Причина кроется здесь:

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

Один из самых ярких комментариев:

"So glad I'm a C# programmer."

Но для C# есть тоже интересные задачки):

int x = 0;
bool result; 
result = x == x;
result = (object)x == (object)x; 
result = (System.Object)x == (System.Object)x; 
result = (int)(object)x == (int)(object)x;
result = (float)x == (float)x; 
result = (int)x == (int)x; 
result = (int)x == (float)x;
result = (float)(int)x == (int)(float)x; 
result = (System.Int32)x == (System.Int32)x; 
result = x.ToString() == x.ToString(); 
result = (object)x.ToString() == (object)x.ToString(); 

Но тут все было более-менее предсказуемо (хотя я ошибся два раза при быстром просмотре). Ответы не пишу, чтобы вы могли потренироваться самостоятельно.

Еще один пример. Есть код:

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

В этом случае вернет false. Такая же ситуация в JavaScript и Python.

В C# такой код не скомпилируется и выдаст

"Control cannot leave the body of a finally clause".

Еще один пример, хотя и не такой страшный:

int[]  numbers() {
  return null;
}

Этот код может быть записан как:

int  numbers() [] {
  return null;
}

без потери функционала.

Perl

Perl попал в этот список, потому что Perl – это сплошной перл, а точнее идейный вдохновитель или родитель (не знаю, что там раньше было) регулярных выражений.

Чего только стоят такие переменные:

$.
$_
$_#
$$
$[
@_

Например, «$=» показывает текущий размер страницы. Ох!!!

Это самые яркие «фичи» языков. Рекордсмен – JavaScript, но практически все языки могут похвалиться своими скрытыми возможностями. Может поделитесь своими вариантами?


Ищите нас в интернетах!

Комментарии

Свежие вакансии