====================================================================
MappingPackage examples
====================================================================

Function are objects of type Mapping.  In this section we demonstrate
some library operations from the packages MappingPackage1, MappingPackage2, 
and MappingPackage3 that manipulate and create functions. Some terminology: 
a nullary function takes no arguments, a unary function takes one argument, 
and a binary function takes two arguments.

We begin by creating an example function that raises a rational number
to an integer exponent.

  power(q: FRAC INT, n: INT): FRAC INT == q**n
                      Type: Void

  power(2,3)
    8
                       Type: Fraction Integer

The twist operation transposes the arguments of a binary function.
Here rewop(a, b) is power(b, a).

  rewop := twist power
    theMap(MAPPKG3;twist;MM;5!0)
                       Type: ((Integer,Fraction Integer) -> Fraction Integer)

This is 2^3.

  rewop(3, 2)
    8
                       Type: Fraction Integer

Now we define square in terms of power.

  square: FRAC INT -> FRAC INT
                       Type: Void
The curryRight operation creates a unary function from a binary one by
providing a constant argument on the right.

  square:= curryRight(power, 2)
    theMap(MAPPKG3;curryRight;MBM;1!0,0)
                       Type: (Fraction Integer -> Fraction Integer)

Likewise, the curryLeft operation provides a constant argument on the
left.

  square 4
    16
                       Type: Fraction Integer

The constantRight operation creates (in a trivial way) a binary
function from a unary one: constantRight(f) is the function g such
that g(a,b)= f(a).

  squirrel:= constantRight(square)$MAPPKG3(FRAC INT,FRAC INT,FRAC INT)
    theMap(MAPPKG3;constantRight;MM;3!0)
              Type: ((Fraction Integer,Fraction Integer) -> Fraction Integer)

Likewise, constantLeft(f) is the function g such that g(a,b)= f(b).

  squirrel(1/2, 1/3)
    1
    -
    4
                       Type: Fraction Integer

The curry operation makes a unary function nullary.

  sixteen := curry(square, 4/1)
    theMap(MAPPKG2;curry;MAM;2!0,0)
                       Type: (() -> Fraction Integer)

  sixteen()
    16
                       Type: Fraction Integer

The * operation constructs composed functions.

  square2:=square*square
    theMap(MAPPKG3;*;MMM;6!0,0)
                       Type: (Fraction Integer -> Fraction Integer)

  square2 3
    81
                       Type: Fraction Integer

Use the ** operation to create functions that are n-fold iterations of
other functions.

  sc(x: FRAC INT): FRAC INT == x + 1
                       Type: Void

This is a list of Mapping objects.

  incfns := [sc**i for i in 0..10]
   [theMap(MAPPKG1;**;MNniM;6!0,0), theMap(MAPPKG1;**;MNniM;6!0,0),
    theMap(MAPPKG1;**;MNniM;6!0,0), theMap(MAPPKG1;**;MNniM;6!0,0),
    theMap(MAPPKG1;**;MNniM;6!0,0), theMap(MAPPKG1;**;MNniM;6!0,0),
    theMap(MAPPKG1;**;MNniM;6!0,0), theMap(MAPPKG1;**;MNniM;6!0,0),
    theMap(MAPPKG1;**;MNniM;6!0,0), theMap(MAPPKG1;**;MNniM;6!0,0),
    theMap(MAPPKG1;**;MNniM;6!0,0)]
                       Type: List (Fraction Integer -> Fraction Integer)

This is a list of applications of those functions.

  [f 4 for f in incfns]
    [4,5,6,7,8,9,10,11,12,13,14]
                       Type: List Fraction Integer

Use the recur operation for recursion:

  g := recur f means g(n,x) == f(n,f(n-1,...f(1,x))).

  times(n:NNI, i:INT):INT == n*i
                       Type: Void

  r := recur(times)
    theMap(MAPPKG1;recur;2M;7!0,0)
                       Type: ((NonNegativeInteger,Integer) -> Integer)

This is a factorial function.

  fact := curryRight(r, 1)
    theMap(MAPPKG3;curryRight;MBM;1!0,0)
                       Type: (NonNegativeInteger -> Integer)

  fact 4
    24
                       Type: PositiveInteger

Constructed functions can be used within other functions.

  mto2ton(m, n) ==
    raiser := square^n
    raiser m
                       Type: Void

This is 3^(2^3).

  mto2ton(3, 3)
    6561
                       Type: Fraction Integer

Here shiftfib is a unary function that modifies its argument.

  shiftfib(r: List INT) : INT ==
    t := r.1
    r.1 := r.2
    r.2 := r.2 + t
    t
                       Type: Void

By currying over the argument we get a function with private state.

  fibinit: List INT := [0, 1]
    [0,1]
                       Type: List Integer

  fibs := curry(shiftfib, fibinit)
    theMap(MAPPKG2;curry;MAM;2!0,0)
                       Type: (() -> Integer)

  [fibs() for i in 0..30]
   [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597,
    2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418,
    317811, 514229, 832040]
                       Type: List Integer

See Also:
o )show MappingPackage1
o )help MappingPackage2
o )help MappingPackage3
o )help MappingPackage4

