Forth
http://fforum.winglion.ru/

FORTH-рефакторинг
http://fforum.winglion.ru/viewtopic.php?f=2&t=3013
Страница 1 из 2

Автор:  gudleifr [ Чт июл 17, 2014 13:01 ]
Заголовок сообщения:  FORTH-рефакторинг

Код:
VARIABLE RESULT
VARIABLE TAIL
: INCREMENT ( A --) DUP @ 1+ SWAP ! ;
: DECREMENT ( A --) DUP @ 1- SWAP ! ;
: NORM ( N, K -- N, K | N, N-K)
  2DUP 2* - DUP 0< IF + ELSE DROP THEN ;
: REDUCTION ( N, K -- N-1, K, N-1, K-1 | )
  NORM ?DUP IF TAIL INCREMENT SWAP 1- SWAP 2DUP 1-
  ELSE RESULT INCREMENT TAIL DECREMENT DROP THEN ;
: COMPUTE ( N, K -- CNK)
  0 RESULT ! 1 TAIL !
  BEGIN REDUCTION TAIL @ 0= UNTIL RESULT @ ;

Имеется очевидный кусок (надеюсь все понимают, что он делает), реализованный в лоб (разве что, без факториалов).
Налицо избыточные сравнения и перетасовки стека.
Предложения по причесыванию?

P.S. Это задача именно на "классический FORTH", а не на рассуждения по его "развитию".


M перенес обсуждение в соответствующий раздел


Автор:  Hishnik [ Чт июл 17, 2014 13:25 ]
Заголовок сообщения:  Re: FORTH-рефакторинг

А что, по работе надо, или так, в рамках общего просвещения нас, убогих? :)

Автор:  gudleifr [ Чт июл 17, 2014 13:30 ]
Заголовок сообщения:  Re: FORTH-рефакторинг

Хищник писал(а):
А что, по работе надо..?
Вчера было надо. Написал в статье, что случай маловероятен, а насколько - пришлось срочно считать.

Однако, вопрос серьезен. Я вижу здесь только два направления рефакторинга: активное переписывание в кодах и возможность "на лету" отказываться от стека для вычислений и создавать подходящие структуры.
"Классического" решения я не знаю. Разве что, переменные в стек возвратов перебросить...

Автор:  gudleifr [ Пн авг 04, 2014 23:10 ]
Заголовок сообщения:  Re: FORTH-рефакторинг

Ладно, раз никто не предложил ничего путного, делаем очевидное:
Код:
VARIABLE RESULT
: CN0 ( N, 0 -- -1) 2DROP 1 RESULT +! -1 ;
: CN1 ( N, 1 -- -1) DROP RESULT +! -1 ;
: CNK ( N, K -- N-1, K, N-1, K-1, 1)
  SWAP 1- SWAP 2DUP 1- 1 ;
: NORM ( N, K -- N, K | N, N-K)
  2DUP 2* - DUP 0< IF + ELSE DROP THEN ;
: REDUCTION ( N, K -- N-1, K, N-1, K-1, 1 | -1)
  NORM DUP IF DUP 1- IF CNK ELSE CN1 THEN ELSE CN0 THEN ;
: COMPUTE ( N, K -- CNK)
  0 RESULT ! 1 BEGIN >R REDUCTION R> + ?DUP 0= UNTIL RESULT @ ;

Очевидно? Очевидно!
Но, как бы, непонятно, как от первого варианта перейти ко второму, не зная "смысла задачи"?
И, конечно, чем дальше, тем больше скрупулезных проверок типа "а точно ли мы не порушили стек в этой ветке?"
Кто знает более симпатичные варианты причесывания?

Автор:  gudleifr [ Пн авг 11, 2014 21:33 ]
Заголовок сообщения:  Re: FORTH-рефакторинг

