Code Comments
Programming Forum and web based access to our favorite programming groups.HaloO,
John M. Dlugosz wrote:
> So a function can only supply values for one dimension? Given
> @array[foo;bar]
> each function is called in list context and returns a list for one of the dimensio
ns.
> But what if you wanted a function to replace the literal subscript in:
> @array[1,2;1;3]
> @array[foo] # what does foo return to be equiv to the first line?
sub foo { return (1,2;1;3) }
The thing the spec is unclear about is what "as part of a subscript"
means. In @array[foo] the sub should see the whole context, though.
I guess the parser is producing slice context at compile time because
it sees &postcircumfix:<[ ]>. The point is that in @array[foo;bar] it
is unclear how to split the dimensions of @array into contexts for
&foo and &bar if @array is more then two-dimensional. In the case of
@array.dim == 2 &foo and &bar are in list context anyway. Actually the
shape of @array is generally unknown until runtime.
Now my question: could slice context be a runtime feature that acts
before the dispatch to &postcircumfix:<[ ]> by retrieving the shape
of the @array and handing it over to &foo as context, capture the
shape of the slice returned and hand over the remaining shape as
context to &bar? Since relying on the order of &foo and &bar in the
source is bad, an even more elaborate scheme can be used that queries
&foo and &bar before the actual call which slots they intend to fill
in the pending slice operation.
Regards, TSa.
--
The Angel of Geometry and the Devil of Algebra fight for the soul
of any mathematical being. -- Attributed to Hermann Weyl
Post Follow-up to this messageTSa Thomas.Sandlass-at-barco.com |Perl 6| wrote: > Now my question: could slice context be a runtime feature that acts > before the dispatch to &postcircumfix:<[ ]> by retrieving the shape > of the @array and handing it over to &foo as context, capture the > shape of the slice returned and hand over the remaining shape as > context to &bar? Since relying on the order of &foo and &bar in the > source is bad, an even more elaborate scheme can be used that queries > &foo and &bar before the actual call which slots they intend to fill > in the pending slice operation. The plot thickens! Consider the user-defined index translation functions, or the differential indexing feature. Both use * inside the subscript. If you have @array[$a;*-2;$c] the * has to know to map to a function to retrieve the length of the proper dimension. If it can't count semicolons at compile-time, it can't rely on parser magic and it has to call a function at run time. Forget the funny syntax, and what we're really looking at is: @array[ $a ; dimlen() - 2 ; $c ] Even if you want to be charitable and say the parser actually expanded the * to dimlen (@array) (without re-evaluating the expression if the array is not a simple variable name), then it still doesn't know what position it is in. Just off the cuff, I think it might use the array target and index position as context variables, or to save the overhead of always setting those, another magic syntax inside the subscript could be used to indicate its own position. So, the * expands to: dimlen (@array, $?SLICEPOS) and this makes it clear how to call your own functions thusly. So you could write @array[ @@(foo(42)) ; bar(@?SLICETARGET, $?SLICEPOS) ; $baz ] and it would supply the proper value after knowing how many dimensions were returned from foo in slice context. The use of @?SLICETARGET allows you to refer to the @array even if it is the result of an expression, without re-evaluating it, or worse if it is a return value or temporary object. It would be handy to have when writing a macro. Hopefully, the grammar for implementing * in subscripts is clean enough that you could write a macro that did something similar for your own construct. There should be no magic that is not available to the programmer as well. --John
Post Follow-up to this messageHmm, both of you are kinda going off on a tangent here. The meaning of the Whatever represented by * is neither something that gets magically interpreted before postcircumfix:<[ ]>, nor is it a compile-time rewrite. Context is supplied by binding in Perl 6, and the binding happens within .[]. It's the fact that the parameter within .[] is declared with @@ that causes it to bind as a slice, so that each dimension of the argument comes in as a single array element. (By the way, you'll note the utility of being able to talk about a postfix by saying .[], which is one of the reasons we allow the optional dot there. :) Now, you'll ask how *-2 works. If you do math on a Whatever object, it just remembers that offset until the Whatever is given a meaning, which, in this case, is delayed until the subscripting operator decides what the size of the next dimension is. At a lower level than the subscript it probably ends up being some kind of a fallback multi that binds to a Whatever type for that dimension, as the subscripting operator processes through each dimension in its @@ array. Or maybe it's just a case in a switch. In any case, the subscriptor knows the next "top" dimension, so it can know the size at that point. At compile time the subscript parser really only knows how many dimensions are referred to by how many semicolons there are. A subscript that is explicitly cast to @@ is known to be multidimensional, and interpolates the returned List of Capture into the outer List of Capture, and the compiler can make no compile-time assumptions about how far down the dimension list any subsequent dimensional sublists will end up. However, at least we can hope that @@ x() specifies the exact number of dimensions to interpolate at run time. One additional variant of Whatever is **, which represents an arbitrary number of dimensions. In essence, it's an instruction to the subscripting logic as it's processing top-down through the dimensions that it has to reverse its logic and count the rest of the subscripts bottom-up from the end of its @@ bound list instead of from the beginning. As such, there can really only be one such reversal, so we limit ourselves to a single ** argument representing an arbitrary number of dimensions to skip over, assuming the rest of the dimensions are end-anchored, as it were. Larry
Post Follow-up to this messageLarry Wall larry-at-wall.org |Perl 6| wrote: > Now, you'll ask how *-2 works. If you do math on a Whatever object, > it just remembers that offset until the Whatever is given a meaning, > which, in this case, is delayed until the subscripting operator > decides what the size of the next dimension is. At a lower level than > the subscript it probably ends up being some kind of a fallback > multi that binds to a Whatever type for that dimension, as the > subscripting operator processes through each dimension in its @@ array. > Or maybe it's just a case in a switch. In any case, the subscriptor > knows the next "top" dimension, so it can know the size at that point. > > I see. The *-2 isn't resolved to a number right away, but evaluates to a "whatever-2" object, that is passed. The subscripting implementation knows what is going on when it gets to that. That means that ordinary uses will not require knowledge about the dimensions and context, as it is handled all inside the subscripting code. But constructs that generate loops around that expression will have to know. This certainly includes the autoindexing thing being discussed in another thread. But I'm also thinking of junctions. Junctions thread through the subscript, it is writ. A junction, like a range, can use * for an endpoint, can it not? Writing @foo[$x;2..*;$y] >>*<< blah blah will serve up the slice first, using the mechanism described above. But the similar $n=all(2..*); @foo[$x;$n;$y] * blah blah is described as creating a loop around the * operator. I guess it would convert to the first one and see what the subscripter gave back? Is that still possible if multiple junctions are present? --John
Post Follow-up to this messageLarry Wall larry-at-wall.org |Perl 6| wrote: > At compile time the subscript parser really only knows how > many dimensions are referred to by how many semicolons there > are. A subscript that is explicitly cast to @@ is known to be > multidimensional, and interpolates the returned List of Capture into > the outer List of Capture, and the compiler can make no compile-time > assumptions about how far down the dimension list any subsequent > dimensional sublists will end up. > > What I still want to know is: When does .[] provide a single item, rather than a list (a list that might contain only one item)? $x = @array[$n]; # I expect $x holds the single result, not a list of one item! $x = @array[foo()]; # what about now? --John
Post Follow-up to this message
Show a Printable Version
Email This Page to Someone!
Receive updates to this thread
Powered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.