Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Базарная площадь
  
О разделе

Основная страница

Группы обсуждений


Тематический каталог обсуждений

Архив

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  06:14[Войти] | [Зарегистрироваться]
Обсуждение темы:
Оберон-технология: особенности и перспективы


Тематика обсуждения: Оберон-технология. Особенности, перспективы, практическое применение. 

Количество сообщений на странице

Порядок сортировки сообщений
Новое сообщение вверху списка (сетевая хронология)
Первое сообщение вверху списка (обычная хронология)

Перейти на конкретную страницу по номеру


Всего в теме 6256 сообщений

Добавить свое сообщение

Отслеживать это обсуждение

Обсуждение из раздела
Школа ОБЕРОНА

<<<... | 5696—5687 | 5686—5677 | 5676—5667 | ...>>>
Всего сообщений в теме: 6256; страниц: 626; текущая страница: 58


№ 5686   21-10-2007 06:44 Ответить на это сообщение Ответить на это сообщение с цитированием
Ответ на »сообщение 5685« (Стэн)
___________________________

Ответ на »сообщение 5684« (Илья Ермаков)
___________________________
Вот цикл, который прямо таки подкупает легкостью своего чтения и понимания... Но в нем есть ошибки - где они?

Ну и какое отношение имеет сей код (и не с WHILE, а с многими выходами) к обсуждаемому вопросу? Не выкинули сложную начинку во вложенные процедуры, но цикл тут причём?
Кстати, если разработчики Aos любят LOOP ... END, то вот Oberon Microsystems - нет (в исходниках Блэкбокса он встречается очень редко). Они в аналогичных ситуациях вводят в теле цикла специальную переменную - состояние (включающую в том числе ошибочные ситуации). И строят как сам цикл, так и развилки и вложенные циклы внутри него с использованием этой переменной. Получается гораздо лучше, чем с кучей выходов - код непрерывен и поддаётся внимательному построчному анализу.
А после окончания цикла по переменной сразу видно, по какому поводу цикл завершён. И эта же переменная может идти наверх как результат успеха-неуспеха. Можно даже конечный автомат нарисовать для построения такого цикла.


№ 5685   21-10-2007 06:29 Ответить на это сообщение Ответить на это сообщение с цитированием
Ответ на »сообщение 5684« (Илья Ермаков)
___________________________
>>> Вот Вам и разница в мотивах. Меня не очень волнует "кто сказал, что программист не ошибётся". Опытному программисту для таких несложных циклов, действительно, всё равно, как написать, и если он в уме прокрутил условия на цикл, то он запишет его верно.
>>> Меня волнует, как будет выглядеть чтение и понимание этого цикла.
Вот цикл, который прямо таки подкупает легкостью своего чтения и понимания... Но в нем есть ошибки - где они?

