yury_finkel: (Default)
Поскольку писать мне пока особо не о чем, и к тому же я нахожусь в некотором отупении от (заканчивающейся) простуды, то пост будет программистский.

Недавно в комментах у [livejournal.com profile] rexy_craxy я упомянул о знаменитой ошибке в программе на FORTRAN IV, из-за которой не то НАСА потеряло спутник, не то американские военные — ракету (не помню точно). Расскажу поподробнее.

Вот кусок программы на Фортране:
        DO 20 I=1,5
        ... какие-то операторы ...
20      CONTINUE

Это цикл с переменной-счётчиком I, принимающей значения от 1 до 5 (а 20 — это метка последнего оператора тела цикла, в данном случае пустого оператора CONTINUE). Тут всё нормально.

Но вспомним, что запятая и точка на клавиатуре расположены рядом. И вот однажды программист опечатывается и вместо запятой вводит точку:

        DO 20 I=1.5
        ... какие-то операторы ...
20      CONTINUE

Как ни покажется странным, этот кусок нормально проходит компиляцию. Почему? Да потому, что 1) в Фортране пробелы внутри идентификаторов ничего не значат, 2) переменные в Фортране можно не объявлять (их тип определяется по первой букве идентификатора). В результате первая строка теперь означает присваивание числа 1.5 переменной DO20I (типа FLOAT).

В результате происходит следующее: присваивание числа некоей далее не используемой переменой, выполнение операторов один раз (к тому же переменной I, вероятно, уже было выше присвоено какое-то значение, так что ошибки не происходит) и... всё. Т. е. вместо цикла получаем однократное выполнение тела цикла со "случайным" значением переменной-счётчика.

Компилятор на такую ошибку не ругается. Ошибок времени выполнения тоже не происходит. Представьте, насколько трудно отловить такую ошибку, особенно при тогдашней (60-х годов) технике отладки программ (а если это всё было на перфокартах?!)

Вот так вот ошибка, допущенная при разработке синтаксиса языка, провоцирует трудноотлавливаемые ошибки при программировании. И программиста, допустившего такую ошибку, просто грех ругать чайником и т.п. Ему только посочувствовать можно. Я считаю, что в таком случае не программист виноват, а язык программирования (точнее, его разработчики). (Кстати, чтобы смягчить эффект, ЕМНИП, в FORTRAN-77 разрешили писать запятую перед переменной-счётчиком: DO 20, I=1,5; если запятую не писать, то компилятор выдавал предупреждение).

То же самое происходит и в C/C++. Но об этом я умолчу, т. к. фанаты C воспринимают наезд на своего кумира весьма болезненно :)

