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)
Хотя и это можно скрыть за "синтаксическим сахаром".
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:
// перебирается список
// печатаем каждый элемент
Напечатано:
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
// печатаем 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)
Хотя и это можно скрыть за "синтаксическим сахаром".
Комментариев нет:
Отправить комментарий