LOOP
    (* empty receive buffer (ev. "garbage" from previous offers) *)
    REPEAT
        p.Receive(buf, 0, LEN(buf), 0, fip, fport, len, res);
    UNTIL res = AosUDP.Timeout;

    exit := FALSE;
    INC(xid);
    AosOut.Enter; AosOut.String("AosDHCP: Discover - xid "); AosOut.Int(xid, 0); AosOut.Exit;
    time := AosKernel.GetTimer();

    (* Send DHCP-DISCOVER Msg *)
    msgLen := CreateDHCPDiscoverMsg(int.dev.local, xid, 0(*((time-start) DIV AosKernel.second)*), buf);
    p.SendBroadcast(int, BootPServer, buf, 0, msgLen);

    (* Receive the DHCP-OFFER *)
    p.Receive(buf, 0, LEN(buf), offerDelay, fip, fport, len, res);

    (* Is it a BOOTPReply from DHCP ServerPort? *)
    IF (res = AosUDP.Ok) & (fport = BootPServer) & (len >= 28) & (buf[0] = 2X) & (xid = AosNet.Get4(buf, 4)) THEN
        localAdr := AosNet.Get4(buf, 16);
        AosOut.Enter; AosOut.String("AosDHCP: BootP reply from "); AosIP.OutAdr(AosNet.Get4(buf, 20));
        AosOut.String("; IP offered: "); AosIP.OutAdr(localAdr); AosOut.Exit;

        IF len > 236 THEN
            ParseOptions(buf, 236, len, maskAdr, gatewayAdr, dns, domain, serverIP, rxid, msgType);
            AosOut.Enter; AosOut.String("AosDHCP: Offer received - xid "); AosOut.Int(rxid, 0);
            AosOut.String( " msgType "); AosOut.Int(ORD(msgType), 0); AosOut.Exit;

            (* Check xid to make sure it matches the most recent DISCOVER request *)
            IF (rxid = xid) & (msgType = 2X) THEN (* DHCP-OFFER *)
                requestTries := 1; requestDelay := 2 * AosKernel.second;
                LOOP
                    (* empty receive buffer (ev. "garbage" from previous offers or ACKs) *)
                    REPEAT
                        p.Receive(buf, 0, LEN(buf), 0, fip, fport, len, res);
                    UNTIL res = AosUDP.Timeout;

                    time := AosKernel.GetTimer();
                    AosOut.Enter; AosOut.String("AosDHCP: Request - xid "); AosOut.Int(xid,0); AosOut.Exit;
                    msgLen := CreateDHCPRequestMsg(int.dev.local, xid, 0(*((time-start) DIV AosKernel.second)*), buf, serverIP, localAdr);
                    p.SendBroadcast(int, BootPServer, buf, 0, msgLen);
                    (* Receive the DHCP-ACK *)
                    p.Receive(buf, 0, LEN(buf), requestDelay, fip, fport, len, res);
                    IF (res = AosUDP.Ok) & (fport = BootPServer) & (len >= 28) & (buf[0] = 2X) THEN
                        IF (localAdr = AosNet.Get4(buf, 16)) THEN
                            ParseOptions(buf, 236, len, maskAdr, gatewayAdr, dns, domain, serverIP, rxid, msgType);
                            AosOut.Enter; AosOut.String("AosDHCP: Ack - xid "); AosOut.Int(rxid,0);
                            AosOut.String( " msgType "); AosOut.Int(ORD(msgType), 0); AosOut.Ln;
                            AosOut.String("  localIP: "); AosIP.OutAdr(localAdr);
                            AosOut.String("; mask: "); AosIP.OutAdr(maskAdr);
                            AosOut.String("; gateway: "); AosIP.OutAdr(gatewayAdr);
                            AosOut.Exit;
                            exit := FALSE
                        ELSE
                            AosOut.Enter; AosOut.String("AosDHCP: Nack - xid "); AosOut.Int(rxid,0);
                            AosOut.String( " msgType "); AosOut.Int(ORD(msgType), 0); AosOut.Ln;
                            AosOut.Exit;
                            localAdr := AosIP.NilAdr;
                            exit := TRUE;
                            res := 3;
                        END;
        EXIT
    END;
                    (* REPEAT UNTIL AosKernel.GetTimer() - time > requestDelay; *) (* busy wait *)
                    sleep := offerDelay - (AosKernel.GetTimer() - time);
                    IF sleep > 0 THEN
                        t.Sleep(sleep);
                    END;
                    IF requestTries >= MaxRequestTries THEN
                        AosOut.Enter; AosOut.String("AosDHCP: Retransmission limit reached"); AosOut.Exit;
                    END;
                    INC(requestTries); requestDelay := requestDelay * 2
                END;
                IF exit THEN EXIT END
            ELSE
                (* wrong type *)
                res := 2;
            END
        ELSE
            (* wrong length *)
            res := 1;
        END
    END;

    (* Exponential backoff *)
    (* REPEAT UNTIL AosKernel.GetTimer() - time > offerDelay; *) (* busy wait *)

    sleep := offerDelay - (AosKernel.GetTimer() - time);
    IF sleep > 0 THEN
        t.Sleep(sleep);
    END;

    offerDelay := offerDelay*3 DIV 2;
    INC(offerTries);
    IF offerTries > MaxOfferTries THEN
        res := AosUDP.Timeout;
        EXIT;
    END;
