Hmmm...  David,  you seem to have covered all the issues with that rather 
lucid screed [attached at bottom].  I have a couple of dragon-nits to pick, 
one involving infrastructure and one involving syntax.  

First: it seems strange to me to add yet another property ("but 
used_to_be_scalar") to the output of the LoL semicolon, when there's a 
perfectly good distinction still floating around (the one that is 
deliberately blurred between [1] and 1).  Using the scalarness of a LoL 
element has the potential to make some really esoteric but useful things very 
easy to do, since it's a general syntax that could be used for any LoL, not 
just for slicing.  

But then, there may be good reasons (not obvious to me) to use a property.

Second: Regardless of the LoL infrastructure, we seem to be adopting opposing 
viewpoints on whether scalar-ish element in the LoL should be a scalar by 
default, with a syntactic hook to denote it as a list-of-1; or whether it 
should be a list-of-1 by default, with a syntactic hook to denote it as a 
scalar.  There are good reasons why either case will surprise a nontrivial 
subset of people.  Maybe we can sidestep the issue by making use of list 
context as you pointed out. 

Hmmm... What about replacing '*' entirely, with the yadda-yadda-yadda?
Certainly '0...' ought to enumerate (lazily) everything from 0 to infinity,
so it ought to return everything.  But then why not make term-'...' into 
an abbreviation for '0...'?  That sort of keeps the conceptual crud down
while letting everything get written straightforwardly:

How about this scenario?:

Ground rules: list expressions slice; scalar expressions index; 

Basic cases:
  [5    ;  0..6]    # scalar exps are scalar by default (index)
  [(5)  ;  0..6]    # 5 is now in list context (slice)
  [1..1 ;  0..6]    # '..' returns a list of 1 element (slice)
  [0... ;  0..6]    # '0...' is a valid lazy list, if ugly (whole axis)
  [...  ;  0..6]    # '...' acts like '0...' (whole axis)
  [*    ;  0..6]    # OK, have it your way - '*' is a synonym for '0...'.

Cases that return nothing: (either an empty list or undef...)
  [     ; 0..6]     # An empty list yields nothing 
  [undef; 0..6]     # undefined value yields nothing 
  [1..0;  0..6]     # '..' gives list of no elements; you get nothing
 
Forcing syntax:
  [+(5) ; 0..6]     # unary '+' forces scalar context (index always)
  [(5)  ; 0..6]     # List-context parens force list context (slice always)
  [5*   ; 0..6]     # postfix-* forces a slice? (no conflicts?)

Not accepted syntax:
  [*5   ; 0..6]     # does something strange -- tries to index with a glob.
 
The only reason to gripe about that (for me) is that surrounding parens change
sense compared to perl5/PDL slicing -- but that seems trivial compared to 
hammering out something that's convenient for everyone and still makes some 
sort of coherent sense.

 
Quoth David Green on Wednesday 12 January 2005 05:40 am,
> OK, so at issue is the difference between an element of an array ($p5[1])
> and a slice (that might contain only one element, @p5[1]), only
> generalised to n dimensions.  (A problem which didn't exist in P5 because
> there were no higher dimensions!)
>
> And we don't want @B[4; 0..6] to reduce to a 1-D 6-array because then
> dimensions would just be disappearing into some other...dimension.
> (To lose one dimension is a misfortune, to lose two is plane careless....)
> On the other hand, nobody wants to have to write @B[gone(4)] every time
> you need an array element.
>
> Given $a=42 and @a=(42), what if @X[$a] returned a scalar and @[EMAIL 
> PROTECTED]
> returned a slice?  Similarly, @X[$a; 0..6] would return a 6-array, and
> @[EMAIL PROTECTED]; 0..6] a 1x6-array -- scalar subscripts drop a given 
> dimension and
> array subscripts keep it.  (I think this is almost what Craig was
> suggesting, only without giving up ! for factorial. =))
>
> The list-of-lists semicolon can still turn the 42 into [42], so that if
> you have a list-of-listy function that doesn't care whether you started
> with scalars or not, it doesn't have to know.  But really the LoL
> semicolon would turn 42 into C<[42] but used_to_be_scalar>, so that
> something that *does* care (e.g. subscripting an array) can simply check
> for that property.
>
> Using a scalar to get a scalar feels rather appropriate, and not too
> surprising, I think.  Most people would probably expect @X[$a] to return
> a scalar, and use @[EMAIL PROTECTED] to mean a slice (if @a happened to have 
> only a
> single element, you're still probably using an array subscript to get
> possibly many elements -- otherwise why would you be using an array @a
> instead of just a plain scalar in the first place?)
>
> Plus if you do want to force an array subscript instead of a scalar, or
> vice versa, you don't need any new keywords to do it: @[EMAIL PROTECTED]; 
> 0..6] or
> @X[[42]; 0..6] (which is the same as @X[list 42; 0..6], right?  Which
> could also be written @X[*42; 0..6], which is kind of nice, because [*42]
> means "give me the 42nd slice" while [*] means "give me an unspecified
> slice, a slice of everything".)
>
>
> Anyway, delving right into the can of wyrms, in P5 there were list,
> scalar, and void contexts (1-D, 0-D, and... uh... -1-D?), but now that we
> have real multidimensional arrays, we could have infinite contexts (ouch).
> Well, there must be some nice way to generalise that, but it raises a
> bunch of questions.  (I can imagine "table context" being reasonably
> popular.)
>
> Various functions in P5 left the dimension of their arg untouched (take a
> list, return a list), or dropped it down one (take a list, return a
> scalar).  (Taking a scalar and returning a list is less common, but I can
> imagine a 2-D version of 'split' that turns a string into a table....)
>
> So in p6, should 'shift'ing an n-D array return a scalar or an array of
> n-1 dimensions?  It depends on whether you see it as a way to criss-cross
> through an array one element at a time, or as a way to take one 'layer'
> off something.  Both would be useful.
>
> 'grep' could return a list (1-D) of all matching individual elements, but
> perhaps more usefully it could preserve dimensionality:
>     my @board is shape(8;8);
>     #match alternating squares:
>     @checkerboard=grep { ($_.index[0] + $_.index[1])%2 } @board;
>
> ...to end up with a ragged 2-D array containing only the usable half of
> our checkerboard.  (I'm assuming we have something like .index to get the
> x, y co-ords of an element?)
>
> 'reverse' would presumably flip around the indices in all dimensions.  Ah,
> the fun of coming up with new multidimensional variations on all the old
> (or new) favourites!
>
>
>              - David "a head-scratcher no matter how you slice it" Green

Reply via email to