четверг, 26 октября 2017 г.

Haskell vs мои скрипты. Count & Map

Integer def List:Count
  List in aList
 aList Match (
  List:[]
   0
  ( List:Make: _ Tail )
   ( 1 + Tail call.me )
 ) // aList Match
; // List:Count

// что тут делать с "длинной рекурсией"
// - пока не очень понятно,
// возможно стоит сделать Count
// "хранимым членом"

Тогда так:

Integer def List:Count
  List in aList
 aList Match (
  List:[]
   0
  ( List:Make: _ Tail Count )
   (
    If ( Count .IsValid ) then
     Count
    Else
     ( 1 + Tail call.me )
   )
 ) // aList Match
; // List:Count

List def List:Map
  List in aList
  Lambda in aLambda
 aList Match (
  List:[]
   List:[]
  ( List:Make: Head Tail )
   List:Make:
     ^@( Head aLambda do )
     ^@( Tail aLambda call.me )
 ) // aList Match
; // List:Map

Ну и вызов:

List:Make 1 List:Make 2 List:Make 3 List:Make 4 List:Make 5 List:[]
 // строим список [ 1 2 3 4 5 ]
IsOdd
 // отбираем нечётные
List:Map
( ToString + ' ' )
 // тут приводим к строке и добавляем пробел
List:Map
List:For:
 // перебирается список
Print
 // печатаем каждый элемент

Напечатано:
1 3 5

Ну и вызов:

List:Make 1 List:Make 2 List:Make 3 List:Make 4 List:Make 5 List:[]
 // строим список [ 1 2 3 4 5 ]
IsOdd
 // отбираем нечётные
List:Map
List:Count
Print
 // печатаем List:Count

Напечатано:
3

Пока выглядит вроде некузяво.

Но у меня же скрипты изначально императивные. И ОПЗ (обратная польская запись).

Но идею я вроде понял. Там строится граф/дерево разбора выражений в узлах которого записывается либо значение, либо ссылка на функцию (возможно со связанными параметрами, и не факт, что со всеми).

Если это значение, то выражение - вычислено полностью.

Если ссылка на функцию, то вычислено не полностью.

Тут и проявляется "ленивость".

Когда в узле вычисляется функция, то в узел записывается результат вычисления вместо ссылки на функцию.

Тут проявляется кеширование результатов. Ранее вычисленные функции - больше не вычисляются. А представляются значениями записанными в узлах графа/дерева.

Ну и код на Haskell:

xs = 1 : map (*2) xs

Выглядит так:

List def xs
 List:Make:
  1
  ( call.me ( 2 * ) List:Map )
; // List:Map

Я честно скажу - не проверял, но должно сработать.

Завтра проверю.

Бесконечной рекурсии там точно не будет.

При вызове xs.

Она сконструирует список:
 1 : reference to expression ( xs ( 2 * ) List:Map )

А вот применится ли  Map к правильному значению - вопрос пока открыт.

Возможно Map будет применяться не к xs, а к 1 ВСЕГДА.

Тут вопрос пока открыт. Надо проверить.

Возможно надо написать так:

List def xs
 List:Make:
  1
  ( Result ( 2 * ) List:Map )
; // List:Map

Есть и такой вариант. И он (как мне кажется) - ближе к истине.

Ибо call.me - это ссылка на функцю, а Result - это уже вычисленное значение.

Тонкая грань.

Или так:

List def xs
  List VAR myResult
 List:Make:
  1
  ( myResult ( 2 * ) List:Map )
 >>> myResult
 myResult
; // List:Map)

Хотя и это можно скрыть за "синтаксическим сахаром".

Комментариев нет:

Отправить комментарий