Forth и другие саморасширяющиеся системы программирования Locations of visitors to this page
Текущее время: Чт мар 28, 2024 14:31

...
Google Search
Forth-FAQ Spy Grafic

Часовой пояс: UTC + 3 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 85 ]  На страницу Пред.  1, 2, 3, 4, 5, 6  След.
Автор Сообщение
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Вт дек 18, 2012 00:07 
Не в сети
Аватара пользователя

Зарегистрирован: Вт ноя 06, 2007 21:23
Сообщения: 227
Откуда: Екатеринбург
Благодарил (а): 4 раз.
Поблагодарили: 7 раз.
WingLion писал(а):
Alexander писал(а):
Выходит , просто три прохода по одному массиву.

три прохода, это, когда три раза DO LOOP по массиву, а у меня всего лишь три сравнения на элемент и один проход.
И сравнения такие, что однозначно определяют, попадает ли элемент в нужную категорию или нет - попал -> считаем, не попал - следующее сравнение. А оптимизация сравнений - это уже другой марлезонский балет...

ага согласен. проверить бы забег на 1 , 10, 100 Мегабайтах )

Вышло даже очень удачно, все предложили свои версии задчки на том ФОРТ которым им привычно пользоваться
Пусть некоторые из нас и пишут на шифровальной машине, но всё же дать пояснения - это сложная задача.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Вт дек 18, 2012 00:23 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 13:19
Сообщения: 3565
Откуда: St.Petersburg
Благодарил (а): 4 раз.
Поблагодарили: 72 раз.
Alexander писал(а):
ага согласен. проверить бы забег на 1 , 10, 100 Мегабайтах )

мой форт загнется сразу, потому что у нрго 64 килобайта рабочее
поле
Alexander писал(а):
но всё же дать пояснения - это сложная задача

да, особенно, когда набирать их приходится одной рукой :)

_________________
С уважением, WingLion
Forth-CPU . RuF09WE
Мой Форт
Отсутствие бана это не заслуга юзера, а недоработка модератора (с)


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Вт дек 18, 2012 16:29 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 22:48
Сообщения: 7960
Благодарил (а): 25 раз.
Поблагодарили: 144 раз.
true-grue писал(а):
Только хуже, поскольку сомнительно, чтобы даже начинающий программист на Си принялся на пустом месте создавать глобальный массив Q.

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


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Вт дек 18, 2012 17:31 
Не в сети

Зарегистрирован: Пн ноя 05, 2007 13:54
Сообщения: 144
Благодарил (а): 0 раз.
Поблагодарили: 13 раз.
Простой пример. Если мы посмотрим на реализацию на Си современных интерпретаторов, то убедимся в том, что состояние интерпретатора (регистры, стеки и другие изменяемые данные) хранится не в виде набора глобальных переменных, а содержится в полях структуры. Сторонний код, запускающий интерпретатор, самостоятельно заботится о выделении памяти (на стеке, в куче и т.д.) и времени жизни соответствующего состояния. В результате, не смотря на небольшие накладные расходы, получаем большую свободу действий: можно запустить несколько копий интерпретатора одновременно, можно организовать загрузку интерпретатора из ПЗУ и т.п.

Глобальная переменная, подобно якорю, привязывает к код к текущему окружению. Областью видимости и временем жизни данных можно и нужно управлять (используя для этого удобные инструменты). Тут имеет смысл провести аналогию с функциональным программированием, где результат функции зависит лишь от аргументов, а не ее внутреннего состояния. Понятно, что эта философия несколько непрактична, и более разумным был бы подход, связанный с ограничением распространения побочного эффекта рамками взаимодействующих сущностей (процессов, объектов, акторов, систем), а на всего, так сказать, глобального вычислительного пространства.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Вт дек 18, 2012 17:49 
Не в сети

