[Nickle]Array comprehension syntax

Bart Massey nickle@nickle.org
Sun, 04 Aug 2002 23:34:03 -0700


My principal syntactic objection are that both the formal
and result types of the comprehension func, together with
the fact that it's a func and its arity, are already known.
Thus, the explicit func() is inappropriate: the
comprehension should just take formal names and an
expression, like the Smalltalk block construct.

Perhaps something like
  int[10,10] a = { =(i,j) i * j ... };
is not too bad?  Note that this syntax might also allow
things like
  int[10] a = { =(i) i + 1, =(i) i + 2, =(j) j * j ... };
although I can't for the life of me figure out how this
would be useful :-).

Note also that if you want a lambda for structure it's not a
big deal to have one:
  int[11] a = { =(i)
    int func(int j) {
       if (j < 5)
           return j;
       return 10 - j;
    } (i) ... };
although arguably better here is
  int[11] a = { =(i) ({ if (i < 5) return i; return 10 - i; }) ... };
and arguably better still is
  int triangle(int n, int i) {
     int b = n // 2;
     if (i < b)
         return i;
     return 2 * b - i;
  }
  int[11] a = { =(i) triangle(11, i) ... };
although in all these examples it is troubling that changing
the size of a will not automatically work, so maybe
  int[11] a = { =(i) triangle(dim(a), i) ... };
works, although I don't think a is scoped in yet in the
initializer :-) so probably not.  Sigh.
  
The other classic approach is to not let the user name the
formals, but instead pre-supply names: something like
  int[11] a = { = triangle($#, $1) ... };
or perhaps something less ugly.

	Bart

In message <E17bBub-00017c-00@localhost> you wrote:
> 
> Array comprehensions are lambdas evaluated to initialize an array; they're 
> passed the index of the desired element and compute that element.  
> Essentially, they're a shorthand notation for:
> 
>     int[*,*]	a = [2, 2];
> 
>     for (int i = 0; i < 2; i++)
> 	for (int j = 0; j < 2; j++)
> 	    a[i,j] = lambda (i,j);
> 
> I've got the underlying code all built for compiling and executing these,
> but I'm a bit stuck on the syntax.  My current (lame) syntax looks like:
> 
>     int[*,*]	a = [2, 2] { = int func (int i, int j) { return i*j; } };
> 
> Actually, any expression which evaluates to a function can be used inside
> the initializer:
> 
>     int c (int i, int j) { return i * j; }
>     
>     int[*,*]	a = [2, 2] { = c };
> 
> I'm really not excited about this syntax and am looking for suggestions.
> However, even with this weak syntax, compose looks a lot nicer:
> 
>     poly (poly...) compose (poly f, poly g) {
>         return poly func (poly args...) {
>             poly(int) pick(int start) {
>                 return func (int i) { return args[start+i]; };
>             }
>             return f (g ((poly[func_args(g)]) { = pick(0) } ...),
>                       (poly[func_args(f)-1]) { = pick(func_args(g)) }...);
>         };
>     }
> 
> The only problem is that the arguments 'f' and 'g' aren't statically
> typechecked to accept only functions.  We don't have any syntax for
> a function which takes an arbitrary number of arguments, all we have
> is syntax for a function which takes a variable number of arguments;
> the problem is that:
> 
> 	poly(poly...) a = poly func (poly g) { return g; }
> 
> is currently a type error (Incompatible types 'poly(poly ...)', 'poly(g)')
> 
> We need a formal spec for our current type system...
> 
> -keith
> 
> 
> 
> _______________________________________________
> Nickle mailing list
> Nickle@nickle.org
> http://nickle.org/mailman/listinfo/nickle