День 11. Чтение стандарта dpans94-rus

День 11. Чтение стандарта dpans94-rus

Чтение стандарта. Размышления о стековой нотации. Реализация Жизни на Перле.

На форуме натойчиво советуют читать стандарт. Последовал совету. Хотел его распечатать, но там очень интерсеное оформление под plain-text, получется на много бумаги. Переформатировал, умешьшил шрифт и.д. Все равно много. Вышел из положения тем, что читаю и одновременно немного его форматирую и заодно удаляю многие пустые фразы, как-то, Название главы, а дальше фраза, что мол в настоящем стандарте она не определена. Смысловой нагрузки нет, зато занимает место. Сие покоцанное творение доступно отсюда

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

По стековой нотациивозникли соображения. Сначала я никак не мог понять ее страность – почему вершина стека расположили слева? Ведь интуитивнее – справа,в том порядке в котором читаем:

  ВерхнееЧисло ЗаНим А Б С Д ... ДноСтека

начав активно писать, быстро понял правильность принятого положения – вершина стека справа

  ДноСтека ... Д С Б А ВерхнееЧисло

Все правильно – имеено в таком порядке мы вводим параметры! И соответсвенно, так они и располагаются на стеке. Как только понял – быстро перенял и усвоил. Получилось естественно. Жаль, что это, действительно важный момент, не объясняют, не акцентируются на нем.

Дальнейшее соображение касалось, почему принято, что слова могут возвращать различное число параметров на стеке... Выяснилось тоже практикой, путем набивания своих (блин, ну сколько ж можно!!!) шишок. Различное число параметров, как правило, возвращают слова, результат работы которых неоднозначен, и в программе поэтому нужно принимать решение... Например выделение памяти, слово ALLOCATE. Оно возвращает флаг успешности и/или (вот где неоднозначность числа парметров!) адрес начала блока выделенной памяти. Понятно, если операция закончилась неудачно, зачем еще на стек класть ненужный параметр – его все равно потом удалят. Понятно, что и коррекстеность кодирования, требует от кодировщика анализа такого варианта развития ситуации. Т.е. отпадает необходимость в дополнительном операторе DROP, в отдельной ветви условного оператора

 ALLOCATE ( адр 1 | 0 )
 INVERT IF
 ABORT" Не смог выделить память!"
 THEN

Кстати, еще один большой вопрос к разработчика SP-Forth – ау, парни, куда дели NOT ??? Знаете, как без него хреново???? Ну, на что похожа эта фраза INVERT ? Согласитесь, ну очень просится сюда слово NOT

Понятно и логично, правда? А теперь, давайте немножко подумаем. И, скажем, пусть в случае неуспеха слово возвращает нулевой адрес? Чем полохо? Что изменится? Добавится только один оператор.

 ALLOCATE ( адр | 0 )
 ?DUP IF ELSE
 ABORT" Не смог выделить память!"
 THEN

?DUP продублирует число на стеке, если оно не ноль. IF удалит верхнее число, и если это было не ноль ничего не сделает, т.к. эта ветвь пуста, а если ноль – ситуция с невыделенным адресом. Вуаля, мы вылетаем с ошибкой,что и нужно было.

Да, правильно, сюда очень просится перловское слово UNLESS – IF наоборто – очень уж удобное.

 ALLOCATE ( адр | 0 )
 ?DUP UNLESS
 ABORT" Не смог выделить память!"
 THEN

или, еще, сокращая

 ALLOCATE ( адр | 0 )
  ?UNLESS
 ABORT" Не смог выделить память!"
 THEN

сделать такое слово ?UNLESS которое бы в случае нуля на стеке (общепризнанный FALSE) удаляет его и начинает выполнять соотвествующую ветвь...

Этот пример, показал, что не все так однозначно с различным количеством возвращаемых параметров. Этот вопрос лежит в области принципов (!) создания программ именно для Forth среды.

Так вот, эти самые принципы и должна раскрывать любая книга, претендующая на роль учебника, любой материал – на роль введения, первого знакомства. Этого в настоящем дистрибутиве SP-Forth – нет!

В последнем примере, я фактически совместил в одной переменной две сущности – адрес и результат выполнения операции. Часто, эти сущности, являются взаимоисключающими, и поэтому их совмещение целесообразно на практике – если операция была выолнена неуспешно, зачем выдавать бессмысленный результат. Так вот в нашем случае, мы его и выдаем! И однозначно бессмысленный результат и говорит о результате операции. В других языках, роль бессмысленого результата выполняют предопределенные значения NULL или undef...

Работая в Forth быстро замечаешь одну закономерность в использовании условных операторах – иногда нужно чтобы они удаляли анализируемое значение а иногда – нет. Когда речь идет о флагах, то практически всегда их нужно удалять со стека. И существующие условные операторы так и спроектированы. Если же идет речь об анализе бессмысленных значений, о которых мы говорили, то нет. Поэтому их приходится дублировать словом ?DUP. Неплохо бы было их совместить в одном управляющем слове. Вот три варианта, которые моглт бы претендовать на эту роль

      0?: .... THEN
  FALSE?: .... THEN
  ?UNLESS .... THEN