Практический вывод для меня такой: никогда не пренебрегать предупреждениями (warning'ами) компилятора. Современные компиляторы пытаются исправить такие ошибки в синтаксисе языка тем, что сомнительные (но допустимые с точки зрения синтаксиса) места пропускают, но помечают предупреждением. Так вот, я всегда стремлюсь не оставлять ни одного warning'а в своих программах — на любом языке. Даже если это всего лишь предупреждение о неиспользуемой переменной. Что и рекомендую всем.
yury_finkel: (Default)
(По-русски см. ниже)

Esperante. Ofte oni plendas al mi pri jena problemo en mia programo Ek (esperanta klavaro): en iu programo anstataŭ enigo de ĉapelita litero (plej ofte de ĉ) okazas forviŝo de antaŭe enigita litero. Tion kaŭzas tio, ke por kongruo kun Vindozo 95/98/ME Ek uzas specialan kaŝitan klavararanĝon, en kiu al AltGr+C (aŭ Alt+Ctrl+C) estas atribuita litero ĉ, kaj respektive al AltGr+G — ĝ ktp. Sed en iuj programoj tiaj literkombinoj plenumas internajn funkciojn, tial ili estas "glutataj" (kaj ĉar Ek funkcias tiel, ke unue oni tajpas "c", kaj poste ĉe enigo de postfikso "x" okazas forviŝo de la "c" kaj enigo anstataŭ ĝi de "ĉ", do pro nefunkcio de la "ĉ" restas nur la forviŝo).

Definitiva solvo de la problemo: Ĉar la linio Vindozo 95/98/ME praktike mortis, do oni povas uzi rekte unikodan reĝimon, kiu funkcias nur en la linio Vindozo NT/2000/XP/Vista. Por tio klaku per la dekstra musbutono sur la piktogramo de Ek en la taskopleto, el aperinta menuo elektu Agordu, en aperinta fenestro elektu langeton Instalo, kaj tie en la maldekstra panelo de elekto de kodpaĝo elektu neniu, poste premu la butonon Bone. Eble, post tio la programo petos restartigi la operaciumon.

Post tio Ek ne plu uzos anstataŭigon de klavararanĝo kaj transdonados en aplikprogramojn senpere unikodajn kodonojn de la esperantaj ĉapelitaj literoj. La menciita problemo devos malaperi.

По-русски. Часто мне жалуются на такую проблему в моей программе Ek (эсперантизатор клавиатуры): в той или иной программе вместо ввода буквы с диакритикой (чаще всего ĉ) происходит удаление ранее введённой буквы. Это вызвано тем, что для совместимости с Windows 95/98/ME Ek использует специальную скрытую раскладку клавиатуры, в которой на AltGr+C (или Alt+Ctrl+C) назначена буква ĉ, и соответственно на AltGr+G — ĝ и т.д. Но в некоторых программах такие сочетания клавиш выполняют служебные функции, поэтому они "проглатываются" (а поскольку Ek устроен так, что сначала вводится "с", а затем при вводе постфикса "x" происходит забой "c" и ввод вместо него "ĉ", то из-за несрабатывания "ĉ" остаётся только забой).

Кардинальное решение проблемы:
Поскольку линия Windows 95/98/ME практически умерла, то можно использовать непосредственно юникодный режим, который работает только в линии Windows NT/2000/XP/Vista. Для этого нажмите правой кнопкой мыши на иконке Ek в трее, из появившегося меню выберите Agordu (Настроить), в появившемся окошке выберите закладку Instalo (Установка) и там в левой панели выбора кодовой страницы выберите neniu (никакая), после чего нажмите кнопку Bone (дословно "Хорошо", т.е. Принять). Возможно, после этого программа попросит перезагрузить систему.

После этого Ek не будет использовать подмену раскладки клавиатуры и будет передавать в приложения непосредственно юникодные коды эсперантских букв с диакритикой. Упомянутая проблема должна исчезнуть.
yury_finkel: (Default)
В последнее время пашу как папа Карло, его лошадь и его собака, вместе взятые. PHP, HTML, CSS, JavaScript, AJAX и MySQL уже по ночам снятся...

В связи с этим вспомнились две моих "любимых" глюкофичи в PHP как в языке.

На первую я напоролся месяца три назад. Пишу примерно следующее:
$a=false;
$b=true;
$a=$a or $b;
(про && и || я знаю, но как старый паскалист, предпочитаю and и or этим сишным закорючкам)... и получаю $a==false !!! Я потратил час, чтобы локализовать это место, и ещё полчаса бился головой о клавиатуру, думая, что я сошёл с ума. Чуть ли не с детства знаю, что false or true==true, а тут на́ тебе... В конце концов, как всегда, пришлось залезть в документацию — и тут выяснилось, что приоритет операций and и or ниже приоритета операции присваивания! Т.е. выполняется следующее:
($a=$a) or $b;
т.е. фактически не выполняется ничего. Мда. Насколько я понимаю, такой приоритет для and и or позаимствован из Perl'а, чтобы можно было в перловском стиле писать:
сделать_чего-то_там or die('капец');
На мой взгляд, такая имитация естественного (английского) языка в языке программирования совершенно ни к чему (как вспомню Кобол, так вздрогну). Языки программирования должны следовать логике, а не имитировать человеческий язык.

(Кстати, приоритеты and и or ещё, оказывается, равны, т.е. в сложных выражениях скобки надо ставить).

Ну а вторую глюкофичу я знаю много-много лет, но напарываюсь на неё регулярно. Это старая ловушка всех си-образных языков. Если случайно в условии вместо == написать =, то компилятор/интерпретатор это спокойно проглотит и послушно выполнит присваивание, а потом результат сравнит с нулём. Стоит где-то просто опечататься, и часы увлекательного вылавливания глюка обеспечены :( В современных компиляторах C/C++ на такую конструкцию по крайней мере выдаётся предупреждение, а в более современных языках (Java, C#, D) так вообще невозможно написать (насколько я знаю), но PHP это проглатывает незамеченно, как компиляторы C в старые добрые времена... Вот за такие штуки я C и си-образный синтаксис и не люблю. Я, как старый паскалист, считаю, что выражение — это выражение, а присваивание — это оператор, и не фиг смешивать одно с другим.

Вот, поворчал, и вроде как полегчало :)