Автор |
Сообщение |
|
|
Заголовок сообщения: |
Re: FORTH-рефакторинг |
|
|
Продолжение писания в таком стиле привело к следующим наблюдениям: 1. Хотя, списки адекватно описывают любые ситуации на игровом поле, оперировать ими можно только вручную (программист/пользователь должен сам помнить помнить, "что где лежит"). Можно, конечно, ценой применения ООП и, соответственно, потери управляемости кода, "срезать несколько углов", перейдя от списковых данных к реляционным. Или, наоборот, усложнить программу анализаторами семантики символов. 2. Наиболее удобным будет двухуровневое представление данных: на уровне списков будет осуществляться ввод и запросы детальной информации, а на уровне статистики будет накапливаться информация, нужная для основных операций игры (суммарная сила, суммарный тоннаж, суммарный бонус и т.д.). Получается некий аналог ЭЛТ: списки представляют собой некоторый многомерный набор таблиц (реляционные "кубы данных"), изменения которой немедленно пересчитываются и отображаются в "главной таблице". 3. Концепция "главной таблицы" позволяет рассматривать ее как набор регистров, в которых удобно производить вычисления над списками, что избавит от необходимости протаскивать их через обычный стек данных. 4. Естественным FORTH-представлением этой структуры является вторичная FORTH-машина, отличающаяся от изначальной заменой СТЕКА на проблемно-ориентированную регистрово-табличную модель (возможно, имеющую естественное визуальное представление); и СЛОВАРЯ - на хранилище сигналов о необходимости пересчета (ЗНАЧЕНИЕ, соответственно, будет представляться состоянием списков).
Продолжение писания в таком стиле привело к следующим наблюдениям: 1. Хотя, списки адекватно описывают любые ситуации на игровом поле, оперировать ими можно только вручную (программист/пользователь должен сам помнить помнить, "что где лежит"). Можно, конечно, ценой применения ООП и, соответственно, потери управляемости кода, "срезать несколько углов", перейдя от списковых данных к реляционным. Или, наоборот, усложнить программу анализаторами семантики символов. 2. Наиболее удобным будет двухуровневое представление данных: на уровне списков будет осуществляться ввод и запросы детальной информации, а на уровне статистики будет накапливаться информация, нужная для основных операций игры (суммарная сила, суммарный тоннаж, суммарный бонус и т.д.). Получается некий аналог ЭЛТ: списки представляют собой некоторый многомерный набор таблиц (реляционные "кубы данных"), изменения которой немедленно пересчитываются и отображаются в "главной таблице". 3. Концепция "главной таблицы" позволяет рассматривать ее как набор регистров, в которых удобно производить вычисления над списками, что избавит от необходимости протаскивать их через обычный стек данных. 4. Естественным FORTH-представлением этой структуры является вторичная FORTH-машина, отличающаяся от изначальной заменой СТЕКА на проблемно-ориентированную регистрово-табличную модель (возможно, имеющую естественное визуальное представление); и СЛОВАРЯ - на хранилище сигналов о необходимости пересчета (ЗНАЧЕНИЕ, соответственно, будет представляться состоянием списков).
|
|
|
|
Добавлено: Ср дек 02, 2015 13:55 |
|
|
|
|
|
Заголовок сообщения: |
Re: FORTH-рефакторинг |
|
|
gudleifr писал(а): Для реализации списка Ну, что, ничего не надумалось? У меня получается препохабненько (в примере - начало карточной военно-морской игры на Win32Forth): Код: : START ;
\ СТРОКОВЫЕ КОНСТАНТЫ : SI ( <NAME> -- ) HERE CREATE >NAME , DOES> ( -- A) @ ; : SD ( <NAME> -- A) HERE CREATE >NAME DUP , DOES> ( -- A) @ ;
\ МАССИВ ДЛЯ ХРАНЕНИЯ СПИСКОВ HEX 10000 DECIMAL ALLOCATE DROP CONSTANT LST : LD ( E -- AW) 2* CELLS LST + ; : LN ( E -- AE) LD CELL+ ; 1 0 LD ! 0 0 LN ! : LA ( -- E) 0 LN @ IF 0 LN DUP @ DUP LN @ ROT ! ELSE 0 LD DUP @ DUP 1+ ROT ! THEN 0 OVER LN ! ; : LF ( E --) 0 LN @ OVER LN ! 0 LN ! ;
\ ДОБАВЛЕНИЕ НОВОЙ ГОЛОВЫ СПИСКА ... : L+ ( W,E1 -- E2) LA DUP>R LN ! R@ LD ! R> ; \ ... И СОХРАНЕНИЕ ЕЕ ПО АДРЕСУ СТАРОЙ : @L+! ( W,AE -- ) DUP>R @ L+ R> ! ;
\ ТАСОВАНИЕ СПИСКА ПУТЕМ УДАЛЕНИЯ ... : L- ( E1,N -- E2,W) ?DUP IF SWAP DUP ROT 1- 0 ?DO LN @ LOOP LN DUP @ DUP LN @ ROT ! ELSE DUP LN @ SWAP THEN DUP LD @ SWAP LF ; \ ... И ВСТАВКИ В НОВЫЙ СПИСОК : L// ( E1,N -- E2) 0 SWAP BEGIN ?DUP WHILE DUP>R RANDOM ROT SWAP L- ROT L+ R> 1- REPEAT NIP ;
\ ПЕРЕБОР ЭЛЕМЕНТОВ СПИСКА ПО ПОРЯДКУ : LR ( E,EX --) >R BEGIN ?DUP WHILE DUP LD @ R@ EXECUTE ( E,W-- E) LN @ REPEAT R>DROP ;
\ СУНДУКИ - НАБОР КОРАБЛЕЙ
\ СИМВОЛЫ SI 3" SI 5" SI 16" SI "A" SI "B" SI "C" SI TORPEDO SI ASW SI AIR SI BOMBER SI DAM-CTRL SI EVASIVE SI ECM SI COVER SI AIR-DEF SI (I) SI (II) SI (III) SI (IV) SI (V) SI (VI) SI USSSR SI USA SI GB SI ITALY SI FRANCE SI JAPAN SI КРУПНЫЙ SI АВИАНОСЕЦ SI ПОДЛОДКА SI ЖИВУЧЕСТЬ SI ОЧКОВ SI BB SI CVN
\ КАРТА - СПИСОК ТРИПЛЕТОВ (ИМЯ, СИМВОЛЫ, ПАРАМЕТРЫ), ГДЕ \ СИМВОЛЫ - СПИСОК СИМВОЛОВ, А \ ПАРАМЕТРЫ - СПИСОК ПАР (СИМВОЛ, ЗНАЧЕНИЕ) : КАРТА+ ( E1 <NAME> -- E2) 0 0 0 L+ L+ SD SWAP L+ SWAP L+ ; : S+ ( E,S -- E) OVER LD @ LN @ LD @L+! ; : P= ( E,N,S -- E) SWAP 0 L+ L+ OVER LD @ LN @ LN @ LD @L+! ;
\ КАРТА С ТЕМИ ЖЕ ПАРАМЕТРАМИ, СПИСКИ, СРОСШИЕСЯ ХВОСТАМИ : СИСТЕРШИП+ ( E1 <NAME> -- E2) DUP LD @ LN @ DUP LD @ SWAP LN @ LD @ 0 L+ L+ SD SWAP L+ SWAP L+ ;
0 КАРТА+ IOWA BB S+ (I) S+ USA S+ КРУПНЫЙ S+ 5" S+ 16" S+ "B" S+ "C" S+ 10 ЖИВУЧЕСТЬ P= 14 ОЧКОВ P= СИСТЕРШИП+ NEW-JERSEY КАРТА+ CONSTELLATION CVN S+ (I) S+ USA S+ АВИАНОСЕЦ S+ КРУПНЫЙ S+ 12 ЖИВУЧЕСТЬ P= 22 ОЧКОВ P= 2 AIR P= 4 AIR-DEF P= СИСТЕРШИП+ NIMITZ СИСТЕРШИП+ KENNEDY 5 L// CONSTANT КОРАБЛИ
\ ПРОВЕРКА : EX5 8 SPACES DUP LD @ COUNT TYPE SPACE LN @ LD @ . CR ; : EX4 ['] EX5 LR ; : EX3 8 SPACES COUNT TYPE CR ; : EX2 ['] EX3 LR ; : EX1 DUP LD @ COUNT TYPE CR DUP LN @ LD @ EX2 LN @ LN @ LD @ EX4 CR ; CR КОРАБЛИ ' EX1 LR FORGET START
Пример работы:
NIMITZ КРУПНЫЙ АВИАНОСЕЦ USA (I) CVN AIR-DEF 4 AIR 2 ОЧКОВ 22 ЖИВУЧЕСТЬ 12
NEW-JERSEY "C" "B" 16" 5" КРУПНЫЙ USA (I) BB ОЧКОВ 14 ЖИВУЧЕСТЬ 10
CONSTELLATION КРУПНЫЙ АВИАНОСЕЦ USA (I) CVN AIR-DEF 4 AIR 2 ОЧКОВ 22 ЖИВУЧЕСТЬ 12
KENNEDY КРУПНЫЙ АВИАНОСЕЦ USA (I) CVN AIR-DEF 4 AIR 2 ОЧКОВ 22 ЖИВУЧЕСТЬ 12
IOWA "C" "B" 16" 5" КРУПНЫЙ USA (I) BB ОЧКОВ 14 ЖИВУЧЕСТЬ 10
ok Т.е. дальше L+ и @L+! дело не идет - только свапинг увеличивается. Проще в голове список представить и через них выразить, чем какие-то умные списковые слова измыслить.
[quote="gudleifr"]Для реализации списка[/quote] Ну, что, ничего не надумалось? У меня получается препохабненько (в примере - начало карточной военно-морской игры на Win32Forth): [code]: START ;
\ СТРОКОВЫЕ КОНСТАНТЫ : SI ( <NAME> -- ) HERE CREATE >NAME , DOES> ( -- A) @ ; : SD ( <NAME> -- A) HERE CREATE >NAME DUP , DOES> ( -- A) @ ;
\ МАССИВ ДЛЯ ХРАНЕНИЯ СПИСКОВ HEX 10000 DECIMAL ALLOCATE DROP CONSTANT LST : LD ( E -- AW) 2* CELLS LST + ; : LN ( E -- AE) LD CELL+ ; 1 0 LD ! 0 0 LN ! : LA ( -- E) 0 LN @ IF 0 LN DUP @ DUP LN @ ROT ! ELSE 0 LD DUP @ DUP 1+ ROT ! THEN 0 OVER LN ! ; : LF ( E --) 0 LN @ OVER LN ! 0 LN ! ;
\ ДОБАВЛЕНИЕ НОВОЙ ГОЛОВЫ СПИСКА ... : L+ ( W,E1 -- E2) LA DUP>R LN ! R@ LD ! R> ; \ ... И СОХРАНЕНИЕ ЕЕ ПО АДРЕСУ СТАРОЙ : @L+! ( W,AE -- ) DUP>R @ L+ R> ! ;
\ ТАСОВАНИЕ СПИСКА ПУТЕМ УДАЛЕНИЯ ... : L- ( E1,N -- E2,W) ?DUP IF SWAP DUP ROT 1- 0 ?DO LN @ LOOP LN DUP @ DUP LN @ ROT ! ELSE DUP LN @ SWAP THEN DUP LD @ SWAP LF ; \ ... И ВСТАВКИ В НОВЫЙ СПИСОК : L// ( E1,N -- E2) 0 SWAP BEGIN ?DUP WHILE DUP>R RANDOM ROT SWAP L- ROT L+ R> 1- REPEAT NIP ;
\ ПЕРЕБОР ЭЛЕМЕНТОВ СПИСКА ПО ПОРЯДКУ : LR ( E,EX --) >R BEGIN ?DUP WHILE DUP LD @ R@ EXECUTE ( E,W-- E) LN @ REPEAT R>DROP ;
\ СУНДУКИ - НАБОР КОРАБЛЕЙ
\ СИМВОЛЫ SI 3" SI 5" SI 16" SI "A" SI "B" SI "C" SI TORPEDO SI ASW SI AIR SI BOMBER SI DAM-CTRL SI EVASIVE SI ECM SI COVER SI AIR-DEF SI (I) SI (II) SI (III) SI (IV) SI (V) SI (VI) SI USSSR SI USA SI GB SI ITALY SI FRANCE SI JAPAN SI КРУПНЫЙ SI АВИАНОСЕЦ SI ПОДЛОДКА SI ЖИВУЧЕСТЬ SI ОЧКОВ SI BB SI CVN
\ КАРТА - СПИСОК ТРИПЛЕТОВ (ИМЯ, СИМВОЛЫ, ПАРАМЕТРЫ), ГДЕ \ СИМВОЛЫ - СПИСОК СИМВОЛОВ, А \ ПАРАМЕТРЫ - СПИСОК ПАР (СИМВОЛ, ЗНАЧЕНИЕ) : КАРТА+ ( E1 <NAME> -- E2) 0 0 0 L+ L+ SD SWAP L+ SWAP L+ ; : S+ ( E,S -- E) OVER LD @ LN @ LD @L+! ; : P= ( E,N,S -- E) SWAP 0 L+ L+ OVER LD @ LN @ LN @ LD @L+! ;
\ КАРТА С ТЕМИ ЖЕ ПАРАМЕТРАМИ, СПИСКИ, СРОСШИЕСЯ ХВОСТАМИ : СИСТЕРШИП+ ( E1 <NAME> -- E2) DUP LD @ LN @ DUP LD @ SWAP LN @ LD @ 0 L+ L+ SD SWAP L+ SWAP L+ ;
0 КАРТА+ IOWA BB S+ (I) S+ USA S+ КРУПНЫЙ S+ 5" S+ 16" S+ "B" S+ "C" S+ 10 ЖИВУЧЕСТЬ P= 14 ОЧКОВ P= СИСТЕРШИП+ NEW-JERSEY КАРТА+ CONSTELLATION CVN S+ (I) S+ USA S+ АВИАНОСЕЦ S+ КРУПНЫЙ S+ 12 ЖИВУЧЕСТЬ P= 22 ОЧКОВ P= 2 AIR P= 4 AIR-DEF P= СИСТЕРШИП+ NIMITZ СИСТЕРШИП+ KENNEDY 5 L// CONSTANT КОРАБЛИ
\ ПРОВЕРКА : EX5 8 SPACES DUP LD @ COUNT TYPE SPACE LN @ LD @ . CR ; : EX4 ['] EX5 LR ; : EX3 8 SPACES COUNT TYPE CR ; : EX2 ['] EX3 LR ; : EX1 DUP LD @ COUNT TYPE CR DUP LN @ LD @ EX2 LN @ LN @ LD @ EX4 CR ; CR КОРАБЛИ ' EX1 LR FORGET START
Пример работы:
NIMITZ КРУПНЫЙ АВИАНОСЕЦ USA (I) CVN AIR-DEF 4 AIR 2 ОЧКОВ 22 ЖИВУЧЕСТЬ 12
NEW-JERSEY "C" "B" 16" 5" КРУПНЫЙ USA (I) BB ОЧКОВ 14 ЖИВУЧЕСТЬ 10
CONSTELLATION КРУПНЫЙ АВИАНОСЕЦ USA (I) CVN AIR-DEF 4 AIR 2 ОЧКОВ 22 ЖИВУЧЕСТЬ 12
KENNEDY КРУПНЫЙ АВИАНОСЕЦ USA (I) CVN AIR-DEF 4 AIR 2 ОЧКОВ 22 ЖИВУЧЕСТЬ 12
IOWA "C" "B" 16" 5" КРУПНЫЙ USA (I) BB ОЧКОВ 14 ЖИВУЧЕСТЬ 10
ok[/code] Т.е. дальше L+ и @L+! дело не идет - только свапинг увеличивается. Проще в голове список представить и через них выразить, чем какие-то умные списковые слова измыслить.
|
|
|
|
Добавлено: Сб ноя 28, 2015 11:26 |
|
|
|
|
|
Заголовок сообщения: |
Re: FORTH-рефакторинг |
|
|
Еще одна задачка на рефакторинг. Для реализации списка очевидно необходимы всего 4 слова: LD - адрес поля данных элемента, LN - адрес поля связи элемента, LA - выделение места под новый элемент, LF - освобождение места удаляемого элемента (мы не эстеты и слово ATOM - проверку, что в LD - "просто значение" или ссылка на вложенный список - не используем). Требуется из этих четырех слов собрать (с минимизацией DUP-ов и SWAP-ов) слова для работы со следующими типами списков. 1. Просто список. Операции вставки и удаления. 2. Список структур. Каждый элемент списка верхнего уровня - ссылка на список определенной длины, каждый элемент которого "ассоциируется" с некоторым "полем структуры". Операции добавления/удаления новой "структуры", доступа к ее "полям". 3. Список параметров. Каждый элемент списка верхнего уровня - ссылка на список, первый элемент которого содержит идентификатор параметра, а остальные - его значение. Операции добавления/удаления параметра, доступ к его значению.
Еще одна задачка на рефакторинг. Для реализации списка очевидно необходимы всего 4 слова: LD - адрес поля данных элемента, LN - адрес поля связи элемента, LA - выделение места под новый элемент, LF - освобождение места удаляемого элемента (мы не эстеты и слово ATOM - проверку, что в LD - "просто значение" или ссылка на вложенный список - не используем). Требуется из этих четырех слов собрать (с минимизацией DUP-ов и SWAP-ов) слова для работы со следующими типами списков. 1. Просто список. Операции вставки и удаления. 2. Список структур. Каждый элемент списка верхнего уровня - ссылка на список определенной длины, каждый элемент которого "ассоциируется" с некоторым "полем структуры". Операции добавления/удаления новой "структуры", доступа к ее "полям". 3. Список параметров. Каждый элемент списка верхнего уровня - ссылка на список, первый элемент которого содержит идентификатор параметра, а остальные - его значение. Операции добавления/удаления параметра, доступ к его значению.
|
|
|
|
Добавлено: Пн ноя 02, 2015 11:43 |
|
|
|
|
|
Заголовок сообщения: |
Re: FORTH-рефакторинг |
|
|
Hishnik писал(а): А CASE смотрится вполне изящно и сопровождаемо. Изящных не встречал. Обычно - источник ошибок и причина полной нечитаемости кода. Впрочем, я не видел, чтобы какому нибудь PASCAL-исту CASE помешал бы плодить циклы. Hishnik писал(а): Из кинематики выводится время до грунта. Его и отсчитываем. (В позднихх версиях "Лунолета", правда, этот блок не поместился в память калькулятора, и его заменили на "итерактивное самовыкапывание" (с забавными побочными эффектами)).
[quote="Hishnik"]А CASE смотрится вполне изящно и сопровождаемо.[/quote]Изящных не встречал. Обычно - источник ошибок и причина полной нечитаемости кода. Впрочем, я не видел, чтобы какому нибудь PASCAL-исту CASE помешал бы плодить циклы.
[quote="Hishnik"]Из кинематики выводится время до грунта.[/quote]Его и отсчитываем. (В позднихх версиях "Лунолета", правда, этот блок не поместился в память калькулятора, и его заменили на "итерактивное самовыкапывание" (с забавными побочными эффектами)).
|
|
|
|
Добавлено: Ср фев 25, 2015 02:00 |
|
|
|
|
|
Заголовок сообщения: |
Re: FORTH-рефакторинг |
|
|
gudleifr писал(а): Ну, как бы, хорошо откомпилированный конечный автомат (не претендующий на гомеостатичность) превращается просто в набор IF...GOTO. А CASE смотрится вполне изящно и сопровождаемо. Он внутри, конечно, тоже в какой-то степени IF.. GOTO, но по большому счету это относится к любой управляющей конструкции. gudleifr писал(а): зарылись в грунт - отсчитываем время назад с тем же ускорением Да ну зачем же? Из кинематики выводится время до грунта.
[quote="gudleifr"]Ну, как бы, хорошо откомпилированный конечный автомат (не претендующий на гомеостатичность) превращается просто в набор IF...GOTO.[/quote] А CASE смотрится вполне изящно и сопровождаемо. Он внутри, конечно, тоже в какой-то степени IF.. GOTO, но по большому счету это относится к любой управляющей конструкции.
[quote="gudleifr"]зарылись в грунт - отсчитываем время назад с тем же ускорением[/quote] Да ну зачем же? Из кинематики выводится время до грунта.
|
|
|
|
Добавлено: Ср фев 25, 2015 01:28 |
|
|
|
|
|
Заголовок сообщения: |
Re: FORTH-рефакторинг |
|
|
Hishnik писал(а): Конечный автомат, по крайней мере, в некоторых случаях. Ну, как бы, хорошо откомпилированный конечный автомат (не претендующий на гомеостатичность) превращается просто в набор IF...GOTO. Что на FORTH обычно смотрится препохабнейше и может быть оправдано только желанием разбиратьр егулярные выражения. Конечно, можно вовремя вспомнить, что сам FORTH является конечным автоматом, но решений, использующих этот факт я не встречал (хотя, сам писать пытался). P.S. Из "Лунолета" пришла идея организовать гомеостаз в виде "вычислительного управляющего воздействия" блока "обработки флагов" на "вычислительный блок (зарылись в грунт - отсчитываем время назад с тем же ускорением, кончилось топливо - выполняем расчет за сверхбольшой интервал и т.д.)
[quote="Hishnik"]Конечный автомат, по крайней мере, в некоторых случаях.[/quote]Ну, как бы, хорошо откомпилированный конечный автомат (не претендующий на гомеостатичность) превращается просто в набор IF...GOTO. Что на FORTH обычно смотрится препохабнейше и может быть оправдано только желанием разбиратьр егулярные выражения. Конечно, можно вовремя вспомнить, что сам FORTH является конечным автоматом, но решений, использующих этот факт я не встречал (хотя, сам писать пытался).
P.S. Из "Лунолета" пришла идея организовать гомеостаз в виде "вычислительного управляющего воздействия" блока "обработки флагов" на "вычислительный блок (зарылись в грунт - отсчитываем время назад с тем же ускорением, кончилось топливо - выполняем расчет за сверхбольшой интервал и т.д.)
|
|
|
|
Добавлено: Ср фев 25, 2015 01:07 |
|
|
|
|
|
Заголовок сообщения: |
Re: FORTH-рефакторинг |
|
|
gudleifr писал(а): И речь не о том, как сделать "менее страшно", а как вообще туда не ходить... Большинство циклов в структурных программах - от лукавого. Конечный автомат, по крайней мере, в некоторых случаях.
[quote="gudleifr"]И речь не о том, как сделать "менее страшно", а как вообще туда не ходить... Большинство циклов в структурных программах - от лукавого.[/quote] Конечный автомат, по крайней мере, в некоторых случаях.
|
|
|
|
Добавлено: Ср фев 25, 2015 00:43 |
|
|
|
|
|
Заголовок сообщения: |
Re: FORTH-рефакторинг |
|
|
Hishnik писал(а): И так, в принципе, на каждом уровне - если мне на этом уровне важно видеть, что действие выполняется в цикле, цикл будет виден. Если нет - спрячу внутрь. И я об том же. Если циклов много - будет страшно. И речь не о том, как сделать "менее страшно", а как вообще туда не ходить... Большинство циклов в структурных программах - от лукавого.
[quote="Hishnik"]И так, в принципе, на каждом уровне - если мне на этом уровне важно видеть, что действие выполняется в цикле, цикл будет виден. Если нет - спрячу внутрь.[/quote]И я об том же. Если циклов много - будет страшно. И речь не о том, как сделать "менее страшно", а как вообще туда не ходить... Большинство циклов в структурных программах - от лукавого.
|
|
|
|
Добавлено: Вт фев 17, 2015 13:27 |
|
|
|
|
|
Заголовок сообщения: |
Re: FORTH-рефакторинг |
|
|
1) Код: 10 0 DO I ОЧИСТИТЬ-ЯЧЕЙКУ LOOP 2) Код: ОЧИСТИТЬ-МАССИВ Во втором случае мне неинтересны детали очистки. Может быть, там и еще что-то делается, кроме записи в ячейки, неважно. И так, в принципе, на каждом уровне - если мне на этом уровне важно видеть, что действие выполняется в цикле, цикл будет виден. Если нет - спрячу внутрь.
1) [code]10 0 DO I ОЧИСТИТЬ-ЯЧЕЙКУ LOOP[/code] 2) [code]ОЧИСТИТЬ-МАССИВ[/code] Во втором случае мне неинтересны детали очистки. Может быть, там и еще что-то делается, кроме записи в ячейки, неважно. И так, в принципе, на каждом уровне - если мне на этом уровне важно видеть, что действие выполняется в цикле, цикл будет виден. Если нет - спрячу внутрь.
|
|
|
|
Добавлено: Вт фев 17, 2015 03:42 |
|
|
|
|
|
Заголовок сообщения: |
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; } Понятно, что если цикл один, то делаем как удобнее/логичнее/нагляднее. Да и какая разница?.. А если в матрешке десяток циклов и способы выделения процедур внутри или снаружи цикла чередуются? Черт ногу сломит...
P.P.S. На неразрешимость проблемы "правильности зацикливания" как бы намекает старая C-фича "курица или яйцо". Допустим наша программа: [code]main() { A; for (i=...) { B; } }[/code] Со временем наборы операторов A и B разрастаются до размеров, требующих их выделения в отдельные подпрограммы: Как правильно? [code] b(i) { B; } main() { A; for (i=...) { B(i); } }[/code] или [code] b(i) { for (i=...) { B } } main() { A; b; }[/code] Понятно, что если цикл один, то делаем как удобнее/логичнее/нагляднее. Да и какая разница?.. А если в матрешке десяток циклов и способы выделения процедур внутри или снаружи цикла чередуются? Черт ногу сломит...
|
|
|
|
Добавлено: Пн фев 16, 2015 15:04 |
|
|
|
|
|
Заголовок сообщения: |
Re: FORTH-рефакторинг |
|
|
Продолжение оттуда же: Цитата: В PASCAL-играх "стратегические" части - это набор вложенных циклов (вульгарно олицетворяющих кибернетическое понятие "сверхустойчивости"). Когда "бой" заканчивается, его результаты принимаются и проверяется их невыход за границы разумного. Превышение "пределов" вызывает прекращение текущего цила повторения "боев", и проверку более слабых условий, если и они нарушаются, то прерывается следующий цикл... По мере погружения в циклы, условия должны становиться все строже и строже, чтобы "бои" проводились в строго заданных условиях, а каждый цикл должен добавлять к этим условиям все новые, исправляя ошибки, возникающие при работе его внутренних частей. Например, внешний цикл Mario.bas перебирает игроков, а вложенный в него - уровни игры. Если уровень проходится игроком благополучно, игрок переходит к следующему, а если нет - цикл прервывается и очередь переходит к другому игроку. Если бы PASCAL-программист имел в голове "схему вложенности условий", непротиворечивую и достаточную, все было бы очень красиво - программа "думала бы сама собой", разумно реагируя на все неприятности... Однако, всегда бывает наоборот: общий набор условий берется "как у всех", а затем, при необходимости что-то добавить, программист выбирает "примерно подходящий" цикл и обвешивает новый блок кучей новых условий/флагов (и никто не гарантирует, что они не будут конфликтовать с другим). Вплоть до добавления новых циклов, противоречащих изначальному плану. Если считать, что самый нижний уровень все-таки связан с ЭВМ (ведь, должна же программа делать что-то полезное), то вся остальная программа - многоступенчатый перевод c "языка PASCAL" на "язык машины". Отсюда - и дикий размер кода (даже, с учетом излишней универсальности на всех уровнях и хранения данных в виде PASCAL-процедур). От "нормального гомеостата" эта конструкция радикально отличается тем, что как бы не "переключались лампочки" на верхних уровнях, работает-то все равно только один самый внутренний цикл, только в разных условиях. Т.е. очевидно, существует возможность установки нужных условий/флагов, не поднимаясь "до самого верха", а тут же "по месту" (как АВАРИЯ в "Лунолете"). В FORTH все еще хуже (или наоборот?), ведь у него и так есть внешний цикл от которого не уйти - Цикл Управления. И, даже, применяется схожая матрешка циклов вокруг WORD. Так, может, в FORTH-программировании можно перенести часть этих "гомеостатов" на сам FORTH? Или придумать другой способ написания диалоговых программ? P.S. Кстати, невозможность организовать "матрешку циклов" в визуальных программах привела к тому, что "визуальные программисты" вообще ничего не могут написать...
Продолжение оттуда же: [quote]В PASCAL-играх "стратегические" части - это набор вложенных циклов (вульгарно олицетворяющих кибернетическое понятие "сверхустойчивости"). Когда "бой" заканчивается, его результаты принимаются и проверяется их невыход за границы разумного. Превышение "пределов" вызывает прекращение текущего цила повторения "боев", и проверку более слабых условий, если и они нарушаются, то прерывается следующий цикл... По мере погружения в циклы, условия должны становиться все строже и строже, чтобы "бои" проводились в строго заданных условиях, а каждый цикл должен добавлять к этим условиям все новые, исправляя ошибки, возникающие при работе его внутренних частей. Например, внешний цикл Mario.bas перебирает игроков, а вложенный в него - уровни игры. Если уровень проходится игроком благополучно, игрок переходит к следующему, а если нет - цикл прервывается и очередь переходит к другому игроку. Если бы PASCAL-программист имел в голове "схему вложенности условий", непротиворечивую и достаточную, все было бы очень красиво - программа "думала бы сама собой", разумно реагируя на все неприятности... Однако, всегда бывает наоборот: общий набор условий берется "как у всех", а затем, при необходимости что-то добавить, программист выбирает "примерно подходящий" цикл и обвешивает новый блок кучей новых условий/флагов (и никто не гарантирует, что они не будут конфликтовать с другим). Вплоть до добавления новых циклов, противоречащих изначальному плану. Если считать, что самый нижний уровень все-таки связан с ЭВМ (ведь, должна же программа делать что-то полезное), то вся остальная программа - многоступенчатый перевод c "языка PASCAL" на "язык машины". Отсюда - и дикий размер кода (даже, с учетом излишней универсальности на всех уровнях и хранения данных в виде PASCAL-процедур).[/quote] От "нормального гомеостата" эта конструкция радикально отличается тем, что как бы не "переключались лампочки" на верхних уровнях, работает-то все равно только один самый внутренний цикл, только в разных условиях. Т.е. очевидно, существует возможность установки нужных условий/флагов, не поднимаясь "до самого верха", а тут же "по месту" (как АВАРИЯ в "Лунолете").
В FORTH все еще хуже (или наоборот?), ведь у него и так есть внешний цикл от которого не уйти - Цикл Управления. И, даже, применяется схожая матрешка циклов вокруг WORD. Так, может, в FORTH-программировании можно перенести часть этих "гомеостатов" на сам FORTH? Или придумать другой способ написания диалоговых программ?
P.S. Кстати, невозможность организовать "матрешку циклов" в визуальных программах привела к тому, что "визуальные программисты" вообще ничего не могут написать...
|
|
|
|
Добавлено: Пн фев 16, 2015 12:26 |
|
|
|
|
|
Заголовок сообщения: |
Re: FORTH-рефакторинг |
|
|
Еще одна задачка на рефакторинг: http://www.gudleifr.h1.ru/c84.html. Вычлененные там операторы - СЛУЧАЙ, ПЕРЕХОД, ВЫДАЧА, КОНЕЦ, ХОД-ИГРОКА, ХОД-БАРТА - в нормальных языках реализуются, разве что, макросами (или дурацкими объектами). А на FORTH? Попутно хорошо бы: 1. Добавить симметрию игрок-компьютер; или, наоборот, полностью отказаться от нее в пользу улучшения играбельности (книжности). 2. Структурировать программу таким образом, что бы упомянутые ошибки стали более явными, и добавление новых фич стало бы более простым. 3. Навесить средства сбора статистики/выбора стратегии.
Еще одна задачка на рефакторинг: [url]http://www.gudleifr.h1.ru/c84.html[/url]. Вычлененные там операторы - СЛУЧАЙ, ПЕРЕХОД, ВЫДАЧА, КОНЕЦ, ХОД-ИГРОКА, ХОД-БАРТА - в нормальных языках реализуются, разве что, макросами (или дурацкими объектами). А на FORTH? Попутно хорошо бы: 1. Добавить симметрию игрок-компьютер; или, наоборот, полностью отказаться от нее в пользу улучшения играбельности (книжности). 2. Структурировать программу таким образом, что бы упомянутые ошибки стали более явными, и добавление новых фич стало бы более простым. 3. Навесить средства сбора статистики/выбора стратегии.
|
|
|
|
Добавлено: Чт окт 23, 2014 19:30 |
|
|
|
|
|
Заголовок сообщения: |
Re: FORTH-рефакторинг |
|
|
gudleifr писал(а): Это, конечно, подтверждает мои догадки о стремлении Rus-FIG привести FORTH к нормам "обычных языков", но, все равно, обидно. Говорим о самодокументированности, о лексиконах, о интерпретации на всех этапах... А на деле - полная беспомощность... Да, это одна из проблем. Быть лидером в какой-то области не так уж просто. Всем хочется иметь какой-то якорь. Вот и берется за основу Си или даже Бейсик.
[quote="gudleifr"]Это, конечно, подтверждает мои догадки о стремлении Rus-FIG привести FORTH к нормам "обычных языков", но, все равно, обидно. Говорим о самодокументированности, о лексиконах, о интерпретации на всех этапах... А на деле - полная беспомощность...[/quote] Да, это одна из проблем. Быть лидером в какой-то области не так уж просто. Всем хочется иметь какой-то якорь. Вот и берется за основу Си или даже Бейсик.
|
|
|
|
Добавлено: Вт авг 12, 2014 00:31 |
|
|
|
|
|
Заголовок сообщения: |
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, с середины.
Тут коллега KPG облыжно обвинил меня в неуважении к национальному достоянию - материалам RusFIG. Воспользуюсь наводкой и попробую поискать там что-то то теме (недаром же, наверное, коллега true-gue как-то заметил, что я пишу старомодно). Найденные "выводы" принадлежат если я не ошибаюсь к мейнстриму: один из непоследних людей написал библиотеку, а другой на ее примере показал, как надо чужие программы читать. Раз я рассуждаю здесь о писании кода, то ожидания читателей должны бы мне помочь. Итак: [quote]* Для подхода к изучению чужого кода нужно во-первых иметь хотя бы примерное знакомство с предметной областью, теорией (совсем необязательно досконально знать, достаточно хотя бы "плавать" в терминах, а непосредственные детали реализации можно будет уяснить из самого кода). Если не отходить далеко от нашего примера — к началу конкретного этого разбора я знал в чём состоит задача "сборки мусора", знал что она обозначается как gc, имел смутное представление о том "как оно работает". * Правило "читай с конца" применённое в самом начале разбора обосновывается технологическими особенностями Форта. Так как forward-ссылки в форте из-за однопроходности компилятора не используются, то определения (процедуры) идут в тексте по мере нарастания сложности, из-за чего "главные", наиболее мощные слова оказываются в конце текста. Отсюда и идёт правило что разбирать программу на форте надо с конца и разматывать клубок нужно, начиная с "торчащей нитки" — главного слова или одного из них. * Последовательность разбора каждой процедуры примерно такая: имя, комментарии, код. Если смысл слова становится понятен на более раннем этапе, то остальные делать соответственно незачем. * Авторы всегда стараются давать говорящие названия своим процедурам (по крайней мере — говорящие им), ваша задача — постараться понять что имелось в виду. Есть стихийно сложившийся "пиратский кодекс" по построению названий форта, который был обзорно описан в "Этимологии", он может помочь. Также можно посмотреть советы по именованию от ~pinka. Но главное подспорье — это здравый смысл (как впрочем и всегда). * Проверяйте ваши "догадки", осознанные предположения о структуре/работе программы эмпирически — то есть непосредственно запуская програму и прогоняя тестовые куски.[/quote] И что? Где здесь FORTH? Есть ли здесь хоть что-то, чего не знают "не-FORTH-программисты"? Нет. Это, конечно, подтверждает мои догадки о стремлении Rus-FIG привести FORTH к нормам "обычных языков", но, все равно, обидно. Говорим о самодокументированности, о лексиконах, о интерпретации на всех этапах... А на деле - полная беспомощность... По крайней мере, на поставленные в теме вопросы ответа я не получил. Может, кто-то, сможет копнуть материалы Rus-FIG более удачно?
P.S. Прошу мне простить некоторую категоричность. Она объясняется тем, что мне достаточно часто приходилось читать чужой код. И смею, вас заверить, там все по-другому. См., например, игрушечный пример того, с чем приходится иметь дело: [url]http://www.gudleifr.h1.ru/4i.html[/url], с середины.
|
|
|
|
Добавлено: Пн авг 11, 2014 21:33 |
|
|
|
|
|
Заголовок сообщения: |
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 @ ; Очевидно? Очевидно! Но, как бы, непонятно, как от первого варианта перейти ко второму, не зная "смысла задачи"? И, конечно, чем дальше, тем больше скрупулезных проверок типа "а точно ли мы не порушили стек в этой ветке?" Кто знает более симпатичные варианты причесывания?
Ладно, раз никто не предложил ничего путного, делаем очевидное: [code]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 @ ;[/code] Очевидно? Очевидно! Но, как бы, непонятно, как от первого варианта перейти ко второму, не зная "смысла задачи"? И, конечно, чем дальше, тем больше скрупулезных проверок типа "а точно ли мы не порушили стек в этой ветке?" Кто знает более симпатичные варианты причесывания?
|
|
|
|
Добавлено: Пн авг 04, 2014 23:10 |
|
|
|
|