Тут коллега KPG облыжно обвинил меня в неуважении к национальному достоянию - материалам RusFIG. Воспользуюсь наводкой и попробую поискать там что-то то теме (недаром же, наверное, коллега true-gue как-то заметил, что я пишу старомодно). Найденные "выводы" принадлежат если я не ошибаюсь к мейнстриму: один из непоследних людей написал библиотеку, а другой на ее примере показал, как надо чужие программы читать. Раз я рассуждаю здесь о писании кода, то ожидания читателей должны бы мне помочь.
Итак:
Цитата:
* Для подхода к изучению чужого кода нужно во-первых иметь хотя бы примерное знакомство с предметной областью, теорией (совсем необязательно досконально знать, достаточно хотя бы "плавать" в терминах, а непосредственные детали реализации можно будет уяснить из самого кода). Если не отходить далеко от нашего примера — к началу конкретного этого разбора я знал в чём состоит задача "сборки мусора", знал что она обозначается как gc, имел смутное представление о том "как оно работает".
* Правило "читай с конца" применённое в самом начале разбора обосновывается технологическими особенностями Форта. Так как forward-ссылки в форте из-за однопроходности компилятора не используются, то определения (процедуры) идут в тексте по мере нарастания сложности, из-за чего "главные", наиболее мощные слова оказываются в конце текста. Отсюда и идёт правило что разбирать программу на форте надо с конца и разматывать клубок нужно, начиная с "торчащей нитки" — главного слова или одного из них.
* Последовательность разбора каждой процедуры примерно такая: имя, комментарии, код. Если смысл слова становится понятен на более раннем этапе, то остальные делать соответственно незачем.
* Авторы всегда стараются давать говорящие названия своим процедурам (по крайней мере — говорящие им), ваша задача — постараться понять что имелось в виду. Есть стихийно сложившийся "пиратский кодекс" по построению названий форта, который был обзорно описан в "Этимологии", он может помочь. Также можно посмотреть советы по именованию от ~pinka. Но главное подспорье — это здравый смысл (как впрочем и всегда).
* Проверяйте ваши "догадки", осознанные предположения о структуре/работе программы эмпирически — то есть непосредственно запуская програму и прогоняя тестовые куски.

И что? Где здесь FORTH? Есть ли здесь хоть что-то, чего не знают "не-FORTH-программисты"? Нет.
Это, конечно, подтверждает мои догадки о стремлении Rus-FIG привести FORTH к нормам "обычных языков", но, все равно, обидно. Говорим о самодокументированности, о лексиконах, о интерпретации на всех этапах... А на деле - полная беспомощность...
По крайней мере, на поставленные в теме вопросы ответа я не получил.
Может, кто-то, сможет копнуть материалы Rus-FIG более удачно?

P.S. Прошу мне простить некоторую категоричность. Она объясняется тем, что мне достаточно часто приходилось читать чужой код. И смею, вас заверить, там все по-другому. См., например, игрушечный пример того, с чем приходится иметь дело: http://www.gudleifr.h1.ru/4i.html, с середины.

Автор:  Hishnik [ Вт авг 12, 2014 00:31 ]
Заголовок сообщения:  Re: FORTH-рефакторинг

gudleifr писал(а):
Это, конечно, подтверждает мои догадки о стремлении Rus-FIG привести FORTH к нормам "обычных языков", но, все равно, обидно. Говорим о самодокументированности, о лексиконах, о интерпретации на всех этапах... А на деле - полная беспомощность...

Да, это одна из проблем. Быть лидером в какой-то области не так уж просто. Всем хочется иметь какой-то якорь. Вот и берется за основу Си или даже Бейсик.

Автор:  gudleifr [ Чт окт 23, 2014 19:30 ]
Заголовок сообщения:  Re: FORTH-рефакторинг

Еще одна задачка на рефакторинг: http://www.gudleifr.h1.ru/c84.html.
Вычлененные там операторы - СЛУЧАЙ, ПЕРЕХОД, ВЫДАЧА, КОНЕЦ, ХОД-ИГРОКА, ХОД-БАРТА - в нормальных языках реализуются, разве что, макросами (или дурацкими объектами).
А на FORTH?
Попутно хорошо бы:
1. Добавить симметрию игрок-компьютер; или, наоборот, полностью отказаться от нее в пользу улучшения играбельности (книжности).
2. Структурировать программу таким образом, что бы упомянутые ошибки стали более явными, и добавление новых фич стало бы более простым.
3. Навесить средства сбора статистики/выбора стратегии.

