Здравствуйте, Mamut, Вы писали:
M>Яркий пример — читаем данные с сокета. Некая информация. M>
M>while not end of stream
M> read socket
M> calculate checksum
M> if checksum fails
M> raise hacker alert
M> exit
M> else
M> calculate number of bytes read
M> if number of bytes greater than MAX_DATA_ALLOWED
M> exit
M> end if
M> process data
M> end if
M>end while
M>
M> Что делать будем-то? Ставить флаги в глобальных переменных?
Какие еще флаги? В каких еще глобальных переменных??????
Циклов бывает всего три типа. Здесь налицо цикл с проверкой условия внутри итерации, т.е. цикл LOOP, так и пишем:
Я немного оптимизировал: наиболее вероятная ветвь исполнения всегда должна идти после THEN, наименее вероятная ветвь в ELSE — такого требование современных конвеерных процессоров.
M>1 (и главное). Здесь участвуют очень интересные люди с большим опытом в программировании, чье мнение я уважаю и ценю. Даже среди того флейма, что мы породили, можно найти инетерсные мысли, куски кода, способы аргументирования и проч.
Респект.
Согласен, что во флейме часто можно найти неожиданные идеи, полезнае и вне его. Но несмотря на свою полезность вне флейма, эти идеи там не употребляются...
M>3. Мне интересно понаблюдать за Сергеем. Ага, как в лаборатории. Интересна реакция организма на критику
2 варианта (местами необоснованное) отторжение и (местами полное) игнорирование.
M>Но в случае с Обероном фанатизм переходит все границы. Отсутствие аргументов заменяется истеричными выкриками "сам такой" и каким-то, колобковским, что ли, поведением. А такой фанатизм надо усмирять.
Вообще, учитывая раздел, можно было бы и простить. Если бы в (количестве и качестве) нарушения границ наблюдался приемлемый юмор.
Так шо я даже не знаю что и предложить...
Переименовать что ли ветку в "Кандидаты развлекаются"?
СГ>Какие еще флаги? В каких еще глобальных переменных??????
СГ>Циклов бывает всего три типа. Здесь налицо цикл с проверкой условия внутри итерации, т.е. цикл LOOP, так и пишем: СГ> СГ>Я немного оптимизировал: наиболее вероятная ветвь исполнения всегда должна идти после THEN, наименее вероятная ветвь в ELSE — такого требование современных конвеерных процессоров.
Блин. Костыль на костыле. Объясните мне какая разница между:
while
if
exit
и
for
if
exit
Почему в Обероне я не могу написать первый случай? Аргумент "три типа цикла" не пройдет — это детский сад. Прочие языки очень даже позволяют такое делать. Аргументы "так удобно компилятору" не пройдет — должно быть удобно мне, как программисту.
СГ>Я немного оптимизировал: наиболее вероятная ветвь исполнения всегда должна идти после THEN, наименее вероятная ветвь в ELSE — такого требование современных конвеерных процессоров.
А что, команды языка Оберон напрямую транслируются в машинный команды?
Здравствуйте, Сергей Губанов, Вы писали:
CГ>Я немного оптимизировал: наиболее вероятная ветвь исполнения всегда должна идти после THEN, наименее вероятная ветвь в ELSE — такого требование современных конвеерных процессоров.
А в чём прикол? Вроде сумма длин прыжков (для каждой ветки) в обоих случаях одинакова и число разрывов конвеера тоже. Или?
Здравствуйте, Mamut, Вы писали:
M>>Что, и сборку мустора будем на Оберонах писать? Успехов... покажите только потом исходники, посмеемся вместе.
M> GC в Оберонах присутствует по умолчанию
Одну секундочку. Мы его только пишем. Поэтому нет еще никакого Оберона. И сборки мусора вместе с ним.
Здравствуйте, AVC, Вы писали:
AVC>Когда программист пишет (или, что важнее, читает) на Модуле/Обероне цикл "WHILE p DO ... END" он абсолютно уверен... AVC>...на Си/Си++, он не может быть в этом уверен, т.к. внутри цикла может находиться как оператор break, так и знаменитый goto.
Понимаете, мне кажется, что здесь имеется противоречие между двумя подходами к пониманию структурности.
"Академический" подход ставит структурность в сугубо формальные рамки и заявляет о её самоценности.
"Прагматический" подход рассматривает структурность как средство достижения удобства изложения алгоритма.
"Академический" подход спекулятивен: его сторонник созерцает код и склонен к проведению формальной верификации программ. "Вот у нас есть кусок кода — цикл. Каков его консеквент?"
"Прагматический" подход сугубо конструктивен: его сторонник ставит себе задачу написания кода, и применяет структурирование программы для облегчения её решения. "Напишем-ка цикл... А вот тут выйдем досрочно по break..."
Почему я ставлю кавычки? Теория без практики мертва, а практика без теории слепа. Ни тот, ни другой подход не является оптимальным в чистом виде. Программист должен и создавать, и сопровождать код, значит, хороший программист со спокойной совестью напишет цикл, содержащий break, но обязательно осознавая, каков консеквент цикла он имеет в виду получить, а если цикл получится большой или достаточно сложный, — ещё и задокументирует свои намерения для целей сопровождения.
Каков итог? Ни Оберон, ни Фортран-II популярностью не пользуются, а Си++ — пользуется.
Здравствуйте, moudrick, Вы писали:
M>Здравствуйте, Mamut, Вы писали:
M>>>Что, и сборку мустора будем на Оберонах писать? Успехов... покажите только потом исходники, посмеемся вместе.
M>> GC в Оберонах присутствует по умолчанию
M>Одну секундочку. Мы его только пишем. Поэтому нет еще никакого Оберона. И сборки мусора вместе с ним.
Ааа. Понял То есть — а на чем же написан рантайм Оберона? Боюсь, на ассемблере. Вернее, того Оберона, что BlueBottle. BlackBox вполне себе на C наверное написан
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Циклов бывает всего три типа. Здесь налицо цикл с проверкой условия внутри итерации, т.е. цикл LOOP, так и пишем: СГ>
Итого:
лексем — 24
строк кода — 12
символов (не считая отступов) — 236
while (!end_of_stream) {
read_socket();
if (checksum == fails) {
raise_hacker_alert();
break;
}
if (number_of_bytes_read() > MAX_DATA_ALLOWED) break;
process_data();
}
Итого:
лексем — 33
строк кода — 9
символов (не считая отступов) — 175
Ну и где хваленое превышение в разы?
PS Это я еще не говорю об очередной подмене понятий: вместо цикла "выполняй пока не конец потока" получился "выполняй вечно" с последующей проверкой условия. Это не есть одно и то же.
A>>double max(double a, double b) {
A>> return a > b ? a : b;
A>>}
A>>
A>А она и некорректна — double так не сравнивают.
Вот яркий пример догматического подхода к общеизвестным правилам.
Есть такая догма: "сравнивать double на равенство нельзя!" — значит любая программа, сравнивающая их на равенство — ошибочна. Все, больше ничего объяснять и доказывать не надо.
Я отвечаю за свои слова, а не за то как вы их интерпретируете!
A>>>double max(double a, double b) {
A>>> return a > b ? a : b;
A>>>}
A>>>
A>>А она и некорректна — double так не сравнивают.
Q>Вот яркий пример догматического подхода к общеизвестным правилам.
Q>Есть такая догма: "сравнивать double на равенство нельзя!" — значит любая программа, сравнивающая их на равенство — ошибочна. Все, больше ничего объяснять и доказывать не надо.
OAB>и т.д... и посмотрю на того кто осмелится такое писать в одну строку! OAB> Понимаю что процедуры на 2-3 экрана это не нормально, но иногда без них не обойтись
Если надо — обойтись всегда можно. Надо привыкать делать из хорошего кода еще более лучший, если это себя оправдывает.
Рефакторинг рулит. Паттерн Выделение метода (Extract Method). Примерчик там, правда, галименький, но ничего лучшего я не нашел. Применяем его с одновременным применением паттерна добавление параметра (Add Parameter).
Сокращаем текст длинного метода на ~5 строк. Заодно если называем только что выделенный метод правильно, не нужно тратить лишние строки на поясняющие комментарии (самодокументированность).
procedure UnlinkLeftRight(current: PReferenceNode)
// Мой первоначальный вариант названия - ProcessLeftInline - пока не увидел поясняющего коммента.begin
OAB> if Assigned(current^.RightInline) then
OAB> begin
OAB> // glue left with right - тоже можно выделить.... но время пока не пришло - ждем-с... обнаружения дублирования этого кода
OAB> current^.LeftInline^.RightInline := current^.RightInline;
OAB> current^.RightInline^.LeftInline := current^.LeftInline;
OAB> end
OAB> else
begin
OAB> current^.LeftInline^.RightInline := nil; // unlink leftend
end
OAB>procedure TReferenceTree.UnlinkNode(current: PReferenceNode);
OAB>begin
OAB> if Assigned(current^.LeftInline) then
OAB> begin
UnlinkLeftRight(current); // unlink left/right - пусть пока тут побудет, по закону сохрранения исходника
OAB> end
OAB> else ; // nothink glue/unlink
OAB> // unlink next/previous
OAB> if Assigned(current^.PrevSibling) then
OAB> begin
OAB> if Assigned(current^.NextSibling) then
OAB> begin
OAB> // glue periouse with next
OAB> current^.PrevSibling^.NextSibling := current^.NextSibling;
И так далее по образцу.
По ходу может ообразоваться чудесный шаблонный метод. Это если мы на него надеемся. А если не надеемся, то можно запрятать условие if Assigned(current^.LeftInline) внутрь выделенного метода, чем достигается еще большая экономия в экранных строках каждого отдельно взятого длинного метода:
procedure UnlinkLeftRight(current: PReferenceNode)
// Мой первоначальный вариант названия - ProcessLeftInlinebegin
OAB> if Assigned(current^.LeftInline) then
OAB> begin
OAB> if Assigned(current^.RightInline) then
OAB> begin
OAB> // glue left with right - тоже можно выделить.... но время пока не пришло - ждем-с... обнаружения дублирования этого кода
OAB> current^.LeftInline^.RightInline := current^.RightInline;
OAB> current^.RightInline^.LeftInline := current^.LeftInline;
OAB> end
OAB> else
begin
OAB> current^.LeftInline^.RightInline := nil; // unlink leftend
OAB> end
OAB> else ; // nothink glue/unlinkend
OAB>procedure TReferenceTree.UnlinkNode(current: PReferenceNode);
OAB>begin
UnlinkLeftRight(current); // все, комент больше не нужен. убиваем, нарушая закон сохранения исходника ;-)
OAB> // unlink next/previous
OAB> if Assigned(current^.PrevSibling) then
OAB> begin
OAB> if Assigned(current^.NextSibling) then
OAB> begin
OAB> // glue periouse with next
OAB> current^.PrevSibling^.NextSibling := current^.NextSibling;
OAB>
звыняйте, не сильно помню паскаль, может чего-то и не так... но идея такова. На сях, конечно, красивее бы это выглядело меньше буквенных символов, но в паскале никто не мешает/не запрещает применить оправдывающие себя методологии разработки.
СГ>>После глупого с моей стороны так сказать усовершенствования стало:
СГ>>n = ...
СГ>>while(n --> 0)
СГ>>{
СГ>> ...
СГ>>}
СГ>>use(n); // теперь n на 1 меньше чем надо (а иногда нет)
- то есть как это - иногда?
СГ>>
СГ>>Мне стыдно за такую глупость, поддался "моде" на --> 0 оператор...
Нет никакой моды. Есть техника правильного использования. Ей надо поддаваться, а на моду по возможности забивать.
Кроме того, операторы инкремента (и префиксные, и постфиксные) обычно питутся без пробела. Это подчеркивает их высокий приоритет. Который уж точно выше, чем у сравнения.
К>Моде? Может просто не потрудился прочитать документацию и выяснить разницу между постфиксным и префиксными -- и ++? Просто, на мой взгляд, если не удосужился подумать, то никакая верификация тут не поможет
Тупая замена не эквивалентна. А обоснованная зависит в какой-то мере от окружающего исходника, в частности от "почему иногда"...
n = (...) + 1; //особенно это полезно будет, если в (...) уже есть в конце - 1while( --n > 0)
СГ>>{
СГ>> ...
СГ>>}
СГ>>use(n); // теперь n будет такое как надо (а иногда на ровном месте не бывает)
СГ>>
Здравствуйте, qwertyuiop, Вы писали:
Q>Вот яркий пример догматического подхода к общеизвестным правилам.
Q>Есть такая догма: "сравнивать double на равенство нельзя!" — значит любая программа, сравнивающая их на равенство — ошибочна. Все, больше ничего объяснять и доказывать не надо.
Славный наш бесстрашный КЫВТ! Что с тобой творится?!! Почему из любой ветки флейм прёт?!
(насчёт "любая программа": так мы же говорим как раз о строгой теоретической догматичности, которая предполагает ежинственный способ сравнения double. В реальной жизни я сам double сравниваю не краснея, даже в тех случаях когда возможны не особо критичные погрешности)
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
WARNING: expression "to_be || !to_be" is always true
СГ>Лишние THEN и DO писать ни в коем случае не надо — это будет синтаксической ошибкой.
Они — лишние сами по себе. Самый простой синтаксис условного оператора должен быть такой:
if условие оператор
Проблема в том, что нужно как-то выделить условие чтобы компилятор смог понять где оно начинается и где заканчивается. Для этого в С поступили просто: заключили его в скобки — логично и симметрично. В Обероне с одной стороны он отделен пробелом (он здесь несет вполне определенный синтаксический смысл, поэтому должен участвовать в подсчете вашего оверхеда), с другой — словом THEN. Ни логики, ни симметрии.
В качестве оператора в С может стоять как одиночный, так и составной оператор. Оберон же фактически заставляет программиста всегда использовать составной оператор, заключаа его между THEN и END. И это хорошо?! И что вы там подсчитываете, какой оверхед?
Я отвечаю за свои слова, а не за то как вы их интерпретируете!
Здравствуйте, Amidlokos, Вы писали:
A>Здравствуйте, qwertyuiop, Вы писали:
Q>>Вот яркий пример догматического подхода к общеизвестным правилам.
Q>>Есть такая догма: "сравнивать double на равенство нельзя!" — значит любая программа, сравнивающая их на равенство — ошибочна. Все, больше ничего объяснять и доказывать не надо.
A>Славный наш бесстрашный КЫВТ! Что с тобой творится?!! Почему из любой ветки флейм прёт?!
A>(насчёт "любая программа": так мы же говорим как раз о строгой теоретической догматичности, которая предполагает ежинственный способ сравнения double. В реальной жизни я сам double сравниваю не краснея, даже в тех случаях когда возможны не особо критичные погрешности)
Ничто тебе не мешает написать класс с перегруженными нужным образом операторами сравнения и приведения к double. Разве только отсутствие времени... Может и написан уже где-то. Поиск в осети рулит.
Здравствуйте, achp, Вы писали:
OV>>Вы хотите сказать, что на С/С++ невозможно обеспечить p == false после выхода из цикла while(p)?
A>Формально говоря, это так.