Здравствуйте, Сергей Губанов, Вы писали:
СГ>Ну, как что делать, обращайтесь ко мне, я Вам помогу, научу как надо грамотно программировать. СГ>В данном случае надо использовать цикл с проверкой остановки выполнения итерации внутри самой итерации, то есть надо использовать цикл LOOP:
СГ>
Ой, спасибо! Ну-с, с учетом поправки Socrat'а мой код принимает следующий вид:
while (queue.has_elements()) {
elem = queue.get_first();
if (elem.get_state() == ST_FREE) {
elem.start_processing(...);
break;
}
queue.make_last(elem);
}
Предлагаю вам посчитать overhead по строчкам/лексемам и помедитировать над результатом.
PS про подмену понятий было сказано не единожды, так что повторяться не буду.
Здравствуйте, SiAVoL, Вы писали:
SAV> Цикл должен быть вещью в себе (не знаю как это выразить, надеюсь эту фразу вы поймете правильно).
Выразить это можно используя процедуры. Цикл должен быть вещью в себе в том смысле, что его тело можно оформить как независимую процедуру, а в случае с несколькими выходами, как несколько независимых процедур.
WHILE a DO x END
REPEAT x UNTIL b
LOOP
x;
IF b THEN y; EXIT END;
z
END
x, y, z — независимые от самих циклов процедуры. Ни каких флагов = глобальных переменных.
Здравствуйте, Сергей Губанов, Вы писали:
СГ>2) Известно, что стандарты оформления Си-образного кода требуют использования большего количества строчек чем это реально необходимо (чтобы читающему понятно стало где что написано).
Эти стандарты служат очень многим целям и большинство из них абсолютно не зависят от языка программирования (например, здесь
Сергей, если Вы не удосуживаетесь просто прочитать документацию, то обсуждать что-либо с вами становится просто глупо.
Рядом вам привели, в чём ошибка (если в доки заглянуть лень)
Наверное буду уже не первым, ещё больше разочаровывающимся в вас как собеседнике...
Здравствуйте, CrystaX, Вы писали:
CX>Почему Вы решили, что минимальное количество лексем является признаком правильности синтаксиса?
1) Не минимальное вообще, а по 1 лексеме достаточно и необходимо между словами в базовых синтаксических конструкциях (IF, WHILE, CASE, WITH, ... и т.д.).
2) Компилятор отловит все случайные явные "зевки" сделанные программистом, например такой:
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Здравствуйте, SiAVoL, Вы писали:
SAV>> Цикл должен быть вещью в себе (не знаю как это выразить, надеюсь эту фразу вы поймете правильно).
СГ>Выразить это можно используя процедуры. Цикл должен быть вещью в себе в том смысле, что его тело можно оформить как независимую процедуру, а в случае с несколькими выходами, как несколько независимых процедур.
А как процедуру с несколькими точкаи выхода не дано?
PROCEDURE
IF cond1 THEN RETURN 1 END;
IF cond2 THEN RETURN 2 END;
IF cond3 THEN RETURN 3 END;
END
moudrick wrote:
> C>Угу, поэтому все академические разработки весьма успешно загибаются. > C>Живет только созданое практиками. > С++, кстати, тоже начинался с академической разработки. А практики его > потом подхватили. > Ссылку навскидку не нашел, извините.
Э, нет.
С++ сразу разрабатывался как практичное дополнение для С, с сохранением
обратной совместимости и т.п. Хотя изначально и писал его профессор.
Здравствуйте, qwertyuiop, Вы писали:
Q>Оберон же фактически заставляет программиста всегда использовать составной оператор, заключаа его между THEN и END. И это хорошо?!
Да это хорошо. Найдите ошибку в следующем си-образном коде (компилятор ее не найдет, так как формально программа корректна):
if(ВыполненоНекотороеУсловие1())
return ВернутьНекотороеЗначениеОпределяемоеСледующимиПарамертами1(a, b, c, d, e, f, h);
if(ВыполненоНекотороеУсловие2());
return ВернутьНекотороеЗначениеОпределяемоеСледующимиПарамертами2(a, b, c, d, e, f, h);
if(ВыполненоНекотороеУсловие3())
return ВернутьНекотороеЗначениеОпределяемоеСледующимиПарамертами3(a, b, c, d, e, f, h);
В другом синтаксисе такой "зевок" невозможен:
IF ВыполненоНекотороеУсловие1() THEN
RETURN ВернутьНекотороеЗначениеОпределяемоеСледующимиПарамертами1(a, b, c, d, e, f, h)
END;
...
IF ВыполненоНекотороеУсловие2() THEN
RETURN ВернутьНекотороеЗначениеОпределяемоеСледующимиПарамертами2(a, b, c, d, e, f, h)
END;
...
IF ВыполненоНекотороеУсловие3() THEN
RETURN ВернутьНекотороеЗначениеОпределяемоеСледующимиПарамертами3(a, b, c, d, e, f, h)
END
А можно так:
IF ВыполненоНекотороеУсловие1() THEN
RETURN ВернутьНекотороеЗначениеОпределяемоеСледующимиПарамертами1(a, b, c, d, e, f, h)
ELSIF ВыполненоНекотороеУсловие2() THEN
RETURN ВернутьНекотороеЗначениеОпределяемоеСледующимиПарамертами2(a, b, c, d, e, f, h)
ELSIF ВыполненоНекотороеУсловие3() THEN
RETURN ВернутьНекотороеЗначениеОпределяемоеСледующимиПарамертами3(a, b, c, d, e, f, h)
END
S>А еще типичная ошибка — вместо "==" в условии поставить "="... Издержки нестрогих языков.
В некоторых языках (например, в PHP) есть еще одна конструкция, "===" — проверка на идентичность.
Пример:
/*
PHP - нетипизированый язык. Поэтому там на такие грабли можно наткнуться, что оёёёй
*/print("1" == "0001" ? 'equal' : 'not equal');
// напечатает equal, потому что произойдет конвертация в int
// (PHP парсит содержимое двойных кавычек)print("1" === '0001' ? 'equal' : 'not equal');
// напечатает not equal, потому что объекты одинакового типа и их содержимое не равно
Здравствуйте, Сергей Губанов, Вы писали:
CX>>Почему Вы решили, что минимальное количество лексем является признаком правильности синтаксиса?
СГ>1) Не минимальное вообще, а по 1 лексеме достаточно и необходимо между словами в базовых синтаксических конструкциях (IF, WHILE, CASE, WITH, ... и т.д.).
СГ>2) Компилятор отловит все случайные явные "зевки" сделанные программистом, например такой: СГ>
Из Ваших слов выходит, что синтаксис должен быть масимально жестким. Вот в этом месте может быть только такая-то лексема и никакая другая, а вот в этом — такая-то и никакая другая, так?
Да, каркас синтаксиса C не жесткий, в отличие от Оберона. Здесь допустимы вольности. Здесь есть места (и довольно много), где в грамматике языка присутствует категория MAYBE. Но здесь мы опять приходим к первоначальному вопросу: "Для кого это правильно?". И ответ прост. Жесткий каркас синтаксиса языка — хорошо компилятору, плохо пользователям. Гибкий синтаксис — плохо компилятору, хорошо разработчику.
PROCEDURE a : BOOLEAN
{* пара десятков строчек кода *}
RETURN TRUE;
END a;
PROCEDURE b
VAR
a : BOOLEAN;
BEGIN
a := FALSE;
{* пара десятков строчек кода *}
IF a THEN
{* критически важный код *}
END
END;
Забыл спросить: почему Паскаль остается самым распространенным из всего семейства паскалеподобных языков, в то время как остальные применяются весьма и весьма редко? У меня есть определенное мнение на этот счет, а у Вас?
Здравствуйте, Сергей Губанов, Вы писали:
СГ>1) Не минимальное вообще, а по 1 лексеме достаточно и необходимо между словами в базовых синтаксических конструкциях (IF, WHILE, CASE, WITH, ... и т.д.).
Здравствуйте, Sergey J. A., Вы писали:
СГ>>1) Не минимальное вообще, а по 1 лексеме достаточно и необходимо между словами в базовых синтаксических конструкциях (IF, WHILE, CASE, WITH, ... и т.д.). SJA>А это
Вы не читали ? Там даже приведён так Вами любимый расклад по звёздам.
Дык. Если факты не соответствуют теории — тем хуже для фактов. (с) не помню чей
Я, кстати, тот пример еще усовершенствовал. Если посмотреть внимательнее, то конструкция "if cond action" в этом примере является избыточной и может быть сокращена до "cond action", где cond — логическое условие, action — выполняемое действие. В результате код сокращается до
while not end_of_stream
read_socket
checksum == fails
raise_hacker_alert
break
number_of_bytes_read>MAX_DATA_ALLOWED break
process_data
Итого:
лексем — 6
строк кода — 7
символов (не считая отступов) — 144
Здравствуйте, Mamut, Вы писали:
M>Фи "Надо делать настолько просто, насколько возможно, но не проще" Самое простое это Оберон. А то, что понаписано здесь — фи, гадость какая-то
Неправда. Самое оптимальное — "пацакон". Остается только удивляться почем некоторые ковбои еще до сих пор не могут расстаться с такими оверхедными языками как C++ и Оберон, которые... bla-bla-bla...
П>Предлагаю вам посчитать overhead по строчкам/лексемам и помедитировать над результатом. П>PS про подмену понятий было сказано не единожды, так что повторяться не буду.
Вот забежал домой и не удержался — заглянул на секунду в Инет.
Не уследил начало дискуссии о данном куске кода.
По виду — типичный планировщик задач.
Не могу понять, зачем постоянно проверяется наличие в очереди элементов? Они ведь в цикле не удаляются.
IF queue.has_elements() THEN
elem := queue.get_first();
WHILE elem.state # ST_FREE DO
queue.make_last(elem);
elem := queue.get_first()
END;
elem.start_processing(...)
END
Прошу прощения за качество кода. Наверное, можно было сделать лучше. Спешу.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Здравствуйте, Сергей Губанов, Вы писали:
B>>так что получается в обероне точно так же програмист не может быть "уверен, что перед следующим оператором после выхода из цикла выполняется условие ~p (NOT p)."
СГ>Может. Таково одно из положений структурного программирования. СГ>
СГ>WHILE p DO
СГ> ...
СГ>END;
СГ>ASSERT(~p)
СГ>
СГ>Этот ассерт ни когда не остановит выполнение программы, условие ~p всегда истинно.
СГ>
СГ>while (p)
СГ>{
СГ> ...
СГ>}
СГ>assert(!p)
СГ>
СГ>А вот этот ассерт иногда может остановить работу программы. Например, если внутри цикла сделать break не присвоив p ложное значение.
Давайте внесём ясность касательно постусловий и инвариантов цикла, и какое отношение к этому имеют условия и ассерты.
Цикл можно представить в виде такого ветвления
assert(P); // допущение о состоянии программы перед циклом (включая инвариант)
enter:
assert(Q); // P -> Q допущение сразу после ветвления (перед проверками)
. . .
assert(R0);
if(R) goto leave; // R -> T закон выхода (ложь в while(), break, return)
assert(R1); // R1 -> R0 & !R
. . .
assert(S0);
if(S) goto enter; // S -> Q закон повтора (конец тела цикла, проверка в do-while(), continue)
assert(S1);
. . .
assert(Q && !T); // безусловный повтор (означает, что выполняется предусловие и не выполняется постусловие)goto enter;
leave:
assert(T);
Предикаты P...T связаны между собой импликацией.
Естественно, что допущения и законы выражаются поистине гигантскими булевыми выражениями. Эти выражения имеют ценность только для верификации программы, но не для написания/исполнения.
Пусть некое "маленькое" выражение r обладает таким свойством: (R0 && r -> R), (R0 && !r -> R1)
Тогда
assert(R0);
if(R) goto leave;
assert(R0 && !R);
можно переписать как
if(r) goto leave;
То есть, вместо while(All_Known_Laws_And_Assertions){...} мы пишем while(tiny_test){...}
Разумеется, в некоторых случаях (в частности, если в теле цикла нет break) можно утверждать, что постусловие содержит tiny_test как один из конъюнктов. Но вообще говоря, это необязательно.
Подытоживая:
Булевы выражения, которые управляют ветвлением — это не сами предусловия/постусловия/инварианты, а только признаки.
Здравствуйте, AVC, Вы писали:
AVC>По виду — типичный планировщик задач.
ХЗ что это — из головы придумал. У меня на работе даже сишного компилера нет, если честно.
AVC>Не могу понять, зачем постоянно проверяется наличие в очереди элементов? Они ведь в цикле не удаляются.
Учитывая принцип "черного ящика" — мы не можем это сказать. Можем сказать лишь что они не удаляются в этом цикле этой программы.