Автор:  gudleifr [ Пн фев 16, 2015 12:26 ]
Заголовок сообщения:  Re: FORTH-рефакторинг

Продолжение оттуда же:
Цитата:
В PASCAL-играх "стратегические" части - это набор вложенных циклов (вульгарно олицетворяющих кибернетическое понятие "сверхустойчивости"). Когда "бой" заканчивается, его результаты принимаются и проверяется их невыход за границы разумного. Превышение "пределов" вызывает прекращение текущего цила повторения "боев", и проверку более слабых условий, если и они нарушаются, то прерывается следующий цикл...
По мере погружения в циклы, условия должны становиться все строже и строже, чтобы "бои" проводились в строго заданных условиях, а каждый цикл должен добавлять к этим условиям все новые, исправляя ошибки, возникающие при работе его внутренних частей.
Например, внешний цикл Mario.bas перебирает игроков, а вложенный в него - уровни игры. Если уровень проходится игроком благополучно, игрок переходит к следующему, а если нет - цикл прервывается и очередь переходит к другому игроку.
Если бы PASCAL-программист имел в голове "схему вложенности условий", непротиворечивую и достаточную, все было бы очень красиво - программа "думала бы сама собой", разумно реагируя на все неприятности... Однако, всегда бывает наоборот: общий набор условий берется "как у всех", а затем, при необходимости что-то добавить, программист выбирает "примерно подходящий" цикл и обвешивает новый блок кучей новых условий/флагов (и никто не гарантирует, что они не будут конфликтовать с другим). Вплоть до добавления новых циклов, противоречащих изначальному плану.
Если считать, что самый нижний уровень все-таки связан с ЭВМ (ведь, должна же программа делать что-то полезное), то вся остальная программа - многоступенчатый перевод c "языка PASCAL" на "язык машины". Отсюда - и дикий размер кода (даже, с учетом излишней универсальности на всех уровнях и хранения данных в виде PASCAL-процедур).

От "нормального гомеостата" эта конструкция радикально отличается тем, что как бы не "переключались лампочки" на верхних уровнях, работает-то все равно только один самый внутренний цикл, только в разных условиях. Т.е. очевидно, существует возможность установки нужных условий/флагов, не поднимаясь "до самого верха", а тут же "по месту" (как АВАРИЯ в "Лунолете").

В FORTH все еще хуже (или наоборот?), ведь у него и так есть внешний цикл от которого не уйти - Цикл Управления. И, даже, применяется схожая матрешка циклов вокруг WORD. Так, может, в FORTH-программировании можно перенести часть этих "гомеостатов" на сам FORTH? Или придумать другой способ написания диалоговых программ?

P.S. Кстати, невозможность организовать "матрешку циклов" в визуальных программах привела к тому, что "визуальные программисты" вообще ничего не могут написать...

Автор:  gudleifr [ Пн фев 16, 2015 15:04 ]
Заголовок сообщения:  Re: FORTH-рефакторинг

P.P.S. На неразрешимость проблемы "правильности зацикливания" как бы намекает старая C-фича "курица или яйцо".
Допустим наша программа:
Код:
main()
{
A;
for (i=...) { B; }
}

Со временем наборы операторов A и B разрастаются до размеров, требующих их выделения в отдельные подпрограммы:
Как правильно?
Код:
b(i)
{
B;
}
main()
{
A;
for (i=...) { B(i); }
}

или
Код:
b(i)
{
for (i=...) { B }
}
main()
{
A;
b;
}

Понятно, что если цикл один, то делаем как удобнее/логичнее/нагляднее. Да и какая разница?..
А если в матрешке десяток циклов и способы выделения процедур внутри или снаружи цикла чередуются? Черт ногу сломит...

