*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 .