Есть два базовых понятия - "массив" и "итератор".
"Массив" - это структура данных.
"Итератор" - это императивная конструкция для перебора элементов массива.
Простейший пример:
revert - принимает в качестве параметра массив и возвращает его "перевёрнутое отображение".
Именно - ОТОБРАЖЕНИЕ, а не КОПИЮ.
Пример:
join - принимает в качестве параметров ДВА массива и возвращает их "отображение, как если бы они были склеены".
Опять же - именно ОТОБРАЖЕНИЕ, а не копию.
Пример:
Ещё пример:
И ещё пример:
removeduplicates - принимает в качестве параметра массив и возвращает его "отображение с удалёнными дубликатами".
Пример:
И ещё пример:
filter - принимает ДВА параметра - функтор и массив и возвращает "отображение массива в котором все элементы удовлетворяют значению функтора".
Пример:
Частными случаями "массивов" являются файлы.
Пример:
Ещё пример:
Возвращаемся к массивам.
sort - принимает в качестве параметров - функтор сортировки и массив и возвращает "отображение массива, сортированное в соответствии с функтором".
Пример:
Ещё пример (делает то же самое, что предыдущий, но иллюстрирует тот факт, что в функторе может быть написан "любой код", а не обязательно оператор из аксиоматики):
Свёртка массивов:
Пример:
Ещё пример:
И ещё пример (иллюстрирующий, что может быть подан ЛЮБОЙ пользовательский функтор, а не только оператор аксиоматики):
И ещё пример:
Встраивание "дополнительного функтора".
process - принимает два параметра - функтор обработки элемента массива и собственно массив.
Возвращает "отображение массива с применённым функтором".
Пример:
Ещё пример (комбинация process и revert):
Да! Забыл сказать.
Модификатор AUTO - означает, что тип выражения будет выведен "автоматически" (как auto в C++11).
Итерация по скомпилированному коду.
codearray - принимает ОДИН параметр - ссылку на скомпилированный код и возвращает его в качестве "отображения массива".
ЛЮБОЙ скомпилированный код скриптовой машины можно получить в качестве "массива".
Пример:
!!! Конструкция DO - выполняет слово, ссылка на которое ей передана.
Ещё пример (комбинация codearray и process):
- Этот пример делает то же самое, что предыдущий, но иллюстрирует возможность вынесения "дополнительного функтора" за "тело цикла".
Проиллюстируем это ещё таким примером:
!!! @ - этот оператор возвращает ссылку на слово, которое стоит ЗА ним.
Ещё пример (то же самое, но с анонимным кодом):
Приведённые конструкции в общем-то - аналог списков в Python'е.
Итерация по вложенным словам (или аналог RTTI).
membersarray - принимает один параметр - ссылку на слово и возвращает "отображение массива вложенных элементов".
Пример:
Ещё пример (комбинация membersarray и process):
Ну и пример (с функцией возвращающей массив):
А причём тут RTTI?
А вот причём:
wordname - слово принимающее ссылку на слово и возвращающее его имя.
Пример:
Ещё пример:
Да!!! Слово IN - определяет ВХОДНОЙ параметр.
А скобки - () - определяют "анонимное слово". Собственным пространством имён.
Далее про RTTI:
wordparent - получает ссылку на слово и возвращает ссылку на его родителя.
Пример:
wordproducer - получает ссылку на слово и возвращает ссылку на слово, которое его породило.
Пример:
Аналогично можно перебирать входные параметры и результирующие значения.
А также - много чего ещё.
Понятно причём тут RTTI?
Кстати map-reduce (http://ru.wikipedia.org/wiki/MapReduce) и Свёртка списка (http://ru.wikipedia.org/wiki/%D0%A1%D0%B2%D1%91%D1%80%D1%82%D0%BA%D0%B0_%D1%81%D0%BF%D0%B8%D1%81%D0%BA%D0%B0) - не из той же ли серии, что я тут всё понаписал?
Ну и напоследок:
"Пользовательский массив":
FunctorToArray - принимает один параметр - функтор итерации, возвращает "отображение массива".
Пример:
Ну да... ну да... http://habrahabr.ru/post/132554/
Цитата:
"
Модуль itertools содержит специальные функции для работы с итерируемыми объектами. Желаете продублировать генератор? Соединить два генератора последовательно? Сгруппировать значения вложенных списков в одну строчку? Применить map или zip без создания ещё одного списка?
Просто добавьте import itertools."
:-)
Как всегда - "всё придумано до нас".
----------------------------------------------------------------------
(+) http://habrahabr.ru/post/85238/
(+)
numbers = [1,2,3,4,5]
squares = [number*number for number in numbers]
-- так я тоже могу.
Вот:
numbers = [ 1 2 3 4 5 ]
squares = [ for numbers (IN anItem anItem * anItem) ]
(+) http://ninjaside.info/blog/ru/funkcii-map-i-zip-i-lambda-python/
"Массив" - это структура данных.
"Итератор" - это императивная конструкция для перебора элементов массива.
Простейший пример:
ARRAY VAR A := [ 1 2 3 4 5 ] // - Объявление массива и его инициализация FOR A WriteLn // - простейший итератор по массиву. // Принимает ДВА параметра - собственно массив и подитеративную функцию. // - в данном примере на устройство вывода будут выведены числа 1 2 3 4 5
revert - принимает в качестве параметра массив и возвращает его "перевёрнутое отображение".
Именно - ОТОБРАЖЕНИЕ, а не КОПИЮ.
Пример:
ARRAY VAR A := [ 1 2 3 4 5 ] // - Объявление массива и его инициализация FOR revert A WriteLn // - в данном примере на устройство вывода будут выведены числа 5 4 3 2 1
join - принимает в качестве параметров ДВА массива и возвращает их "отображение, как если бы они были склеены".
Опять же - именно ОТОБРАЖЕНИЕ, а не копию.
Пример:
ARRAY VAR A := [ 1 2 3 4 5 ] // - Объявление массива и его инициализация FOR join A A WriteLn // - в данном примере на устройство вывода будут выведены числа 1 2 3 4 5 1 2 3 4 5
Ещё пример:
ARRAY VAR A := [ 1 2 3 4 5 ] // - Объявление массива и его инициализация FOR join A join A A WriteLn // - в данном примере на устройство вывода будут выведены числа 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
И ещё пример:
ARRAY VAR A := [ 1 2 3 4 5 ] // - Объявление массива и его инициализация ARRAY VAR В := [ 6 7 8 9 10 ] // - Объявление массива и его инициализация FOR join A B WriteLn // - в данном примере на устройство вывода будут выведены числа 1 2 3 4 5 6 7 8 9 10
removeduplicates - принимает в качестве параметра массив и возвращает его "отображение с удалёнными дубликатами".
Пример:
ARRAY VAR A := [ 1 2 3 4 5 ] // - Объявление массива и его инициализация FOR removeduplicates join A A WriteLn // - в данном примере на устройство вывода будут выведены числа 1 2 3 4 5, // как если бы мы работали с просто A, а не с join A A
И ещё пример:
ARRAY VAR A := [ 1 2 3 4 5 ] // - Объявление массива и его инициализация ARRAY VAR В := [ 2 6 3 7 10 ] // - Объявление массива и его инициализация FOR removeduplicates join A B WriteLn // - в данном примере на устройство вывода будут выведены числа 1 2 3 4 5 6 7 10
filter - принимает ДВА параметра - функтор и массив и возвращает "отображение массива в котором все элементы удовлетворяют значению функтора".
Пример:
ARRAY VAR A := [ 1 2 3 4 5 ] // - Объявление массива и его инициализация FOR filter BOOLEAN ( IN anItem Result := anItem != 2 ) A WriteLn // - в данном примере на устройство вывода будут выведены числа 1 3 4 5
Частными случаями "массивов" являются файлы.
Пример:
FILE VAR F := OpenRead 'C:\somefile.txt' // - Объявление файла и его инициализация FOR chars F Write // - в данном примере на устройство вывода будет выведено содержимое файла посимвольно
Ещё пример:
FILE VAR F := OpenRead 'C:\somefile.txt' // - Объявление файла и его инициализация FOR lines F WriteLn // - в данном примере на устройство вывода будет выведено содержимое файла построчно
Возвращаемся к массивам.
sort - принимает в качестве параметров - функтор сортировки и массив и возвращает "отображение массива, сортированное в соответствии с функтором".
Пример:
ARRAY VAR A := [ 1 3 4 2 5 ] // - Объявление массива и его инициализация FOR sort < A WriteLn // - в данном примере на устройство вывода будут выведены числа 1 2 3 4 5
Ещё пример (делает то же самое, что предыдущий, но иллюстрирует тот факт, что в функторе может быть написан "любой код", а не обязательно оператор из аксиоматики):
ARRAY VAR A := [ 1 3 4 2 5 ] // - Объявление массива и его инициализация FOR sort BOOLEAN ( IN anItem1 IN anItem2 Result := anItem1 < anItem2 ) A WriteLn // - в данном примере на устройство вывода будут выведены числа 1 2 3 4 5
Свёртка массивов:
Пример:
ARRAY VAR A := [ 1 2 3 4 5 ] // - Объявление массива и его инициализация INTEGER VAR X := ( 0 FOR A + ) // - в переменной X будет значение 0 + 1 + 2 + 3 + 4 + 5
Ещё пример:
ARRAY VAR A := [ 1 2 3 4 5 ] // - Объявление массива и его инициализация INTEGER VAR X := ( 1 FOR A * ) // - в переменной X будет значение 1 * 1 * 2 * 3 * 4 * 5
И ещё пример (иллюстрирующий, что может быть подан ЛЮБОЙ пользовательский функтор, а не только оператор аксиоматики):
ARRAY VAR A := [ 1 2 3 4 5 ] // - Объявление массива и его инициализация INTEGER VAR X := ( 0 FOR A AUTO ( IN anItem1 IN anItem2 Result := anItem1 + anItem2 ) ) // - в переменной X будет значение 0 + 1 + 2 + 3 + 4 + 5
И ещё пример:
ARRAY VAR A := [ 1 2 3 4 5 ] // - Объявление массива и его инициализация INTEGER VAR X := ( 0 FOR A AUTO ( IN anItem1 IN anItem2 Result := anItem1 + anItem2 + 10 ) ) // - в переменной X будет значение 0 + 1 + 10 + 2 + 10 + 3 + 10 + 4 + 10 + 5 + 10
Встраивание "дополнительного функтора".
process - принимает два параметра - функтор обработки элемента массива и собственно массив.
Возвращает "отображение массива с применённым функтором".
Пример:
ARRAY VAR A := [ 1 2 3 4 5 ] // - Объявление массива и его инициализация FOR process AUTO ( IN anItem Result := anItem + 10 ) A WriteLn // - в данном примере на устройство вывода будут выведены числа 11 12 13 14 15
Ещё пример (комбинация process и revert):
ARRAY VAR A := [ 1 2 3 4 5 ] // - Объявление массива и его инициализация FOR revert process AUTO ( IN anItem Result := anItem + 10 ) A WriteLn // - в данном примере на устройство вывода будут выведены числа 15 14 13 12 11
Да! Забыл сказать.
Модификатор AUTO - означает, что тип выражения будет выведен "автоматически" (как auto в C++11).
Итерация по скомпилированному коду.
codearray - принимает ОДИН параметр - ссылку на скомпилированный код и возвращает его в качестве "отображения массива".
ЛЮБОЙ скомпилированный код скриптовой машины можно получить в качестве "массива".
Пример:
PROCEDURE P1 ( 1 + 2 ) ( 3 + 4 ) ( 5 + 6 ) ; // - эта процедура содержит ТРИ атомарных выражения - 1 + 2, 3 + 4, 5 + 6 // Проитерируем эти выражения: FOR codearray @ P1 ( IN anItem anItem DO WriteLn ) // - в приведённом примере будут выведены числа 1 + 2 3 + 4 5 + 6
!!! Конструкция DO - выполняет слово, ссылка на которое ей передана.
Ещё пример (комбинация codearray и process):
PROCEDURE P1 ( 1 + 2 ) ( 3 + 4 ) ( 5 + 6 ) ; // - эта процедура содержит ТРИ атомарных выражения - 1 + 2, 3 + 4, 5 + 6 // Проитерируем эти выражения: FOR process ( IN anItem anItem DO ) codearray @ P1 WriteLn // - в приведённом примере будут выведены числа 1 + 2 3 + 4 5 + 6
- Этот пример делает то же самое, что предыдущий, но иллюстрирует возможность вынесения "дополнительного функтора" за "тело цикла".
Проиллюстируем это ещё таким примером:
ARRAY FUNCTION A // - функция, возвращающая массив PROCEDURE P1 // - P1 - это вложенная процедура в функцию A и явно она нигде не вызывается, // используется только ССЫЛКА на неё (ниже) ( 1 + 2 ) ( 3 + 4 ) ( 5 + 6 ) ; Result := process ( IN anItem anItem DO ) codearray @ P1 ; // A FOR A WriteLn // - в приведённом примере будут выведены числа 1 + 2 3 + 4 5 + 6 // Делается, всё то же самое, что и в предыдущем примере, // только массив получаем как результат работы функции A
!!! @ - этот оператор возвращает ссылку на слово, которое стоит ЗА ним.
Ещё пример (то же самое, но с анонимным кодом):
ARRAY FUNCTION A // - функция, возвращающая массив Result := process ( IN anItem anItem DO ) codearray @ ( ( 1 + 2 ) ( 3 + 4 ) ( 5 + 6 ) ) ; // A FOR A WriteLn // - в приведённом примере будут выведены числа 1 + 2 3 + 4 5 + 6 // Делается, всё то же самое, что и в предыдущем примере, // только массив получаем как результат работы функции A, // которая в свою очередь возвращает его // как "отображение кода анонимной функции"
Приведённые конструкции в общем-то - аналог списков в Python'е.
Итерация по вложенным словам (или аналог RTTI).
membersarray - принимает один параметр - ссылку на слово и возвращает "отображение массива вложенных элементов".
Пример:
PROCEDURE P1 PROCEDURE P1.1 1 + 2 ; // P1.1 PROCEDURE P1.2 3 + 4 ; // P1.2 PROCEDURE P1.3 5 + 6 ; // P1.3 ; // P1 FOR membersarray @ P1 ( IN anItem anItem DO WriteLn ) // - в приведённом примере будут выведены числа 1 + 2 3 + 4 5 + 6
Ещё пример (комбинация membersarray и process):
PROCEDURE P1 PROCEDURE P1.1 1 + 2 ; // P1.1 PROCEDURE P1.2 3 + 4 ; // P1.2 PROCEDURE P1.3 5 + 6 ; // P1.3 ; // P1 FOR process ( IN anItem anItem DO ) membersarray @ P1 WriteLn // - в приведённом примере будут выведены числа 1 + 2 3 + 4 5 + 6
Ну и пример (с функцией возвращающей массив):
ARRAY FUNCTION A PROCEDURE P1 PROCEDURE P1.1 1 + 2 ; // P.1. PROCEDURE P1.2 3 + 4 ; // P1.2 PROCEDURE P1.3 5 + 6 ; // P1.3 ; // P1 Result := process ( IN anItem anItem DO ) membersarray @ P1 ; FOR A WriteLn // - в приведённом примере будут выведены числа 1 + 2 3 + 4 5 + 6
А причём тут RTTI?
А вот причём:
wordname - слово принимающее ссылку на слово и возвращающее его имя.
Пример:
PROCEDURE P1 PROCEDURE P1.1 1 + 2 ; // P1.1 PROCEDURE P1.2 3 + 4 ; // P1.2 PROCEDURE P1.3 5 + 6 ; // P1.3 ; // P1 FOR membersarray @ P1 ( IN anItem wordname anItem WriteLn ) // - в приведённом примере будут выведены строки P1.1 P1.2 P1.3
Ещё пример:
PROCEDURE P1 PROCEDURE P1.1 1 + 2 ; // P1.1 PROCEDURE P1.2 3 + 4 ; // P1.2 PROCEDURE P1.3 5 + 6 ; // P1.3 ; // P1 FOR process ( IN anItem wordname anItem ) membersarray @ P1 WriteLn // - в приведённом примере будут выведены строки P1.1 P1.2 P1.3
Да!!! Слово IN - определяет ВХОДНОЙ параметр.
А скобки - () - определяют "анонимное слово". Собственным пространством имён.
Далее про RTTI:
wordparent - получает ссылку на слово и возвращает ссылку на его родителя.
Пример:
PROCEDURE P1 PROCEDURE P1.1 1 + 2 ; // P1.1 PROCEDURE P1.2 3 + 4 ; // P1.2 PROCEDURE P1.3 5 + 6 ; // P1.3 ; // P1 FOR process ( IN anItem wordname wordparent anItem ) membersarray @ P1 WriteLn // - в приведённом примере будут выведены строки P1 P1 P1
wordproducer - получает ссылку на слово и возвращает ссылку на слово, которое его породило.
Пример:
PROCEDURE P1 PROCEDURE P1.1 1 + 2 ; // P1.1 PROCEDURE P1.2 3 + 4 ; // P1.2 PROCEDURE P1.3 5 + 6 ; // P1.3 ; // P1 FOR process ( IN anItem wordname wordproducer anItem ) membersarray @ P1 WriteLn // - в приведённом примере будут выведены строки PROCEDURE PROCEDURE PROCEDURE
Аналогично можно перебирать входные параметры и результирующие значения.
А также - много чего ещё.
Понятно причём тут RTTI?
Кстати map-reduce (http://ru.wikipedia.org/wiki/MapReduce) и Свёртка списка (http://ru.wikipedia.org/wiki/%D0%A1%D0%B2%D1%91%D1%80%D1%82%D0%BA%D0%B0_%D1%81%D0%BF%D0%B8%D1%81%D0%BA%D0%B0) - не из той же ли серии, что я тут всё понаписал?
Ну и напоследок:
"Пользовательский массив":
FunctorToArray - принимает один параметр - функтор итерации, возвращает "отображение массива".
Пример:
ARRAY FUNCTION A Result := FunctorToArray ( FOR [ 1 2 3 4 5 6 7] YIELD ) ; FOR A WriteLn // - будут напечатаны числа 1 2 3 4 5 6 7
Ну да... ну да... http://habrahabr.ru/post/132554/
Цитата:
"
Ваш лучший друг Itertools
Модуль itertools содержит специальные функции для работы с итерируемыми объектами. Желаете продублировать генератор? Соединить два генератора последовательно? Сгруппировать значения вложенных списков в одну строчку? Применить map или zip без создания ещё одного списка?
Просто добавьте import itertools."
:-)
Как всегда - "всё придумано до нас".
----------------------------------------------------------------------
(+) http://habrahabr.ru/post/85238/
(+)
numbers = [1,2,3,4,5]
squares = [number*number for number in numbers]
-- так я тоже могу.
Вот:
numbers = [ 1 2 3 4 5 ]
squares = [ for numbers (IN anItem anItem * anItem) ]
(+) http://ninjaside.info/blog/ru/funkcii-map-i-zip-i-lambda-python/
map (* 2) [1.. 5]
ОтветитьУдалитьаналогичное отображение возможно?
Вообще - не очень понятно, зачем всё это нужно. Зачем наворачивать скрипт, когда можно сделать функцию на delphi. Чисто спортивный интерес, или это на практике используется?
FOR process ( IN anItem Result := anItem * 2 ) [ 1 2 3 4 5 ] WriteLn
Удалитьесли я правильно всё понимаю
конечно - не чисто спортивный, на "чисто спорт" - у меня нет времени
должно получиться "отображение, как если бы элементы списка были удвоены". Консольный вывод не нужен, только отображение [Int] -> [Int]
УдалитьА подумать?
УдалитьARRAY VAR B = process ( IN anItem Result := anItem * 2 ) [ 1 2 3 4 5 ]
- отображение
ARRAY VAR B = [ FOR process ( IN anItem Result := anItem * 2 ) [ 1 2 3 4 5 ] ( IN anItem anItem ) ]
- копия
пожалуй надо будет process в map переименовать
Удалить