- 1
https://shmat-razum.blogspot.com/2012/12/blog-post.html
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+2
https://shmat-razum.blogspot.com/2012/12/blog-post.html
Есть такое правило, к которому все привыкли: если в программе записано логическое выражение с and, и первое подвыражение оказалось равно false, то второе не вычисляется. Аналогично с or: если первое подвыражение равно true, второе не вычисляется. Это позволяет удобно записывать вещи вида
if (index < 0 || array[index] == NULL)
...
if (index >= 0 && array[index] == ptr)
...
Кстати, во многих скриптовых (perl, php) есть и НЕ short-circuit вариант. Выглядит он внешне как побитовое: & или |.
Вот почему бывает полезно почитать про язык, прежде чем на нём писать.
В другой раз вот так сядешь за неизвестный язык, и окажется что оператор "&&" в нем удаляет все файлы с диска, и шлет матерное письмо маме программиста
Да нормально всё. Раньше все языки такими были. То есть вообще везде и всюду and и or были жадными. И в алголе, и в паскале, и бейсике, и в фортране, и в аде.
Только анскилябры заедушные не могут осилить нормальный порядок вычислений. Дейкстра бы не одобрил подобной early-exit хуиты.
even C programming can be appreciated by the Real Programmer: after all, there's no type checking, variable names are seven (ten? eight?) characters long, and the added bonus of the Pointer data type is thrown in. It's like having the best parts of FORTRAN and assembly language in one place. (Not to mention some of the more creative uses for #define.)
As long as there are ill-defined goals, bizarre bugs, and unrealistic schedules, there will be Real Programmers willing to jump in and Solve The Problem, saving the documentation for later. Long live FORTRAN!
А в языке Ада для короткой и полной схемы существуют разные ключевые слова: просто or и and для полной схемы, а or else и and then для сокращённой. Второе слово в этом случае подсказывает, когда будет вычисляться второй аргумент (слово «else» подсказывает, что первый должен быть false; «then» подсказывает, что первый должен быть true).
Ибо back-compability.
Как однажды меня подколоол bugmenot: "вот и выросло поколение, которое не знает Паскаля".
Кстати в том самом трушном бейсике оно никогда и не работало.
А именно мега-фича однострочных ifчиков (без then!). Которую юзали повсеместно. Применив правило Де-Моргана можно разрулить вообще все мыслимые случаи.
>не просто не действует, а может действовать или не действовать в зависимости от воли компилятора
Это не баг, а фича.
Т.к. всегда была возможность оптимизации (как и {$B-}), навроде -O3 в gcc.
Только у ограниченных крестопитухов и их унылых последователей выполнение &, | нельзя оптимизировать по короткой схеме, а у божественных фортранщиков можно.
В Фортране 66 и в более старых были такие конструкции:
Это «иф логический». THEN в Фортране не используется, но нужны скобки у условия. Слово ELSE ещё не придумали, так что у него всего одна ветвь.
Это «иф арифметический». Действие1 выполняется, если выражение < 0, действие2 — если выражение = 0, действие3 — если выражение > 0. Это почти аналог тернарника, только у него три ветви.
В Фортране 77 появился блочный IF со словом THEN (до Фортрана 77 были только спагетти из GO TO). В блочном ифе наконец-то появились ELSE и ELSE IF.
В Фортране 90 «арифметический» иф задепрекейтили, но не удалили.
*****
В Бейсике были строчные ифы:
Два варианта ифа отличались по формату того, что стоит после слова THEN: если стояло число, оно воспринималось как метка.
В микрософтовском Кубейсике появился блочный IF, стыренный из Фортрана 77.
*****
Наконец, в Паскале изначально был свободный формат с единственным вариантом ифа:
Фортран 66:
Да, у Фортрана были «фирменные» логические операторы .NOT., .EQ., .NE., .LT., .GT., .LE., .GE., .AND., .OR., по всей видимости внесённые любителями Ассемблера.
Бейсик:
Паскаль:
Теперь вроде всё точно.
Добавлю что если в фортране N действий писалось через запятую, то в бейсике для этого было двоеточие.
Фортран:
>IF (<выражение>) <действие1>, <действие2>, <действие3>
Бейсик:
IF (<выражение>) THEN <действие1>: <действие2>: <действие3>
Бейсик:
Если x > 3, напечатает: Иначе не напечатает ничего.
Фортран-66: Напечатает только одну строку: "FOO", если x - 3 < 0; "BAR", если x - 3 = 0; "BAZ", если x - 3 > 0.
Почему нельзя использовать запятую? Запятая в Фортране используется для разделения аргументов PRINT и прочих стандартных вызовов и в древних конструкциях вроде DO, IF. Поэтому, кстати, в «арифметическом ифе» писали три метки, а не три выражения (если я напишу три принта, то парсер сломается при попытке определить, для чего используется запятая).
Не, это я с фортраном путаю. Там GOTO было необязательное. Обязательный THEN нужен парсеру чтоб скобки унылые не ставить.
IF A=B THEN GOTO 50
а можно так:
IF A=B THEN 50
x AND y
- возвращает x, если y<>0
- возвращает 0, если y=0 (или "", если x - строка)
Хотя нет, не уверен насчет лени (что будет, если написать SQR(-1) AND 0 ?), но можно использовать для всяких конструкций:
PRINT STR$(N) + " green bottle" + ("s" AND N<>1)
& эквивалентен AND
| эквивалентен OR
^ эквивалентен XOR
Это означает что они работают как и их математические аналоги. То есть для однобитных интов (булевского типа) как обычные логические функции. ОНИ ЖЕ используются для целых как побитовые операции. Так же как и в сиподобных.
Здесь как и у математических аналогов должны выполняться свойства: комутативности, ассоциативности и дистрибутивности. То есть результат должен быть инвариантом от порядка вычислений.
Возьмём более низкоуровневый пример, учитывая что фортран обычно использовался для вычислений.
Как известно бранчинг - довольно дорогая операция. Компилятор может догадаться что выполнить 1-2 лишних инструкции, гораздо менее затратно ошибиться с веткой. К тому же процессоры могут иметь несколько исполнительных блоков, и если инструкции не зависят друг от друга, то они будут выполняться assпаралельно.
&& - это не AND, но фактически сахарок над вложенными IFами. Которые затем превращаются в условные переходы.
(a>x) AND (diff<0.0000001) AND (i<=n)
Потом, компилятор может менять местами условия, вынося наперёд более простые для расчёта.
Например он знает что на данной платформе медленный плавающий питух, потому он может перенести сравнение флоатов в конец.
Если кодер желает явно задать порядок вычислений язык даёт ему возможность (см. примеры выше).
Вроде как очевидные вещи.
то на каком-нибудь особо ебанутом процессоре может оказаться так, что инструкция сложения будет работать быстрее инструкции побитового OR. И настоящий царский язык должен позволять например сделать так
и компилятор сам на основе эвристик чтоб выбрал, какой код из предложенных вариантов ему компилировать
Гцц вполне умеет работать с такими простыми утверждениями о переменных. Где-то у меня был говнокод, где он настолько был уверен в диапазоне переменной, что выбрасывал к хуям проверки, ассёрты, сдвиги, арифметику и т.п.
Проблема в том, что нету средств чтобы ему эту инфу передать явно.
Толи дело PHP Common Lisp
Поведение может зависеть от номера версии компилятора и настроек оптимизации.
КАК СТРАШНО ЖИТЬ!
Фигурная скобка означает начало комментария.
Это правило действует во всех широко используемых языках программирования: Pascal.
Казалось, оно само собой разумеется, во всех языках.
При столкновении с языком Си автора ждал сильный удар....
Там = означает начало сравнение.
Это правило действует во всех широко используемых языках программирования: Pascal, Basic, Algol, Cobol.
Казалось, оно само собой разумеется, во всех языках.
При столкновении с языком Си++ автора ждал сильный удар. Сравнение в этом языке не просто не действует, а может действовать или не действовать в перегрузки операторов. Эта неопределённость закреплена в стандарте.