На свете много языков программирования и каждый из них обладает своими маленькими причудами — странным синтаксисом, необычным функционалом или нестандартными реализациями. Порой это сбивает с толку не только новичков, но и опытных разработчиков. Иногда эти причуды всерьез останавливают от изучения языка или, напротив, становятся известной фишкой.

Есть очень много подобных вещей в языках программирования, но мы выбрали для вас самые известные из них.

Пустые строки в Oracle SQL



Image courtesy Nic Hughes CC BY 2.0

Oracle считает строки нулевой длины эквивалентными NULL. Это существенное отличие от других БД и ANSI/ISO стандарта SQL, который подразумевает, что пустая строка — ранее известное значение, а NULL — неизвестное, и они не могут быть эквивалентны. Это может принести головную боль при написании кода для нескольких RDBMS или переписывании кода.

Возникла путаница в далёком 1979 году, когда вышла первая версия SQL, а соответствующий стандарт ещё не был разработан. Впрочем, в Oracle предупреждают, что в ближайшем будущем подобное явление пустой строки может исчезнуть.

Цитаты:


«Да, это одна из „прекрасных“ фич Oracle DB» — Lukas Eder
«Пустая строка эквивалентна NULL не больше, чем числу 0» — Ben Blank
«ЧТО!? Я так рад, что мы не используем Oracle. Это пугает» — Jeff Davis

+ как универсальный оператор конкатенации в JavaScript



Image courtesy MicroAssist CC BY-SA 2.0

Оператор + перегружен в JavaScript, и выполняет роль как математического сложения чисел, так и конкатенации строк. То есть если один из операндов строчный, а другой числовой, то условно вместо 1+1=2 вы получите ‘1’+1=’11’: JavaScript без предупреждения приведет число к строке.

Причина тому — недостаточный контроль за совместимостью типов. Например, в Python + используется ровно для тех же целей, но у вас ни за что не получится сложить число и символ.

Цитаты:


«Проблема в том, что скрытое приведение типов в выражениях непредсказуемо» — Anonymous
«JavaScript должен выбрасывать исключение в таком случае» — crgwbr
«+ для конкатенации строк — кошмар» — Matteo Riva

Модули Perl должны возвращать true



Image courtesy anthony kelly CC BY 2.0

Каждый модуль в языке Perl должен возвращать true. Если же этого не происходит, то разработчик рискует сильно подпортить себе карму и столкнуться с ошибкой компиляции.

Причина этого ясна и понятна, если понимать, что такое модуль в Perl. Программа компиляции, рассматривая подключённые к коду модули, в первую очередь проверяет их выполняемость. Даже если в модуле нет кода инициализации, Perl все еще ожидает получить на выходе True.

Цитаты:


«Эта штука всегда оставляет у меня тошнотворное чувство» — Drew Hall
«Это не имеет практического применения, учитывая непрерывно возникающее раздражение» — Schwern

Триграфы в C и C++



Image courtesy REUTERS/Gary Hershorn

Языки C и C++ поддерживают триграфы — трёхсимвольные обозначения, которые автоматически конвертируются в односимвольные. Так, например, комбинация ??! выдаст вам |. Если вы хотите максимально запутать необразованного врага, решившего прочитать ваш код, используйте вместо квадратных скобок комбинацию ??( и ??).

Смысл триграфов вовсе не в желании разработчиков языка обфусцировать код, а в том, что когда-то давно многие клавиатуры просто не содержали распространённых ныне символов, например фигурных скобок.

Цитаты:


«Google не поможет, если вы ищете что-то по запросу ??!??!» — Isaac
«Все так ненавидят триграфы, что C99 принес диграфы как альтернативу… еще больше обфускации» — dododge
«Радость триграфов — делает C нечитаемым с 1977 года» — Martin Beckett

Чувствительность к регистрам PHP



Image courtesy Gregg O'Connell CC BY 2.0

В то время как большинство языков программирования чувствительны к регистру, в PHP названия функций, классов и методов к нему нечувствительны. Но что наиболее сильно поражает разработчиков — то, что имена переменных, констант и свойства классов всё же регистрозависимы.

Доподлинно неизвестно, откуда повелось такое расхождение, но наиболее вероятный вариант — изначальное желание создателей PHP выделить интерфейс CGI в отдельный полноценный язык программирования.

Цитаты:


«Ну, это PHP. Не удивляйтесь» — Grzechooo
«Вот почему PHP-программисты используют подчеркивания вместо CamelCase, называя свои функции» — paperstreet7
«Я не имею ни малейшего представления о том, как создавать языки программирования...» — создатель PHP Rasmus Lerdorf
«Есть ли в PHP что-то, не вызывающее недоумения?» — Lambda Fairy

