LINUX.ORG.RU

Подлости языков программирования: приглашаю покритиковать и пополнить


0

2

По мере знакомства с различными языками программирования обязательно натыкаешься на разные подлости. Я их для коллекции записываю :-)

Пока коллекция не очень большая. Я решил занести её в Википедию:
http://ru.wikipedia.org/wiki/Ловушки_языков_программирования

Надеюсь, будет интересно не только мне :-). Приглашаю критиковать и дополнять.

Кстати, ещё на эту тему:
http://alenacpp.blogspot.com/2008/10/blog-post.html
http://www.ruscript.net/scripts/32/

помню в vb6 функция dir возвращала не ту папку или не папку уже непомню

guilder
()

Прикольно, собрать бы побольше таких материалов, да в учебники вписывать ))) было бы полезно для новичков)))

ЗЫ «if (a = b)» - часто парился в детстве, математика в школе дает только символ «=» :D

erfea ★★★★★
()

Это не ловушки, а просто частые ошибки, совершаемые новичками. И то, чаще всего, один раз.

smh ★★★
()

Арифметика с плавающей точкой


Напомнило xkcd.com/394:
kb - INTEL Kilobyte - 1023.937528 Bytes - Calculated on Pentium FPU

А майндфаков с пред/пост-инкрементом i в одной строке почему нет?

adriano32 ★★★
()
Ответ на: комментарий от erfea

> Ну про неочевидности для начающего кодера...

как можно начать писать на каком-то языке, не ознакомившись с его основами?

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

как можно начать писать на каком-то языке, не ознакомившись с его основами

Пройдитесь по ссылочке, итератор выдаваемый методом end() в stl реально не очень то очевидная штука (собственно как и практически весь stl). Считаю полезным давать такую инфу начинающим кодерам, хреново наступать на грабли известные любому хоть немного опытному кодеру ))))

erfea ★★★★★
()
Ответ на: комментарий от note173

> Неправда. «123» == «123». «1» + «23» == «123». Integer.toString(«1») + «23» != «123»

это тонкости оптимизации, фактически выражение («123» == «123») не обязано возвращать true (если конечно эта оптимизация не прописана в стандарте Явы)

korvin_ ★★★★★
()
Ответ на: комментарий от erfea

> Пройдитесь по ссылочке, итератор выдаваемый методом end() в stl реально не очень то очевидная штука

я сходил по ссылке изначально, и мне такое поведение не кажется неочевидным, ибо проход по односвязному списку (а интерфейс итераторов — это проход по односвязному списку независимо от реализации) предполагает для определения окончания списка сравнение текущего значения переменной-списка с пустым списком (nil/null), а не с последним элементом

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

Когда ты впервые пишешь что-то сложнее хеловорлда, это не так уж и очевидно. Вы видимо плохо помните себя, когда начинали кодить...

erfea ★★★★★
()
Ответ на: комментарий от erfea

> Когда ты впервые пишешь что-то сложнее хеловорлда, это не так уж и очевидно.

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

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

Ну знаете ли, не всегда обращаешь внимание на все тонкости, тем более что приходится держать массу новой (ещё не усвоенной как 2х2=4 информации, пусть и совершенно элементарной позже). Все начинающие программисты нарываются на какие-то грабли, которые потом кажутся смешными ))))

erfea ★★★★★
()
Ответ на: комментарий от erfea

> Ну знаете ли, не всегда обращаешь внимание на все тонкости, тем более что приходится держать массу новой (ещё не усвоенной как 2х2=4 информации, пусть и совершенно элементарной позже). Все начинающие программисты нарываются на какие-то грабли, которые потом кажутся смешными ))))

нарываются, не спорю, и я в общем-то начинающий и нарываюсь, не столько с использованием ЯП, сколько с архитектурой системы, но указанные в статье ситуации не относятся к таким граблям, это базовые вещи, которые нужно знать перед началом использования языка/языковых-средств

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

Не обязано, прописана.
((int)1 + «23»).intern() == «123»

note173 ★★★★★
()

Логические операции вместо поразрядных и наоборот
a = b && c
a = b || c