END;



№ 5684   21-10-2007 06:03 Ответить на это сообщение Ответить на это сообщение с цитированием
Ответ на »сообщение 5682« (Стэн)
___________________________

Ответ на »сообщение 5680« (Илья Ермаков)
___________________________
Тот факт, что lexem на выходе не равен LEX_DEF конечно важен, но кто сказал, что программист не ошибется в группе этих строчек?
Какая разница, что искать - место с BREAK или некорректную логику присваивание условной переменной?

Вот Вам и разница в мотивах. Меня не очень волнует "кто сказал, что программист не ошибётся". Опытному программисту для таких несложных циклов, действительно, всё равно, как написать, и если он в уме прокрутил условия на цикл, то он запишет его верно.
Меня волнует, как будет выглядеть чтение и понимание этого цикла.


№ 5683   21-10-2007 06:00 Ответить на это сообщение Ответить на это сообщение с цитированием
Ответ на »сообщение 5665« (Руслан Богатырев)
___________________________

>>>По-моему, в отношении FOR дело несколько проще. Для Вирта введение этого цикла в язык -- компромисс, на котором настаивают другие. Ему этот цикл похоже не нравится. В любом случае в классическом Паскале, классической Модуле-2 запрещалось изменение значения управляющей переменной внутри цикла. Явно.

Да, верно. (На всякий случай все же проверил с помощью компилятора XDS. :) )
Забавно: я читал у Вирта, что управляющая переменная "не должна" меняться в теле цикла, но ошибочно воспринимал это как "всего лишь" рекомендацию.

Но вопрос все же поставлен шире.
Возьмем пример, который несколько раз приводил Стэн:

WHILE (i < len) & Condition(i) DO ... END;

где Condition(VAR i: INTEGER): BOOLEAN (возможно) меняет значение переменной i.
То, что обнаружение (возможных) побочных эффектов для компилятора не представляет проблемы, было продемонстрировано с помощью цикла FOR.
Но все же такая конструкция не запрещена, так же как не запрещены функции с побочными эффектами.
Братья-функциональщики спрашивают: WHY-Y-Y? :)
Возникла гипотеза (»сообщение 5654«), что в виртовских языках два уровня строгости: обязательный и "рекомендательный". Компилятор не запрещает некоторые отклонения от "хорошего стиля", которые он может обнаружить. (В качестве примера я сослался на компилятор и анализатор КП в ББ.)
Как Вы относитесь к такому предположению?
 AVC


№ 5682   21-10-2007 05:59 Ответить на это сообщение Ответить на это сообщение с цитированием
Ответ на »сообщение 5680« (Илья Ермаков)
___________________________
>>> Я бы оставил свой вариант, но, поскольку один и тот же lexem нужен два раза, ввёл его отдельной переменной.
Отлично, только таким образом мы извратили всю идею условий и инвариантов в циклах. Тот факт, что lexem на выходе не равен LEX_DEF конечно важен, но кто сказал, что программист не ошибется в группе этих строчек?

lexem = result.lexem;
if ( lexem == LEX_DEF )


Какая разница, что искать - место с BREAK или некорректную логику присваивание условной переменной?


№ 5681   21-10-2007 05:52 Ответить на это сообщение Ответить на это сообщение с цитированием
Ответ на »сообщение 5678« (Илья Ермаков)
___________________________
>>> Ну, точно так же и будет использоваться на новом шаге итерации. Цикл будет работать точно так же. Только вместо ветки ELSE return в тот же секунд произойдёт выход из цикла по ложности условия. А после цикла - всё тот же return, который я не написал.
Нет, не также...
Выражение result = prs_def().parse( result.str, params ); перезапишет result.lexeme
Выражение while ( result.lexeme == LEX_DEF ); даст FALSE и выйдет из цикла в место того, чтобы продолжить выполнение...
Более того, структура result в общем случае у меня является вариантной записью, поэтому некоторые поля могут быть не определены. Поэтому некорректно ждать что prs_def().parse( result.str, params ) не возвратит result.lexeme == LEX_DEF, может и возвратить, поэтому Ваш вариант не исправляется простой заменой условий в выражении на result.lexeme != LEX_DEF.