Автор:  Hishnik [ Вт фев 17, 2015 03:42 ]
Заголовок сообщения:  Re: FORTH-рефакторинг

1)
Код:
10 0 DO I ОЧИСТИТЬ-ЯЧЕЙКУ LOOP

2)
Код:
ОЧИСТИТЬ-МАССИВ

Во втором случае мне неинтересны детали очистки. Может быть, там и еще что-то делается, кроме записи в ячейки, неважно. И так, в принципе, на каждом уровне - если мне на этом уровне важно видеть, что действие выполняется в цикле, цикл будет виден. Если нет - спрячу внутрь.

Автор:  gudleifr [ Вт фев 17, 2015 13:27 ]
Заголовок сообщения:  Re: FORTH-рефакторинг

Hishnik писал(а):
И так, в принципе, на каждом уровне - если мне на этом уровне важно видеть, что действие выполняется в цикле, цикл будет виден. Если нет - спрячу внутрь.
И я об том же. Если циклов много - будет страшно. И речь не о том, как сделать "менее страшно", а как вообще туда не ходить... Большинство циклов в структурных программах - от лукавого.

Автор:  Hishnik [ Ср фев 25, 2015 00:43 ]
Заголовок сообщения:  Re: FORTH-рефакторинг

gudleifr писал(а):
И речь не о том, как сделать "менее страшно", а как вообще туда не ходить... Большинство циклов в структурных программах - от лукавого.

Конечный автомат, по крайней мере, в некоторых случаях.

Автор:  gudleifr [ Ср фев 25, 2015 01:07 ]
Заголовок сообщения:  Re: FORTH-рефакторинг

Hishnik писал(а):
Конечный автомат, по крайней мере, в некоторых случаях.
Ну, как бы, хорошо откомпилированный конечный автомат (не претендующий на гомеостатичность) превращается просто в набор IF...GOTO. Что на FORTH обычно смотрится препохабнейше и может быть оправдано только желанием разбиратьр егулярные выражения.
Конечно, можно вовремя вспомнить, что сам FORTH является конечным автоматом, но решений, использующих этот факт я не встречал (хотя, сам писать пытался).

P.S. Из "Лунолета" пришла идея организовать гомеостаз в виде "вычислительного управляющего воздействия" блока "обработки флагов" на "вычислительный блок (зарылись в грунт - отсчитываем время назад с тем же ускорением, кончилось топливо - выполняем расчет за сверхбольшой интервал и т.д.)

Автор:  Hishnik [ Ср фев 25, 2015 01:28 ]
Заголовок сообщения:  Re: FORTH-рефакторинг

gudleifr писал(а):
Ну, как бы, хорошо откомпилированный конечный автомат (не претендующий на гомеостатичность) превращается просто в набор IF...GOTO.

А CASE смотрится вполне изящно и сопровождаемо. Он внутри, конечно, тоже в какой-то степени IF.. GOTO, но по большому счету это относится к любой управляющей конструкции.

gudleifr писал(а):
зарылись в грунт - отсчитываем время назад с тем же ускорением

Да ну зачем же? Из кинематики выводится время до грунта.

Автор:  gudleifr [ Ср фев 25, 2015 02:00 ]
Заголовок сообщения:  Re: FORTH-рефакторинг

Hishnik писал(а):
А CASE смотрится вполне изящно и сопровождаемо.
Изящных не встречал. Обычно - источник ошибок и причина полной нечитаемости кода. Впрочем, я не видел, чтобы какому нибудь PASCAL-исту CASE помешал бы плодить циклы.

Hishnik писал(а):
Из кинематики выводится время до грунта.
Его и отсчитываем. (В позднихх версиях "Лунолета", правда, этот блок не поместился в память калькулятора, и его заменили на "итерактивное самовыкапывание" (с забавными побочными эффектами)).

Страница 1 из 2 Часовой пояс: UTC + 3 часа [ Летнее время ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/