Истинный ноль в Ruby



Image courtesy DaveBleasdale CC BY 2.0

В Ruby 0 == TRUE. Это неожиданно, расходится с большинством других языков, включая Python и C, где 0 всё-таки FALSE, и часто сбивает с толку новичков в Ruby.

Причина в том, что в Ruby только boolean false и нулевое значение (nil) вычисляются в FALSE; все остальное имеет значение TRUE. 0 рассматривается как любое другое число.

Цитаты:


«Это может быть странным, если бы я не считал это неплохим» — Chris Lutz
«Вот почему я люблю Ruby. Мне не приходится иметь дело с таким zero-false злом» — Edditoria
«0==true // аргх, компилятор C в моей голове взорвался!!» — kenny

Пробелы в Python



Image courtesy Paul Kitchener CC BY 2.0

Вместо пунктуации или ключевых слов Python использует отступ для обозначения блока, к которому принадлежит строка кода. Неправильное количество пробелов или смешивание пробелов и табуляции может привести к ошибкам.

Создатели языка стремились сделать код более читабельным и уменьшить количество нажимаемых клавиш за счет того, что многие редакторы и IDE расставляют отступы автоматически.

Цитаты:


«Нет, правда: это то, что мешает мне когда-либо полюбить Python» — wazoox
«Я обожаю отступы в Python, но есть ньюанс: при копировании и вставке кода из Интернета это часто приводит к необходимости дополнительной очистки» — Greg
«Если вам нужны навязанные отступы, вы слишком ленивы» — Joris Meys

Массивы в C подчиняются арифметике указателей



Image courtesy BlueGum CC BY-ND 2.0

Кроме того, что можно получить ссылку на элемент массива как a[i], можно получить ее как i[a].

Причина в том, что массивы в C — указатели на блоки памяти, поэтому a[i]=*(a+i)=*(i+a)=i[a].

Цитаты:


«… это бесценно, когда вы участвуете в конкурсе обфускации C...» — Confusion
«Я не расцениваю это как особенность, это просто взгляд на ядро C. Все для указателей и максимально быстрого получения доступа к памяти. В некотором смысле это красиво» — Michael Neale

Предопределённые переменные Perl



Image courtesy Emily Mathews CC BY 2.0

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

Они служат для выдачи информации или обеспечения доступа к различным аспектам программы. Так, например, $@ — сообщение об ошибке, $$ — идентификатор процесса, $^V — используемая версия Perl. Новичкам приходится часто заглядывать в документацию.

Цитаты:


«Очень раздражает» — MatrixFrog
«Классная штука для однострочников, кстати» — niXar
«Я думаю, что худшие из них — $@ и @$. Работают оба, но я до сих пор не знаю, что делает второй...» — Artem Russakovskii
«Между прочим, есть еще серьезная проблема с этими переменными: они не гуглятся!» — malvim

Автоматическая вставка точки с запятой в JavaScript



Image courtesy Nate Angell CC BY 2.0

JavaScript требует установку точки с запятой в конце каждого законченного выражения. В случае, если этого сделано не было, а после идёт, скажем, пустая строка, JavaScript расценивает это как невнимательность разработчика и самостоятельно вставляет точку с запятой, что иногда помогает, но нередко приводит к ошибкам и неожиданному поведению программы.

Изначально вставка точки с запятой предназначалась для удобства, чтобы сделать C-подобный синтаксис JavaScript проще для новых разработчиков.

Цитаты:


«У вас точно будут проблемы, если вы разрабатываете язык с расчетом на то, что ваши пользователи идиоты» — Rob Van Dam
«Совет: выясните нужное место для точки с запятой и поставьте ее. Это лучше всего» — Doug Crockford
«Вставка точки с запятой — одна из злейших частей JavaScript» — fennec

Автоупаковка в Java и кеширование Integer



Image courtesy Erich Ferdinand CC BY 2.0

Java автоматически упаковывает примитивы в объекты, например, int в Integer. В целом ничего страшного, но Integer кешируется, если его значение лежит между -128 и 127. Это может привести к непредвиденным результатам в случае сравнения автоупакованных объектов, так как программа будет присваивать значение TRUE, если оба объекта имеют значение от -128 до 127, и FALSE во всех остальных случаях.

Autoboxing уменьшает количество кода, а кеширование Integer повышает производительность. Но нужно помнить о подводных камнях.

Цитаты:


«Вот результат преждевременной оптимизации» — Joschua
«Это не распространенная ошибка, но хороший повод использовать нативные типы Java для чисел, логических переменных и так далее» — Ravi Wallau
«Я так рад, что пишу на C#» — Will

Автор перевода: Илья Бубнов
___

P. S. Выбрать направление и начать обучаться по одной из технологий, о которых рассказывалось выше, можно на сайте GeekBrains.

Комментарии (170)


  1. vladon
    27.03.2016 13:53
    +1

    В C++17 триграфы убрали.


    1. Athari
      27.03.2016 18:42
      +1

      А до этого отключили по умолчанию во всех компиляторах, вроде.


  1. goral
    28.03.2016 09:07
    +1

    Еще в MySql CONCAT('colum1','column2') вернет null если в column2 будет null. Неудобно, когда надо соединить firstname, middlename и lastname, ведь middlename есть не у всех.


    1. vlivyur
      28.03.2016 15:24
      +1

      Это для всех SQL справедливо, кроме Oracle.


  1. ivorobioff
    28.03.2016 09:07
    +1

    Но что наиболее сильно поражает разработчиков — то, что имена переменных, констант и свойства классов всё же регистрозависимы.
    Вот тут не соглашусь, так как за все время программирования на пхп не сталкивался с этой проблемой решил специально проверить данное утверждение в PHP 7. Все работает в независимости он регистра.
    Как обычно, на пхп гонят завистники :)
    Myth Busted!


    1. alexkunin
      28.03.2016 13:05
      +2

      Проблемка будет, если на регистро-зависимой файловой системе у вас класс называется не так, как файл. А еще константы таки зависимы:

      define('ABC', 1);
      echo ABC;
      echo abc; // Notice: Use of undefined constant abc — assumed 'abc' in [...][...] on line 3

      Или вы про const в классах? Так тоже ж зависят от регистра:

      class a { const b=1; }
      echo a::b;
      echo a::B; // Fatal error: Uncaught Error: Undefined class constant 'B' in [...][...]:3

      И свойства классов тоже:

      class a { var $b=1; }
      $i = new a();
      echo $i->b;
      echo $i->B; // Notice: Undefined property: a::$B in [...][...] on line 4

      Проверял тут — http://sandbox.onlinephpfunctions.com/, версия 7.0.3.


  1. d_fomenok
    28.03.2016 09:07
    +1

    Про С++ даже не интересно. Все знают, что в нём много устаревших вещей, которые никак не выпилят для обратной совместимости. И на практике никто не использует триграфы.



  1. FRiMN
    30.03.2016 01:40

    Всякие особенности Python:
    https://docs.python.org/2/faq/design.html


  1. Lence
    30.03.2016 10:30

    К особенностям Oracle можно отнести механизм sequence, довольно отличительная черта от остальных RDBMS строящие таблицы с автоинкрементном. А вот строки нулевой длины эквивалентны NULL удобно. Не хотелось бы, чтоб это правило в дальнейшем поменялось.


    1. alexkunin
      30.03.2016 16:13

      Так Postgres то же самое делает, вроде. Просто дает удобный «макрос» SERIAL, который делает все сам, но работает только во время создания таблиц. Если же нужно изменить существующую, то все придется руками делать — CREATE SEQUENCE и т.д.

      Но это неплохо, на самом деле, потому что такой подход дает больше возможностей. А еще это часть стандарта, и встречается в других СУБД.


    1. VolCh
      31.03.2016 00:01

      Остальные — это MySQL? Postgre знает sequence (по сути только его и знает), MS знает.


      1. Lence
        31.03.2016 14:09

        В MS SQL сравнительно недавно появился sequence. На практике пока встречаю, что многие еще не используют данный механизм


  1. Lence
    30.03.2016 16:24

    Конечно же от этого больше плюсов — сквозные "айдишки", кэширование, шаг инкримента, начальная/конечная позиция. Но реакция пользователей других СУБД примерно такая же как и когда узнают про is null, вместо = ''


  1. FRiMN
    02.04.2016 13:51

    В Perl есть два разных набора операторов сравнения — один для строк, другой для чисел: http://ru.perlmaven.com/sravnenie-skalarov-v-perl



    Нужно следить за кавычками в print:
    @i = ('a', 'b', 'c');
    print "@i";    # a b c
    print @i;      # abc

    Списковый оператор print. Для запятых слева от него он имеет наименьший приоритет, но повышает приоритет правой запятой.
    @i = ('a', 'b', print 'c', 'd');
    print "\n",@i;
    # cd
    # ab1