№ 5680   21-10-2007 05:50 Ответить на это сообщение Ответить на это сообщение с цитированием
Я бы оставил свой вариант, но, поскольку один и тот же lexem нужен два раза, ввёл его отдельной переменной.


  lexem = result.lexem;
  if ( lexem == LEX_DEF )
    result = ...;
while ( lexem == LEX_DEF );


В любом случае, я бы сначала построил каркас цикла, а уже потом смотрел, как там и что в нём меняется. И если бы изменение мешало проверке условия, просто запомнил бы значение в отдельной переменной.


№ 5679   21-10-2007 05:46 Ответить на это сообщение Ответить на это сообщение с цитированием
Ответ на »сообщение 5678« (Илья Ермаков)
___________________________
А, ну да, Вы модифицируете result, и вторая проверка в условии цикла уже не будет совпадать с первой.
Ща подумаем.


№ 5678   21-10-2007 05:43 Ответить на это сообщение Ответить на это сообщение с цитированием
Ответ на »сообщение 5676« (Стэн)
___________________________

Ответ на »сообщение 5674« (Илья Ермаков)
___________________________

Не имеет значение, что возвращает prs_def().parse( result.str, params ) в result.lexeme, важно, что она модифицирует result.str, которое используется на новом шаге итерации...

Ну, точно так же и будет использоваться на новом шаге итерации. Цикл будет работать точно так же. Только вместо ветки ELSE return в тот же секунд произойдёт выход из цикла по ложности условия. А после цикла - всё тот же return, который я не написал.


№ 5677   21-10-2007 05:41 Ответить на это сообщение Ответить на это сообщение с цитированием
Ответ на »сообщение 5673« (Стэн)
___________________________

Ответ на »сообщение 5671« (Илья Ермаков)
___________________________
А Вы знаете, что наши каратисты очень часто побеждают японцев на чемпионатах, хотя япония считается родиной каратэ (для некоторых стилей)? А знаете почему? Потому, что в японии четкое следование традиции и технике непреложная истина, а наши допускают "творческое отступление от канона", поэтому более эффективны...

Пример понят. Пример хороший.
Идея Вашего примера в чём? Есть некорые "традиции", "каноны" в искусстве (а в науке-технике - правила грамотной работы), которые хорошо работают в большинстве ситуаций. Но всегда есть "особые точки", в которых требуется импровизация. И именно этой импровизацией, способностью при необходимости отклониться от канонов и обусловлен уровень мастерства, и победа в схватке.

А что у нас с программированием? Да, "особые точки" тоже есть. Но, во-первых, для того, чтобы в них "импровизировать", требуется чёткое владение и применение канонов во всех обычных случаях. Этого не наблюдается, наоборот - повальная "импровизация" всюду, "пратизанщина с вилами", вместо использования обычных, нормальных средств. Начиная от ваяния самопальных циклов и кончая ваянием самопальных алгоритов-велосипедов, на порядок худших общеизвестных аналогов.
Во-вторых, к вопросу о циклах - ценой использования "канонов" и в малом множестве "особых точек" будет далеко не проигрыш на ринге, и даже не некоторая потеря эффективности а, может быть, пара лишних строк. Значение всего этого так исчезающе мало, что стоит ли заморачиваться даже мыслями об этих "импровизациях"? Не лучше ли подумать над задачей.


<<<... | 5696—5687 | 5686—5677 | 5676—5667 | ...>>>
Всего сообщений в теме: 6256; страниц: 626; текущая страница: 58


Добавить свое сообщение

Отслеживать это обсуждение

Дополнительная навигация:
Количество сообщений на странице

Порядок сортировки сообщений
Новое сообщение вверху списка (сетевая хронология)
Первое сообщение вверху списка (обычная хронология)

Перейти на конкретную страницу по номеру
  
Время на сайте: GMT минус 5 часов

Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
Функция может не работать в некоторых версиях броузеров.

Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

 
© При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
Все используемые на сайте торговые марки являются собственностью их производителей.

Яндекс цитирования