Re: Unexpected behaviour with @foo.elems
You're assuming he's using an instance of the built-in Array class. I would think one reason for implementing your own class that "does Positional" is to do something out of the ordinary. So what exactly does Positional promise? I think it should be as general as possible, and avoid thinking of Array implicitly. Jon Lang dataweaver-at-gmail.com |Perl 6| wrote: Jonathan Scott Duff wrote: Or perhaps for 0...@foo.end -> $k { ... } @foo.keys may not be what the user wanted if @foo is a sparse array. IIRC, you have to explicitly ask for the custom index in order to get "sparse array" keys. By design, the normal index is never sparse; only the custom index. That said, a case could be made that the "custom index" rules as currently presented are too restrictive to implement sparse arrays. In particular, the fact that you must map the custom index to the standard index when the array is first created, and that you are not permitted to adjust things later on, kills much of the power inherent in sparse arrays. To implement a sparse array, I'd recommend using hashes. In particular, allow hashes that have sortable keys to be able to access them "by number" as well as "by name" - E.g.: my %x = { 'b' => 2, 'c' => 3 } say %x[0]; # same as say %x %x = 1; say %x[0]; #same as say %x
Re: Unexpected behaviour with @foo.elems
Jonathan Scott Duff wrote: > Or perhaps > > for 0...@foo.end -> $k { ... } > > @foo.keys may not be what the user wanted if @foo is a sparse array. IIRC, you have to explicitly ask for the custom index in order to get "sparse array" keys. By design, the normal index is never sparse; only the custom index. That said, a case could be made that the "custom index" rules as currently presented are too restrictive to implement sparse arrays. In particular, the fact that you must map the custom index to the standard index when the array is first created, and that you are not permitted to adjust things later on, kills much of the power inherent in sparse arrays. To implement a sparse array, I'd recommend using hashes. In particular, allow hashes that have sortable keys to be able to access them "by number" as well as "by name" - E.g.: my %x = { 'b' => 2, 'c' => 3 } say %x[0]; # same as say %x %x = 1; say %x[0]; #same as say %x -- Jonathan "Dataweaver" Lang
Re: Unexpected behaviour with @foo.elems
> Is it still a global in Perl 6? It's not even global in perl5.10. perldoc says: As of release 5 of Perl, assignment to $[ is treated as a compiler directive, and cannot influence the behavior of any other file. (That's why you can only assign compile-time constants to it.) Its use is highly discouraged. Note that, unlike other compile-time directives (such as strict), assignment to $[ can be seen from outer lexical scopes in the same file. However, you can use local() on it to strictly bind its value to a lexical block. perl6's S28 "Special Names [DRAFT]" says under "Perl5 to Perl6 special variable translation": $[ - This feature has been removed
Re: Unexpected behaviour with @foo.elems
On Tue, May 26, 2009 at 9:03 PM, Patrick R. Michaud wrote: > On Tue, May 26, 2009 at 06:43:40PM -0500, John M. Dlugosz wrote: > > Daniel Carrera daniel.carrera-at-theingots.org |Perl 6| wrote: > >> The following construction doesn't do what a user might expect: > >> > >> for 0...@foo.elems -> $k { do_something($k,@foo[$k]) } > > > > Write ^...@foo.elems as a shortcut of 0...@foo.elems, which is the > > variation to exclude that endpoint if you would rather not write > > 0...@foo.elems-1. > > An even cleaner shortcut might be to use ^...@foo instead of ^...@foo.elems: > >for ^...@foo -> $k { do_something($k, @foo[$k]) } > > Somewhat clearer could be: > >for @foo.keys -> $k { do_something($k, @foo[$k]) } > > And some may prefer: > >for @foo.kv -> $k, $v { do_something($k, $v) } > > I think the anti-pattern of "0...@foo.elems" (or its incorrect > form "0...@foo.elems") should probably disappear in favor of > the above forms instead. Or perhaps for 0...@foo.end -> $k { ... } @foo.keys may not be what the user wanted if @foo is a sparse array. -Scott -- Jonathan Scott Duff perlpi...@gmail.com
Re: Unexpected behaviour with @foo.elems
On Wed, May 27, 2009 at 7:05 AM, John Macdonald wrote: > On Tue, May 26, 2009 at 04:38:21PM -0700, yary wrote: >> perl4-perl5.8 or so had a variable that let you change the starting >> index for arrays, so you could actually make the above work. But then >> everyone who'd re-arranged their brains to start counting at 0, and >> written code that has a starting index of 0, would have problems. > > That was $[ and it goes back to perl 1 or so. I recall > experimenting with it a couple of times. Using it, though, > means that you have to use $[ as the lower range limit for > *every* array everywhere. Is it still a global in Perl 6? I've noticed a trend toward using less expansive scopes, so that setting $[ to 1 might mean that arrays that are defined in the current scope are 1-based instead of 0-based, whereas arrays defined in other scopes (such as inside a function imported from a module) might continue to be 0-based. > That gets stale very quickly, and I then decided that I would > just never change the setting of $[ and would remove such a > change from any code that I called. ...which is probably the cleanest way to handle it. It's for a similar reason that postcircumfix:<[ ]> always uses $[-based consecutive integers for indexing: you always have a consistent way of referring to, e.g., "the first element" (@x[0]) or "the last element" (@x[*-1]), without having to worry about which indexing scheme any particular array might be using. That's also the reason for custom indexing: if you _want_ to use 1-based indexing for a given array, you can always define a custom index and then refer to the first element by saying "@x{1}'. -- Jonathan "Dataweaver" Lang
Re: Unexpected behaviour with @foo.elems
On Tue, May 26, 2009 at 04:38:21PM -0700, yary wrote: > perl4-perl5.8 or so had a variable that let you change the starting > index for arrays, so you could actually make the above work. But then > everyone who'd re-arranged their brains to start counting at 0, and > written code that has a starting index of 0, would have problems. That was $[ and it goes back to perl 1 or so. I recall experimenting with it a couple of times. Using it, though, means that you have to use $[ as the lower range limit for *every* array everywhere. That gets stale very quickly, and I then decided that I would just never change the setting of $[ and would remove such a change from any code that I called. This single global value for the initial index of all arrays was one of the things that lead to the greater understanding that "action at a distance" is hazardous to your sanity as a code maintainer.
Re: Unexpected behaviour with @foo.elems
I don't see how you could interpret the name "elems" as something returning "index of the last element". If your IRC interlocutor confused @foo.elems with $#foo, then it seems more likely that they were confused about the semantics of $#foo than of .elems , whose p5 equivalent is just scalar(@foo). Of course, arrays itemify to references in p6, but they still numify to their length, so +...@foo is a synonym for @foo.elems, and I suspect it will be the more common form. Namewise, @foo.elems isn't obviously distinct enough from @foo.values, IMO, whereas numeric context is unambiguous. Anyway, this feels like the common confusion of natural numbers vs offsets. P6 mitigates that confusion somewhat by providing ^N as a shortcut for the commonly-needed 0..N-1 range, and I don't think that idiom should be eschewed by the doc. Yes, @foo.keys and @foo.kv are better in the particular case of looping over a single array's indices, but ^ and .elems can be useful together, too. Consider the case of processing unequal-length arrays in parallel: for ^max(@foo.elems,@bar.elems) On 5/27/09, Daniel Carrera wrote: > Patrick R. Michaud wrote: >> An even cleaner shortcut might be to use ^...@foo instead of ^...@foo.elems: >> >> for ^...@foo -> $k { do_something($k, @foo[$k]) } >> >> Somewhat clearer could be: >> >> for @foo.keys -> $k { do_something($k, @foo[$k]) } >> >> And some may prefer: >> >> for @foo.kv -> $k, $v { do_something($k, $v) } >> >> I think the anti-pattern of "0...@foo.elems" (or its incorrect >> form "0...@foo.elems") should probably disappear in favor of >> the above forms instead. > > Even if there is no language change, at least it'd be good to ensure > that "0...@foo.elems" doesn't appear in the documentation. Instead, > whoever writes the docs should use @foo.keys and @foo.kv. Those are > *very* clear, and they do the right thing. > > Daniel. > -- Sent from my mobile device Mark J. Reed
Re: Unexpected behaviour with @foo.elems
Patrick R. Michaud wrote: An even cleaner shortcut might be to use ^...@foo instead of ^...@foo.elems: for ^...@foo -> $k { do_something($k, @foo[$k]) } Somewhat clearer could be: for @foo.keys -> $k { do_something($k, @foo[$k]) } And some may prefer: for @foo.kv -> $k, $v { do_something($k, $v) } I think the anti-pattern of "0...@foo.elems" (or its incorrect form "0...@foo.elems") should probably disappear in favor of the above forms instead. Even if there is no language change, at least it'd be good to ensure that "0...@foo.elems" doesn't appear in the documentation. Instead, whoever writes the docs should use @foo.keys and @foo.kv. Those are *very* clear, and they do the right thing. Daniel.
Re: Unexpected behaviour with @foo.elems
yary wrote: I'm a relative beginner at perl6, but pretty good with perl5 (and C and a few others), so I read "for 0...@foo.elems" as saying "Give me a list with one item longer then @foo", not "give me the indexes of @foo". But a Perl non-beginner did make that mistake. The problem is that it looks a lot like the Perl 5 "for my $k (0..$#foo)". Anyways, I am not suggesting a change. I am pointing out a possible confusion and letting the experts decide what to do. for @foo.values -> $k { do_something($k,@foo[$k]) } try @foo.keys instead! Yeah... I noticed after I hit send. Changing the meaning of "elems" to mean anything other then the number of elements seems likely to cause even more confusion! I did not say "let's change the meaning of 'elems'". I was very careful to suggest nothing. I simply raised a point of confusion and I can prove that it is a point of confusion because someone who does know about Perl 6 got confused. But what to do about it is something I leave to the experts. Daniel.
Re: Unexpected behaviour with @foo.elems
On Tue, May 26, 2009 at 06:43:40PM -0500, John M. Dlugosz wrote: > Daniel Carrera daniel.carrera-at-theingots.org |Perl 6| wrote: >> The following construction doesn't do what a user might expect: >> >> for 0...@foo.elems -> $k { do_something($k,@foo[$k]) } > > Write ^...@foo.elems as a shortcut of 0...@foo.elems, which is the > variation to exclude that endpoint if you would rather not write > 0...@foo.elems-1. An even cleaner shortcut might be to use ^...@foo instead of ^...@foo.elems: for ^...@foo -> $k { do_something($k, @foo[$k]) } Somewhat clearer could be: for @foo.keys -> $k { do_something($k, @foo[$k]) } And some may prefer: for @foo.kv -> $k, $v { do_something($k, $v) } I think the anti-pattern of "0...@foo.elems" (or its incorrect form "0...@foo.elems") should probably disappear in favor of the above forms instead. Pm
Re: Unexpected behaviour with @foo.elems
Daniel Carrera daniel.carrera-at-theingots.org |Perl 6| wrote: Hello, The following construction doesn't do what a user might expect: for 0...@foo.elems -> $k { do_something($k,@foo[$k]) } Obviously, the intention is to step through every key/value in @foo. Buf @f...@foo.elems] does not exist. If @foo = (1,2,3); then @foo.elems is 3, and @foo[3] is undefined. Yes, I know that you could also have written: for @foo.values -> $k { do_something($k,@foo[$k]) } But I point out that the earlier code sample was given to me on IRC at #perl6. If one of the current developers can make that mistake, other users will too. I cannot say whether it makes sense to alter the language because of this. You are the language experts. I just wanted to raise a likely point of confusion among users. Cheers, Daniel. Write ^...@foo.elems as a shortcut of 0...@foo.elems, which is the variation to exclude that endpoint if you would rather not write 0...@foo.elems-1. --John
Re: Unexpected behaviour with @foo.elems
I'm a relative beginner at perl6, but pretty good with perl5 (and C and a few others), so I read "for 0...@foo.elems" as saying "Give me a list with one item longer then @foo", not "give me the indexes of @foo". I can see users being tripped up by the old problem of "we start counting at 0 and not at 1", which is more at the root of what you're seeing. If perl6 started at 1 then you'd write for 1...@foo.elems -> $k { do_something($k,@foo[$k]) } # wrong in this universe for 0..(@foo.elems-1) -> $k { do_something($k,@foo[$k]) } # works perl4-perl5.8 or so had a variable that let you change the starting index for arrays, so you could actually make the above work. But then everyone who'd re-arranged their brains to start counting at 0, and written code that has a starting index of 0, would have problems. >for @foo.values -> $k { do_something($k,@foo[$k]) } try @foo.keys instead! > But I point out that the earlier code sample was given to me on IRC at > #perl6. If one of the current developers can make that mistake, other users > will too. I cannot say whether it makes sense to alter the language because > of this. Changing the meaning of "elems" to mean anything other then the number of elements seems likely to cause even more confusion! I seem to recall one of the synopses discussing the replacement for p5s "$#foo" to get the last index of foo, but I don't remember where.