Зарегистрирован: Ср июл 05, 2006 14:44
Сообщения: 236
Благодарил (а): 0 раз.
Поблагодарили: 7 раз.
давайте попробуем разобрать вариант предложенный true-grue
немного добавил коментариев и подправил регистр букв для СПФ

Код:
CREATE arr 9 , 1 , -1 , -3 , 4 , 0 , 5 , -6 , -7 , 9 ,
: each: ( array)              ( 0 arr -- )
  R>                          ( 0 arr xt -- )
  SWAP DUP @ >R  CELL+ R>     ( 0 xt arr+ cnt -- )
  0 DO
       2DUP 2>R               ( 0 xt arr+  R: xt arr+ )
       @ SWAP EXECUTE         ( 0 n xt -- )
            2R> CELL+         ( num xt arr+ -- )
    LOOP
  2DROP ;

: negatives ( array - count) 0 SWAP each: 0<  IF 1+ THEN ;
: zeroes ( array - count)    0 SWAP each: 0=  IF 1+ THEN ;
: positives ( array - count) 0 SWAP each: 0 > IF 1+ THEN ;

: main
   CR ." Negatives=" arr negatives .
   CR ." Zeroes=" arr zeroes .
   CR ." Positives=" arr positives . ;

самое главное лексиконообразующее слово здесь each: , и так что оно делает?
зная структуру массива входых данных формирует цикл по элементам и применяет
к ним ( с помощью R> .... EXECUTE ) оставшуюся после each: часть кода до ;
остальные страшные слова 2R>, 2>R формируют необходимые параметры на стеке данных.
поэтому для работы этого слова необходимы оберточные слова ( лексикон )
negatives, zeroes , positives. Например мы не можем написать main таким образом:
Код:
: main2
   CR ." Negatives=" 0 arr each: 0<  IF 1+ THEN .
   CR ." Zeroes="    0 arr each: 0=  IF 1+ THEN .
   CR ." Positives=" 0 arr each: 0 > IF 1+ THEN . ;

если слово each: вызывают трудности для понимания, его можно переписать на свой вкус.
да простят меня коллеги, покажу как можно написать его используя стековые манипуляторы.
в начале подробный вариант с комментариями, а затем сжатый.
Код:
: each_sm: ( arr ) R> 2\ '1 @ 4 + '3 ! '1 @ @ 0 DO '3 @ @ '2 @ EXECUTE '3 @ 4 + '3 ! LOOP ;

