понедельник, 3 августа 2015 г.

ToDo. Write about arrays, lists and iterators

Original in Russian: http://programmingmindstream.blogspot.ru/2014/01/todo_24.html

"Array" and "iterator" are the two basic concepts.

"Array" is the data structure.
"Iterator" is the imperative construct for iteration of array items.

A simple example:
ARRAY VAR A := [ 1 2 3 4 5 ]
// - Array specification and initialization
FOR A WriteLn
// - simple array iterator.
//   Has TWO parameters - the array and the function under iteration.
// - in this example the numbers 1 2 3 4 5 will be displayed

revert - takes array as a parameter and returns its “reverse display”.

I mean the DISPLAY, not a COPY.

Example:
ARRAY VAR A := [ 1 2 3 4 5 ]
// - Array specification and initialization
FOR revert A WriteLn
// - in this example the numbers 5 4 3 2 1 will be displayed

join - takes two arrays as a parameters and returns their “display as if they were merged”.

Remember - the DISPLAY, not a COPY.

Example:
ARRAY VAR A := [ 1 2 3 4 5 ]
// - Array specification and initialization
FOR join A A WriteLn
// - in this example the numbers 1 2 3 4 5 1 2 3 4 5 will be displayed

One more example:
ARRAY VAR A := [ 1 2 3 4 5 ]
// - Array specification and initialization
FOR join A join A A WriteLn
// - in this example the numbers 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 will be displayed

Another example:
ARRAY VAR A := [ 1 2 3 4 5 ]
// - Array specification and initialization
ARRAY VAR В := [ 6 7 8 9 10 ]
// - Array specification and initialization
FOR join A B WriteLn
// - in this example the numbers 1 2 3 4 5 6 7 8 9 10 will be displayed

removeduplicates - takes an array as a parameter and returns its “display with remote duplicates”.

Example:
ARRAY VAR A := [ 1 2 3 4 5 ]
// - Array specification and initialization
FOR removeduplicates join A A WriteLn
// - in this example the numbers 1 2 3 4 5 will be displayed, 
//   as if we work with A only and not with join A A

One more example:
ARRAY VAR A := [ 1 2 3 4 5 ]
// - Array specification and initialization
ARRAY VAR В := [ 2 6 3 7 10 ]
// - Array specification and initialization
FOR removeduplicates join A B WriteLn
// - in this example the numbers 1 2 3 4 5 6 7 10 will be displayed

filter - takes TWO parameters - functor and array and returns “array display with elements that match the functor value”.

Example:
ARRAY VAR A := [ 1 2 3 4 5 ]
// - Array specification and initialization
FOR filter BOOLEAN ( IN anItem Result := anItem != 2 ) A WriteLn
// - in this example the numbers 1 3 4 5 will be displayed

Files is a specific instance of “arrays”.

Example:
FILE VAR F := OpenRead 'C:\somefile.txt'
// - File specification and initialization
FOR chars F Write
// - in this example the file content will be displayed by symbols

One more example:
FILE VAR F := OpenRead 'C:\somefile.txt'
// - File specification and initialization
FOR lines F WriteLn
// - in this example the file content will be displayed by symbols

Let’s get back to arrays.
sort - takes sorting functor and array as parameters and returns “display of array sorted by functor”.

Example:
ARRAY VAR A := [ 1 3 4 2 5 ]
// - Array specification and initialization
FOR sort < A WriteLn
// - in this example the numbers 1 2 3 4 5 will be displayed

Another example (the purpose is the same but it also illustrates that “any code” can be written in functor and not only the axiomatic operator):
ARRAY VAR A := [ 1 3 4 2 5 ]
// - Array specification and initialization
FOR sort BOOLEAN ( IN anItem1 IN anItem2 Result := anItem1 < anItem2 ) A WriteLn
// - in this example the numbers 1 2 3 4 5 will be displayed

Arrays folding:

Example:
ARRAY VAR A := [ 1 2 3 4 5 ]
// - Array specification and initialization
INTEGER VAR X := ( 0 FOR A + )
// - the X variable will have the value 0 + 1 + 2 + 3 + 4 + 5

Another example:
ARRAY VAR A := [ 1 2 3 4 5 ]
// - Array specification and initialization
INTEGER VAR X := ( 1 FOR A * )
// - the X variable will have the value 1 * 1 * 2 * 3 * 4 * 5

One more example (illustrates the fact that not only axiomatic operator but ANY user functor can be given):
ARRAY VAR A := [ 1 2 3 4 5 ]
// - Array specification and initialization
INTEGER VAR X := ( 0 FOR A AUTO ( IN anItem1 IN anItem2 Result := anItem1 + anItem2 ) )
// - the X variable will have the value 0 + 1 + 2 + 3 + 4 + 5

Another example:
ARRAY VAR A := [ 1 2 3 4 5 ]
// - Array specification and initialization
INTEGER VAR X := ( 0 FOR A AUTO ( IN anItem1 IN anItem2 Result := anItem1 + anItem2 + 10 ) )
// - the X variable will have the value 0 + 1 + 10 + 2 + 10 + 3 + 10 + 4 + 10 + 5 + 10

Additional inline functor.

process - takes two parameters - functor for processing of array item and the array.

It returns “display of array with applied functor”.

Example:
ARRAY VAR A := [ 1 2 3 4 5 ]
// - Array specification and initialization
FOR process AUTO ( IN anItem Result := anItem + 10 ) A WriteLn
// - in this example the numbers 11 12 13 14 15 will be displayed

