2012-04-30

unifying generators with function literals? [revised]

4.17: adda/syntax/
unifying generators with function literals?:
(this is a revision of 3.11)

4.18, 4.19: revision#2:
. the generator syntax should be more consistent:
what comes after the power operator should be the power,
and then the body should be a function of that power .
. the way we are unifying generators with function literals
is that the only difference in their syntax
is the appearance of the power operator .

power of a unary operator:
f^(3)(x) = f f f x
power of a binary operator:
(x ^ 3 ) implicitely means x*^3 = *(x, x, x)
power of a list for a binary operator:
* (^(x:1..3).int: x ) = 1 * 2 * 3 = *(1,2,3)
--( same as an operator applied to a
list generated with a power of a parenthetical ).
. generally, (^(x.inType).outType: f(x) )
is saying:
(for x in inType: include f(x)
which is an element of outType );
eg,
(^(x.symbol).list:
 for terminal in f(s):
    s in grammar? be terminal else be '(s)
) -- (be x) means
(return from enclosing expression with x)
so that is saying:
for s in symbol: for terminal in f(s):
if s in grammar then the list includes terminal
else it includes '(s), a list containing s .

. a function is implicitly describing a set of points,
and sets can be generated:
( f(x:1..3).int: x+1 ) is equivalent to
f = { (1, 2), (2,3), (3,4) } is equivalent to
f = {^(x.{1..3}).(int,int): (x, x+1) } .

a parenthetical declared to return a certain type:
(.int: ...) -- has type int .
. this ( f(x.int).t: x+1 ) can also be expressed as:
f: ((x.int).t: x+1) -- has a function type .

4.17: revision#1:
f^(3)(x) = f f f x -- power of a unary operator;
* (^ i:1..3  ) = 1 * 2 * 3 --. power of a binary operator
= *(1,2,3) --( same as an operator applied to a
list generated with a power of a parenthetical ).
. generally, (^x.t) is saying: (for x in t: include x);
and there are several ways to further define and refine
what is included in the list:
# (^x.t; f(x)) -- (for x in t: include f(x)).
# (^x.t | predicate(f(x)))
-- (for x in t: if predicate(f(x)) is true then include f(x)).
# (^x.t | even(x); x`*2; x`+3 | x~=13)
-- for x in t and x is even:
 (x`= x*2; x`= x+3; if x is not 13 then include x).
. another way to apply the power operation to binary operators
is like the exponent does it:
(x ^ 3 ) implicitely means x*^3 = *(x, x, x) .
. these examples have shown the various ways in which
the power operator is a list generator .
. the list generating syntax needs to be
unified with the function literal,
so how are they alike?

. a function is implicitly describing a set of points,
and sets can be generated:
( f(x:1..3).t: x+1 ) is equivalent to
f = { (1, 2), (2,3), (3,4) } is equivalent to
f = {^(x.{1..3}, y.int) | y= (x+1) }
-- for (x,y) in (1..3, int): if y=x+1 then include (x,y);
. but do we want our function literal to be so verbose?

. the power operator would be simpler to understand
if we didn't have special cases for it;
but this syntax is very similar:
{^ (x.{1..3}).int: x+1 }
-- for x in 1..3: include (x, x+1).
. this syntax differs by clarifying that this is
not just any mapping: it's a functional one;
and instead of using the filtering operator (|)
that expects a boolean expression to follow,
we use the colon to indicate that what follows is
the function's definition .

4.18:
. when we define a function literal,
we don't have to quote it because
the fact that the expression depends on a parameter
that is not yet supplied
implies that it can't be reduced at the time it's eval'd,
so it's already virtually quoted .
. but what if it's a function with all defaults?
a function is not evaled until an argument is apply'd;
ie, f(x) is an abbreviation for ('f apply x).

. we can declare parentheticals to have a particular type
similar to the way the power operator
is applied to a parenthetical:
(.int: ...) -- a parenthetical declared to return an int .
. this serves as a declare block, a type converter,
and can be the basis for defining function literals with
explicit parameters; eg:
( f(x.int).t: x+1 ) can also be expressed as:
f: ((x.int).t: x+1) .

. how would adda's list do something equivalent to
this python expression
where there are nested for-loops?:
[terminal
for s in symbols
  for terminal in f(s)
    if s in grammar else [s]]
. something like this:
(^x.list : for s in symbol: for terminal in f(s):
         s in grammar? x`= terminal else x`= '(s)
) --. a list can be either a sublist or an element .