{ ( arr ) R> 2\ } -- загружаем в ячейку 1 адрес массива arr, а в ячейку 2 адрес возврата на часть кода после each:
{ '1 @ 4 + '3 ! } -- извлекаем из ячейкм 1 адрес массива arr, добавляем CELL (4)
и сохраняем в ячейке 3 манипулятора - это адрес первого злемента массива.
{ '1 @ @ 0 DO } -- извлекаем из адреса arr число элементов массива и формируем параметры цикла DO
{ '3 @ @ '2 @ EXECUTE } -- достаем элемент массива из адреса в ячейке 3 и исполняем
код, адрес которого мы сохранили в ячейке 2
{ '3 @ 4 + '3 ! LOOP } -- увеличиваем адрес в ячейке 3 на 4 и закрываем цикл.

переписываем это как положено в стековом манипуляторе:
Код:
: each_sm: ( arr ) R> 2\1`4+'3!1@`0D3@2X3`4+'3!L ;

легко видеть, что:
{ ( arr ) R> 2\ } = { arr ) R> 2\}
{ '1 @ 4 + '3 ! } = {1`4+'3!}
{ '1 @ @ 0 DO } = {1@`0D}
{ '3 @ @ '2 @ EXECUTE } = {3@2X}
{ '3 @ 4 + '3 ! LOOP } = {3`4+'3!L}
надеюсь это поможет понять как работает each:


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Вт дек 18, 2012 17:59 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 22:48
Сообщения: 7960
Благодарил (а): 25 раз.
Поблагодарили: 144 раз.
Глобальные переменные в Си и глобальные переменные в Форте все же имеют некоторые отличия в практике использования. Что такое глобальная переменная в Си? Это прежде всего шанс получить побочные эффекты. Существенно удобнее инкапсулировать данные, заведя обертки get/set, и далее выстроив программу таким образом, что на верхнем уровне мы имеем несложные функции, "опускающиеся" до базовых get/set за 3-4-5-6-7 (и т.д.) вызовов. В итоге на промежуточных уровнях почти всегда имеется некоторое количество стековых кадров, содержащих фактические параметры. С чем, собственно, компилятор прекрасно управляется, адресуя нужный параметр с учетом его области видимости и смещения в стековом кадре. Глобальная переменная тут почти и не нужна. Почему "почти"? Ну например потому, что в глобальный массив можно положить данные, получаемые с аппаратуры. Эти данные эксклюзивны сами по себе, и свободно обращаться с вызовом refill_array() попросту не получится. А значит, и в локальные переменные, теряемые при возврате на верхний уровень, такой массив класть нельзя. Это с int x = MyWindow.Coord.GetX() такое допустимо.
В Форте же стековые кадры как таковые отсутствуют (в том смысле, что они не выделяются компилятором специально). Стек данных - это по сути "текущее операционное поле". Неоднократно звучали мнения, что при нормальном подходе работа идет с несколькими верхними числами на стеке, а если требуется что-то из глубины, значит стоит уже внимательно рассмотреть архитектуру программы на предмет недостатков. А локальная переменная, передаваемая на 2-3-4 уровня ниже, как раз и окажется глубоко. Поэтому с ней придется работать через PICK, вычисляя текущее смещение в уме. Это не так уж удобно. В этой связи глобальный массив для временного использования группой слов вполне имеет право на существование, тем более что его можно а) не именовать; б) позднее перекрыть словом с тем же именем, компилятор не обидится.
Отдельно укажу на программирование в стиле "машина состояний" aka "конечный автомат". Сравнивая API от DirectX, основанное как раз на вызовах функций с множеством параметров, и от OpenGL, где многие параметры являются глобальными, не могу не склониться в сторону последнего.
true-grue писал(а):
Понятно, что эта философия несколько непрактична, и более разумным был бы подход, связанный с ограничением распространения побочного эффекта рамками взаимодействующих сущностей (процессов, объектов, акторов, систем), а на всего, так сказать, глобального вычислительного пространства.

Вполне соглашусь. Только мне кажется, что в программах на Форте взаимодействующие сущности как-то более тесно взаимодействуют. Программы-то меньше, и не так явно выражен интерфейсный компонент, из-за которого глобальные программные объекты могут начать претендовать на уникальные имена вроде XCoord, YCoord.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Вт дек 18, 2012 18:34 
Не в сети

Зарегистрирован: Пн ноя 05, 2007 13:54
Сообщения: 144
Благодарил (а): 0 раз.
Поблагодарили: 13 раз.
Хищник писал(а):
Глобальные переменные в Си и глобальные переменные в Форте все же имеют некоторые отличия в практике использования.

Согласен. Так как разговор начался с "программиста на Си", я изложил свою точку зрения в приложении к разработке достаточно крупного ПО, написанного на этом языке. В духе того, как технология строительства небоскреба отличается от технологии строительства небольшого дачного домика, при разработке программ на Форте, особенно в его традиционной нише (embedded), возможны послабления в плане использования глобальных переменных. Но это касается того случая, когда локализация данных во времени и пространстве оборачивается какими-то серьезными неприятностями. За все приходится платить, за гибкость и расширяемость программ (а отсутствие глобального состояния необходимо для этого) -- в том числе. Иногда, разумеется, цена бывает непомерно высока.

Alex писал(а):
давайте попробуем разобрать вариант предложенный true-grue
немного добавил коментариев и подправил регистр букв для СПФ

Спасибо. А не хотите рассмотреть области применения слова each:?
Вот, например, разве не красиво? : sum ( array - sum) 0 swap each: + ;
Или взять вложенные each:. Или each!: (с перезаписью элементов). Или each над другими структурами данных.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Вт дек 18, 2012 19:33 
Не в сети

Зарегистрирован: Ср июл 05, 2006 14:44
Сообщения: 236
Благодарил (а): 0 раз.
Поблагодарили: 7 раз.
true-grue писал(а):
Вот, например, разве не красиво? : sum ( array - sum) 0 swap each: + ;
Или взять вложенные each:. Или each!: (с перезаписью элементов). Или each над другими структурами данных.


конечно красиво, : db_find ( db -- rec ) each: test_rec ;

Андрей Черезов часто использует подобную технику, можно посмотреть
в дистрибутиве SPF \devel\~ac\rationale\ARRAY.F
или вот еще ссылку, а еще же была Ваша статья, ссылку щас быстро не найду.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Вт дек 18, 2012 19:56 
Не в сети

Зарегистрирован: Пн ноя 05, 2007 13:54
Сообщения: 144
Благодарил (а): 0 раз.
Поблагодарили: 13 раз.
Тут, вообще говоря, имеют место две техники: использование функций высших порядков и использование стека возвратов для организации различных нетривиальных управляющих структур. О необходимости "легализации" последней техники уже давно говорится (http://www.complang.tuwien.ac.at/anton/ ... nko98b.pdf ). На мой вкус, неявные литералы кода в духе each: ... ; более органично реализуются в Форте, чем [: ... ;] each, например.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Вт дек 18, 2012 20:43 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 13:19
Сообщения: 3565
Откуда: St.Petersburg
Благодарил (а): 4 раз.
Поблагодарили: 72 раз.
создание нетривиальных управляющих структур, безусловно, тема интересная, вот только место ей явно не в разделе "форт для начинающих"

_________________
С уважением, WingLion
Forth-CPU . RuF09WE
Мой Форт
Отсутствие бана это не заслуга юзера, а недоработка модератора (с)


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Вт дек 18, 2012 22:09 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 22:48
Сообщения: 7960
Благодарил (а): 25 раз.
Поблагодарили: 144 раз.
А почему бы и не для начинающих? Не все же начинающие программисты, есть и программисты, начинающие работать с Фортом. Функции высших порядков - одна из вещей, которые в Форте "можно сделать, поскольку ничто не препятствует", в отличие от языков, где их нет и быть не может.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Вт дек 18, 2012 22:21 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 13:19
Сообщения: 3565
Откуда: St.Petersburg
Благодарил (а): 4 раз.
Поблагодарили: 72 раз.
тему то загромоздили щукораколебедиными спорами...

_________________
С уважением, WingLion
Forth-CPU . RuF09WE
Мой Форт
Отсутствие бана это не заслуга юзера, а недоработка модератора (с)


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Вт дек 18, 2012 22:30 
Не в сети
Moderator
Moderator

Зарегистрирован: Ср май 10, 2006 15:37
Сообщения: 1132
Откуда: Chelyabinsk ( Ural)
Благодарил (а): 0 раз.
Поблагодарили: 9 раз.
У меня такой each: из решения true-grue получился
Код:
: each: ( array)
   cell+ dup cell - @ cells   
   over + swap
   begin rot over @ r@ execute rot rot cell+ 2dup = until 2drop r> drop
;

Думваю, до begin можно и поудачнее найти решение:) (а если привязать вычисление индексов массива в режиме интерпритации,
то ещё проще, но не гибко) Мне в этом подходе понравился возможный вариант вызова кода с поздним связыванием.

И в таком варианте оно работает на SPF4 и не "канает" на Swift и VFX дальше не проверял.

P.S. Есть ещё короткое решение с циклом, но хранимые на стеке возвратов параметры цикла, похоже
не позволяют ему правильно выполниться. :( Такой прикидочный вариант
Код:
: each: ( array)
   cell+ dup cell - @ cells   
   bounds do i @ r@ execute loop r> drop
;

Стек возврата, в какой то степени можно использовать
по возможностям как стек данных (если ввести расширенный лексикон по работе с ним и как то "разрулить" ситуацию с циклами.

Alex писал(а):
Андрей Черезов часто использует подобную технику, можно посмотреть
.

Первый раз? это было ещё использовано в его событийно-классовом текстовом редакторе в SPF2.5 для ДОС

P.S.
Хищник писал(а):
А почему бы и не для начинающих? Не все же начинающие программисты, есть и программисты, начинающие работать с Фортом. Функции высших порядков - одна из вещей, которые в Форте "можно сделать, поскольку ничто не препятствует", в отличие от языков, где их нет и быть не может.

Кто бы мне бездарю, ещё объяснил что такое функции высшего порядка? (приходит "аналогия" функции высшего программерского
извращения, в "особо" тяжёлой форме :D C манипуляторами или без пока не сделаешь рабочий код "всё едино" :shuffle;


Последний раз редактировалось Kopa Вт дек 18, 2012 23:23, всего редактировалось 1 раз.

Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Вт дек 18, 2012 23:18 
Не в сети
Moderator
Moderator

Зарегистрирован: Ср май 10, 2006 15:37
Сообщения: 1132
Откуда: Chelyabinsk ( Ural)
Благодарил (а): 0 раз.
Поблагодарили: 9 раз.
WingLion писал(а):
создание нетривиальных управляющих структур, безусловно, тема интересная, вот только место ей явно не в разделе "форт для начинающих"

Встретился такой пример Форт кода. Простой или нет? и полезный или нет?
Код:
: silly-control-structures { x y -- }
  begin
  x 5 < while
    y 5 < while
      x y + 5 < while
      x 2 + to x
      y 1 + to y
      repeat
    ." hello" cr
    then
  ." hi" cr
  else
  ." hey" cr
  then
  ." ---" cr ;

1 1 silly-control-structures
." ---" cr
6 0 silly-control-structures
." ---" cr
0 6 silly-control-structures


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Учимся на примерах...
СообщениеДобавлено: Ср дек 19, 2012 08:51 
Не в сети

Зарегистрирован: Ср июл 05, 2006 14:44
Сообщения: 236
Благодарил (а): 0 раз.
Поблагодарили: 7 раз.
самое лучшее место для счетчика - вершина стека, а если там 3 счетчика:
Код:
CREATE arr 9 , 1 , -1 , -3 , 4 , 0 , 5 , -6 , -7 , 9 ,
  : 3+ ( neg zer pos n1 n2 n3 -- neg+n1 zer+n2 pos+n3 ) >R >R >R ROT R> + ROT R> + ROT R> + ;
\ : 3+ ( neg zer pos n1 n2 n3 -- neg+n1 zer+n2 pos+n3 )  6\14+25+36+ ;
  : tst ( n -- n1 n2 n3 ) DUP 0< IF DROP 1 0 0 EXIT THEN 0= IF 0 1 0 ELSE 0 0 1 THEN ;
\ : tst ( n -- n1 n2 n3 ) 1\1`0<i`1`0`0;t1Zi`0`1`0e`0`0`1t ;
  : count-0+ ( arr - neg zer pos ) DUP CELL+ SWAP @ CELLS  OVER + SWAP ?DO I @ tst 3+ CELL +LOOP ;
\ : count-0+ ( arr - neg zer pos ) 1\11@`1+`4*+1`4+DI@[tst][3+]`4N ;

: MAIN
   0 0 0 arr count-0+
   CR ." Positives="   .   
   CR ." Zeroes="      .
   CR ." Negatives="   .   ;


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 85 ]  На страницу Пред.  1, 2, 3, 4, 5, 6  След.

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7


Вы не можете начинать темы
Вы можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
phpBB сборка от FladeX // Русская поддержка phpBB