One more example (combination of process and revert):
ARRAY VAR A := [ 1 2 3 4 5 ]
// - Array specification and initialization
FOR revert process AUTO ( IN anItem Result := anItem + 10 ) A WriteLn
// - in this example the numbers 15 14 13 12 11 will be displayed

Oh! I forgot something.

The AUTO modifier means that the type of expression will be displayed “automatically” (similarly to auto in C++11).

Iteration of the compiled code.

codearray - takes ONE parameter, a link to the compiled code and returns it as an “array display”.

ANY compiled code of the script engine we get as an “array”.

Example:
PROCEDURE P1
 ( 1 + 2 )
 ( 3 + 4 )
 ( 5 + 6 )
;
// - the procedure contains THREE atomic expressions - 1 + 2, 3 + 4, 5 + 6
//   Let’s iterate the expressions:
 
FOR codearray @ P1 ( IN anItem anItem DO WriteLn )
// - in this example the numbers 1 + 2 3 + 4 5 + 6 will be displayed

!!! The DO construct executes the word according to the link given.

Another example (combination of codearray and process):
PROCEDURE P1
 ( 1 + 2 )
 ( 3 + 4 )
 ( 5 + 6 )
;
// - the procedure contains THREE atomic expressions - 1 + 2, 3 + 4, 5 + 6
//   Let’s iterate the expressions:
 
FOR process ( IN anItem anItem DO ) codearray @ P1 WriteLn
// - in this example the numbers 1 + 2 3 + 4 5 + 6 will be displayed

- The purpose of this example is similar to the previous one, plus it illustrates the possibility to eliminate the “additional functor” of the “cycle body”.

Let’s illustrate it with the example:
ARRAY FUNCTION A
// - function that returns an array
 
 PROCEDURE P1
 // - P1 - is a procedure nested in the A function and it is not called explicitly anywhere, 
 //   only the LINK to it is used (below)
  ( 1 + 2 )
  ( 3 + 4 )
  ( 5 + 6 )
 ;
 
 Result := process ( IN anItem anItem DO ) codearray @ P1
; // A
 
FOR A WriteLn
// - in this example the numbers 1 + 2 3 + 4 5 + 6 will be displayed
//   All is same to the previous example, 
//   but the array is a result of the A function execution


The !!! @ operator returns a link to the word behind it.

One more example (like anonymous code):
ARRAY FUNCTION A
// - function that returns an array
 
 Result := process ( IN anItem anItem DO ) codearray @ ( 
  ( 1 + 2 )
  ( 3 + 4 )
  ( 5 + 6 )
 )
; // A
 
FOR A WriteLn
// - in this example the numbers 1 + 2 3 + 4 5 + 6 will be displayed
//   All is same to the previous example, but the array 
//   is a result of the A function execution 
//   that in its turn returns the array as a “display of the code 
//   of the anonymous function

In general, the constructs given are the analogue of the lists in Python.

Iteration of inline words (or analogue of RTTI).

membersarray - takes one parameter - a link to the word and returns “link to the array of inline items”.

Example:
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 )
// - in this example the numbers 1 + 2 3 + 4 5 + 6 will be displayed

Anoter example (combination of membersarray and 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
// - in this example the numbers 1 + 2 3 + 4 5 + 6 will be displayed

Here is an example (with the function that returns an array):
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
// - in this example the lines 1 + 2 3 + 4 5 + 6 will be displayed

Why RTTI?

We need it because:

wordname is a word taking a link to the word and returning its name.

Example:
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 )
// - in this example the lines P1.1 P1.2 P1.3 will be displayed

Another example:
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
// - in this example the numbers P1.1 P1.2 P1.3 will be given

Oh!!! Word IN defines the INPUT parameter.

The brackets () define the “anonymous word” by the own name space.

More about RTTI:

wordparent - takes a link to the word and returns it to the parent.

Example:
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
// - in this example the lines P1 P1 P1 will be displayed

wordproducer - takes a link to the word and returns it to the word that created it.

Example:
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
// - in this example the lines PROCEDURE PROCEDURE PROCEDURE will be displayed

Similarly, we can iterate the input parameters and result values.

There are many more tricks.

Now you see why we need RTTI?

By the way - map-reduce (https://en.wikipedia.org/wiki/MapReduce) and Fold (https://en.wikipedia.org/wiki/Fold_(higher-order_function)) are related to what I described here, are not they?

For the final:

"User array":

FunctorToArray - takes one parameter - iteration functor and returns “display of array”.

Example:
ARRAY FUNCTION A
 Result := FunctorToArray ( FOR [ 1 2 3 4 5 6 7] YIELD )
;
 
FOR A WriteLn
// - the numbers 1 2 3 4 5 6 7 will be printed

Well... well... http://habrahabr.ru/post/132554/ (in Russian)

I quote:
"Your best friend Itertools

Unit itertools has special functions for iterated objects. Do you need to duplicate the iterator? Or combine two generators in sequence? Or group the values of inline lists in one line? Apply map or zip and do not create one more list?

Just add import itertools."

:-)

As always - "thinking about us".
----------------------------------------------------------------------

(+) http://habrahabr.ru/post/85238/ (in Russian)

(+)
numbers = [1,2,3,4,5]
squares = [number*number for number in numbers]

-- I can do that too.

Have a look:
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/ (in Russian)

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

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