if ((a) | (b))
if ((a) & (b))

Это условие будет всегда ложным на архиектурах где char по умолчанию unsugned
char a;
...
if (a < 0)

Тот кто свои ошибки списывают на подлость компиляторов - это быдлокодер в квадрате ;-)

anonymous
()
Ответ на: комментарий от korvin_

Тем не менее, оно не лишнее. Сам нарывался из приведенного там только на один пункт, трудно ж блин было привыкнуть что «=» присвоить :D Благо ошибка легко находится беглым взглядом на код )))

erfea ★★★★★
()

Уж если написал, про проверку равенства в С, то почему забыл про break в switch? А о пропущенном break-е компиляторы не предупреждают.

Begemoth ★★★★★
()

> Я решил занести её в Википедию:

Выпилят как орисс.

По мере знакомства с различными языками программирования обязательно натыкаешься на разные подлости.

Я вот за больше года юзания Ruby, еще не нашел ни одной подлости. Абсолютно системный синтаксис, продуманная стандартная библиотека. С юникодом только были проблемы, но постепенно ситуация выправляется.

geekless ★★
()
Ответ на: комментарий от geekless

А должны?

Я бы предпочёл, чтобы предупреждали, также как предупреждают использовании не всех элементов перечисления в case-ах.

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

Не должны они о пропущенном break'е предупреждать: может, я его специально пропустил? А если в таком случае gcc будет предупреждение выдавать, ни одна программка с флагом -Werror не соберется.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

> Не должны они о пропущенном break'е предупреждать: может, я его специально пропустил? А если в таком случае gcc будет предупреждение выдавать, ни одна программка с флагом -Werror не соберется.

С каким-нибудь -Wextra можно предупреждать. Там и так море всяких предупреждений. Опять же, про неполное покрытие enum'а case'ами.

const86 ★★★★★
()

Да, про числа с плавающей точкой вы верно подметили. Я недавно сталкивался с таким «приколом»: преобразование координат при их типе float периодически давало странные глюки в отображении, сменил на double - пошло намного лучше. В алгоритме для коррекции положения объекта при зуме тоже вышла интересная история, оказалось, что

ZZ = window->Zoom*Zoom_factor - window->Zoom;
и
ZZ = window->Zoom*(Zoom_factor - 1.);
не одно и то же (все типы данных - double). Второе выражение дает неверные результаты.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от const86

Опять же, про неполное покрытие enum'а case'ами.

А что, разве у вас gcc не предупреждает в этом случае? Меня, например, достало прописывать в switch'ах case'ы для всех членов enum'а, т.к. иначе gcc ругается и вываливается с ошибкой.

Eddy_Em ☆☆☆☆☆
()

Вот ещё из распространённого

int a = 5;
double x = a/2;

Теперь x == 2. Ибо обе переменных — int, соответственно применяется целочисленная арифметика. Если требуется операция с плавающей запятой, надо писать a/2.0 или double(a)/2, ну в общем ясно.

Меня, например, достало прописывать в switch'ах case'ы для всех членов enum'а, т.к. иначе gcc ругается и вываливается с ошибкой.

А мне эта фича нравится.

Ещё один косяк у новичков — неправильно воспринимают работу switch и забывают писать break. Ну хотя он почти сразу вылечивается.

Obey-Kun ★★★★★
()
Ответ на: комментарий от Eddy_Em

> Меня, например, достало прописывать в switch'ах case'ы для всех членов enum'а

default спасет отца русской демократии

aho
()
Ответ на: комментарий от korvin_

это тонкости оптимизации, фактически выражение («123» == «123») не обязано возвращать true (если конечно эта оптимизация не прописана в стандарте Явы)

Все строки известные на этапе компиляции заносятся в StringPool и соотвественно для одинаковых из них == будет выдавать true.

Это важно т.к. даёт возможность делать, например:

synchronized ("my synchronized string" ) { }

qnikst ★★★★★
()
Ответ на: комментарий от aho

default спасет отца русской демократии

Можно, конечно, проверить: не ругнется ли gcc на

default:
break;

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

