Несколько слов по бектрекингу.
Бектрекинг тут понимается как "идея реализованная в лоб в каждом конкретном случае".
То есть без либ вообще. Взяли и вызвали остаток кода. Всё.
Основные проблемы при использовании бектрекинговых итераторов:
Как прервать итератор?
Примечание от 13.12.2018
Можно в итератор передавать RP@ для сброса в случае необходимости.Код:
... RP@ TEST: DUP 10 = IF RP! EXIT THEN ....
К примеру мы нашли нужное значение и наша задача выйти из итератора.
Как это сделать не зная особенностей реализации отдельного итератора?
Рассмотрим 3 варианта:
1)
Создание конвенции о вызовах итераторов.
В простейшем случае при вызове остатка кода второй элемент на стеке возвратов представляет собою указатель для сброса стека возвратов. Т.е. в остатке кода достаточно сделать так:
Код:
RDROP R> RP! EXIT
Недостатки: усложнение написания итераторов, дополнительная нагрузка на программиста ( поддерживает ли итератор соглашение?)
2)
Использование механизма перехвата исключений.
Достаточно всего трёх слов:
CATCH: \ --> / err|0 <--
\ вызвать остаток кода и перехватить исключение, если оно было. При откате положить на стек код исключения.
TO-CATCH \ -- 0
\ Выйти из кода, который был вызван из CATCH или CATCH: без исключений с сохранением ТОЛЬКО стека данных
THROW^ \ <-- err|0
\ На обратном ходу (при откате) снять число со стека данных и перейти на CATCH ( CATCH: ), если код отличен от 0 с очисткой стеков данных и возвратов.
Недостатки: дополнительная нагрузка на стек исключений, запись THROW^ CATCH: ... может сбить с толку.
3)
Дополнительный инструментарий.
Тут останавливаться особо не над чем.
Реализация доп.стека под бектрекинг и операции с ним описаны у Гасаненко, а также реализована в СПФ у ~profit'а.
Кстати, Гасаненко говорил, что можно использовать не стек, а цепочку.
См. "Одностековая реализация бэктрекинга для языка Форт". Кстати, единственная работа, которую легко найти в инете. Всё остальное пришлось пережёвывать из поставки СПФ.
Недостатки: доп. сущность, за которой надо следить. Новый лексикон в который надо "въехать".
Я, к примеру, 2 месяца пытался понять логику PRO И CONT , и меня внезапно осенило на прогулке
![Smile :)](./images/smilies/icon_smile.gif)
На самом деле ничего сложного. Непривычно и всё.
Проблема вторая.
Локальные переменные совместно с итераторами.
Условимся, что переменные должны поддерживать многопоточность.
То есть хранение переменных в ШК не подходит.
Хочется, чтобы можно было делать так:
: TEST { a b } ITER: a ! ... ;
Использование конвенций не выглядит тут оптимальным решением.
А вот варианты 2 и 3 выглядят более менее отлично.
Поскольку 3-й вариант описан, сосредоточимся на 2-ом.
Ограничение: должно использоваться слово CATCH:
Так гораздо проще организовать, однако ж не столь очевидно будет применение этого слова для лок.переменных. А это доп. нагрузка на программиста.
Хм, будем думать дальше как сделать логичней и прозрачней.
Несколько слов по бектрекингу.
Бектрекинг тут понимается как "идея реализованная в лоб в каждом конкретном случае".
То есть без либ вообще. Взяли и вызвали остаток кода. Всё.
Основные проблемы при использовании бектрекинговых итераторов:
Как прервать итератор?
[b][i]
Примечание от 13.12.2018
Можно в итератор передавать RP@ для сброса в случае необходимости.[/i][/b]
[code]
... RP@ TEST: DUP 10 = IF RP! EXIT THEN ....
[/code]
К примеру мы нашли нужное значение и наша задача выйти из итератора.
Как это сделать не зная особенностей реализации отдельного итератора?
Рассмотрим 3 варианта:
1)
Создание конвенции о вызовах итераторов.
В простейшем случае при вызове остатка кода второй элемент на стеке возвратов представляет собою указатель для сброса стека возвратов. Т.е. в остатке кода достаточно сделать так:
[code]
RDROP R> RP! EXIT
[/code]
Недостатки: усложнение написания итераторов, дополнительная нагрузка на программиста ( поддерживает ли итератор соглашение?)
2)
Использование механизма перехвата исключений.
Достаточно всего трёх слов:
CATCH: \ --> / err|0 <--
\ вызвать остаток кода и перехватить исключение, если оно было. При откате положить на стек код исключения.
TO-CATCH \ -- 0
\ Выйти из кода, который был вызван из CATCH или CATCH: без исключений с сохранением ТОЛЬКО стека данных
THROW^ \ <-- err|0
\ На обратном ходу (при откате) снять число со стека данных и перейти на CATCH ( CATCH: ), если код отличен от 0 с очисткой стеков данных и возвратов.
Недостатки: дополнительная нагрузка на стек исключений, запись THROW^ CATCH: ... может сбить с толку.
3)
Дополнительный инструментарий.
Тут останавливаться особо не над чем.
Реализация доп.стека под бектрекинг и операции с ним описаны у Гасаненко, а также реализована в СПФ у ~profit'а.
Кстати, Гасаненко говорил, что можно использовать не стек, а цепочку.
См. "Одностековая реализация бэктрекинга для языка Форт". Кстати, единственная работа, которую легко найти в инете. Всё остальное пришлось пережёвывать из поставки СПФ.
Недостатки: доп. сущность, за которой надо следить. Новый лексикон в который надо "въехать".
Я, к примеру, 2 месяца пытался понять логику PRO И CONT , и меня внезапно осенило на прогулке :) На самом деле ничего сложного. Непривычно и всё.
Проблема вторая.
Локальные переменные совместно с итераторами.
Условимся, что переменные должны поддерживать многопоточность.
То есть хранение переменных в ШК не подходит.
Хочется, чтобы можно было делать так:
: TEST { a b } ITER: a ! ... ;
Использование конвенций не выглядит тут оптимальным решением.
А вот варианты 2 и 3 выглядят более менее отлично.
Поскольку 3-й вариант описан, сосредоточимся на 2-ом.
Ограничение: должно использоваться слово CATCH:
Так гораздо проще организовать, однако ж не столь очевидно будет применение этого слова для лок.переменных. А это доп. нагрузка на программиста.
Хм, будем думать дальше как сделать логичней и прозрачней.