Стандарт – это нечто общее, декларация, что-так должно быть. Часто встречается фраза "определено реализацией". И на сообственном опыте уже выясняешь как это реализовано в SP-Forth Трудно его читать – слишком много общих фраз, различных отступлений. Многое на моем этапе, на этапе изучения, просто лишнее, не понятное. Это занимает время, отвлекает. Однозначно, нужен материал, переработанный, с ориентацию на кокретный интерпретатор.

Решил сравнить Perl и SP-Forth по скорости и удобству написания программ. Пока на примере игры Жизнь. Правда, сравнение не корректное – т.к. архитектуру программы я уже отработал, Perl владею гораздо лучше. Но, думаю, что парочку интересных наблюдений таки сделать.

Игра была написана где-то приблизительно за час. С учетом ее отладки. Ошибки были в основном логические: где-то неправильно проставил координаты, где-то в синтаксисе ошибся. Однако "сырая" программа была написана очень быстро, минут где-то за 25. Да, конечно, Forth для меня язык новый, то была первая программа. Но должен заметить, что Перл обеспечил еще несколько удобств, которые сильно помогают в реальной жизни

Ниже, сама программа.
# Life game

$Pole[0] = '.x.x.xxxx.xx.....x'; $Pole[1] = '.x.x.xxxx.xx.....x'; $Pole[2] = '.x.x.xxxx.xx.....x'; $Pole[3] = '.x.x.xxxx.xx.....x'; $Pole[4] = '.x.x.xxxx.xx.....x'; $Pole[5] = '.x.x.xxxx.xx.....x'; $Pole[6] = '.x.x.xxxx.xx.....x'; $Pole[7] = '.x.x.xxxx.xx.....x';

sub IsSosed { my ($x, $y) = (shift, shift) ; return 0 if $x < 0 ; return 0 if $y < 0 ; return 0 if $x > $#Pole ; return 0 if $y >= length($Pole[$x]) ; return 1 if substr($Pole[$x], $y , 1) eq 'x' ; return 0 ; };

sub KolSosed { for($i=0; $i<$#Pole; $i++) { for($j=0; $j < length($Pole[$i]); $j++) { $sosed=0 ;

$sosed++ if IsSosed($i-1, $j) ; $sosed++ if IsSosed($i-1, $j-1) ; $sosed++ if IsSosed($i-1, $j+1) ;

$sosed++ if IsSosed($i+1, $j) ; $sosed++ if IsSosed($i+1, $j-1) ; $sosed++ if IsSosed($i+1, $j+1) ;

$sosed++ if IsSosed($i, $j-1) ; $sosed++ if IsSosed($i, $j+1) ;

$Sos[$i][$j] = $sosed ; }; }; };

sub Pokol { for($i=0; $i<$#Pole; $i++) { for($j=0; $j4) { substr($Pole[$i], $j, 1)='.' ; next} ; if ($sosed<3) { substr($Pole[$i], $j, 1)='.' ; next} ; substr($Pole[$i], $j, 1)='x' ; }; }; };

sub ShowPole { for($i=0; $i<$#Pole; $i++) { print $Pole[$i], "\n" }; print "\n"; };

# --------------------------------------------------------- # --------------------------------------------------------- sub LoopPole { KolSosed ; Pokol ; ShowPole ; };

until ($a=~/q/i) { LoopPole ; $a = ; } ;

Зашел на форум посмотреть что нового... Нашел ответ Dmitry Zyryanov Там он говорит о модуле, который позволяет запускать внешние программы из редактора по одному нажатию кнопки. Адрес разработчтка, правда, изменился на http://belugin.newmail.ru/news1251.html а сам плугин скачивается отсюда

Супер! То что и надо было. Некотрые примечания по установке. Прежде всего распаковываем его в папку C:\Program Files\Far\plugins Дальше, в папке Types создаем файл f.ini такого содержания

#Save=True
#ToMenu=False
run=C:\SPF\spf4.exe %s

он настраивает поведение при запуске на выполнение. Дальше, делаем гарячую клавишу в редакторе для запуска на выполнения – запуcкаем файл C:\Program Files\Far\Plugins\ExtCom\F9.reg Далее, открываем в редакторе любой текст программы на Forth , с раширением *.f и жмем F9 – должно выскочить меню плугинов, в нем находим наш плугин - External Commands – и присваиваем ему гарячую клавишу – "4". Все, теперь по F9 будет запускаться выполнение текущего окан в SP-Forth

При выходе из запущенной программы, опять вернетесь к редактируемому тексту.

Слово \EOF действительно полезное при отладке. Сам часто пользовался в перлоских программах подобным – __EOF__

<<< Предыдущий Начало   Следующий >>>
Copyright © Alex Furashev 2004

При цитировании, ссылка на оригинальный текст обязательна. Допускается копирование материалов только целиком, без внесения каких-либо изменений в оригинальный текст, меняющих смысл, структуру материала и проч.

Hosted by uCoz