ну это же стандартные проблемы при работе с числами с плавающей точкой, независимо от языка (если используется IEEE реализация).

qnikst ★★★★★
()

>Я решил занести её в Википедию

«Не академический материал, отсутствуют ссылки на авторитетные источники» и т.п. Готовая статья под удаление с учётом нынешней политики Педивикии.

KRoN73 ★★★★★
()
Ответ на: комментарий от RedPossum

раз уж начал, добавь из жабы: String A=«123»; String B=«123»; >System.out.println(A==B);

false

Это мелочи по сравнению с:

Integer a = 127; Integer b = 127;
System.out.println(a==b);
>> true

Integer a = 128; Integer b = 128;
System.out.println(a==b);
>> false

На PHP такие грабли есть: [Глобально и надёжно][Не наступите] Не знал, не знал :D

KRoN73 ★★★★★
()
Ответ на: комментарий от Eddy_Em

>> Опять же, про неполное покрытие enum'а case'ами.

А что, разве у вас gcc не предупреждает в этом случае?

Я чувствую себя непонятым. Предупреждает. И на мой взгляд, это предупреждение того же уровня «дотошности», что и предупреждение об отсутствующем брейке. И я считаю, хорошо бы, чтобы оба были в -Wextra.

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

Меня, например, достало прописывать в switch'ах case'ы для всех членов enum'а, т.к. иначе gcc ругается и вываливается с ошибкой.

Достаточно простого default: break; :)

const86 ★★★★★
()
Ответ на: комментарий от const86

И ещё, я считаю, что -Werror увлекаться не надо

А мне нравится: пока все ошибки не исправишь, код не скомпилируется. А то так в одном месте предупреждение, в другом предупреждение, а в итоге - ХЗ что получается. Те же преобразования типов часто выкидывают «веселенькие» фокусы...

Eddy_Em ☆☆☆☆☆
()

Главная подстава всех лиспов, хаскелей и прочей маргинальщины — выучив язык, осознать, что девки всё равно не дают. Да и сам язык никому нах не впился.

anonymous
()

Добавь в C# еще - если подключиться к эвенту 1 раз, а потом 2 раза отключиться, то на следующее подключение события все-равно не будет.

По сути это: 0 + 1 - 2 + 1 = 0. :)

Я с этим попал как-то.

hibou ★★★★★
()

Статью удалят, так что время потрачено зря. Нет значимости, нет АИ.

zombiegrinder_6000
()
Ответ на: комментарий от Eddy_Em

А мне нравится: пока все ошибки не исправишь, код не скомпилируется.

Вопросов нет. Но если это не ошибка? :)

Меня бесят в этом смысле PHP-шные IDE, которые выдают ошибки на выражениях, типа:

if($page = $this->get_page())
    return $page->content();

Ну никогда не путаю я присваивание и сравнение :) За последние лет пять был только один такой случай, и то — из-за опечатки. Приходится лепить лишние скобки:

if(($page = $this->get_page()))
    return $page->content();

или делать лишний вызов функции:

if($this->get_page())
    return $this->get_page()->content();

Или, вообще, забивать на предупреждения… Рискуя в другой раз зевнуть, действительно, потенциальную ошибку :)

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> http://ruby.inuse.ru/article/podvodnye-kamni-stringsub ?

Это ни коим образом не подводные камни. Вот если бы стандартный метод замены не предоставлял возможности подставлять подвыражения из совпавшего фрагмента — вот это бы как раз был бы «камень», и совсем не подводный.

geekless ★★
()
Ответ на: комментарий от Eddy_Em

>> И ещё, я считаю, что -Werror увлекаться не надо

А мне нравится: пока все ошибки не исправишь, код не скомпилируется.

Не надо выдёргивать из контекста. Я имел в виду, что не надо включать -Werror при завышенном уровне предупреждений (сверх того, что я описал выше).

const86 ★★★★★
()
Ответ на: комментарий от anonymous

> Главная подстава всех лиспов, хаскелей и прочей маргинальщины — выучив язык, осознать, что девки всё равно не дают. Да и сам язык никому нах не впился.

Кука, ты? Куда пропал? Ждем новых разоблачений.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.