develooper Front page | perl.perl5.porters | Postings from July 2003

Re: (func()){key}?

Thread Previous | Thread Next
Michael G Schwern
July 30, 2003 23:05
Re: (func()){key}?
Message ID:
On Thu, Jul 31, 2003 at 01:30:26AM -0400, Stephen McCamant wrote:
> I think the reason the parallel you're suggesting doesn't work is that
> despite its use of square brackets, which is confusing, the (...)[...]
> operator (where the parens are mandatory, note) doesn't have anything
> to do with arrays: it's a *list* slice.

Most people don't think about the list vs array thing, and rightly so
as it rarely comes up for practical purposes.

> The (...)[...] list operator exists because "give me the 7th element"
> is an operation that makes sense on a list as well as on an array; if
> this is imposing an array structure on the list, it doesn't seem like
> much of an imposition. Your suggested (...){...} operator seems less
> sensible to me because performing a hash operation on a list is more
> of a stretch ("give me an odd-indexed member of this list such that
> the preceding element is 'foo'").

Its extremely common in Perl to think of a list into a hash.  We do it every
time we return a hash from a function.

    sub foo {
        # this is a list.
        return( foo => 42, bar => 23 );

    %hash = foo;

or here's an idiom I just used today:

    my @Localtime_Keys = qw(sec min hour mday mon year wday yday isdst);
    sub localtime {
        my $time = @_ ? shift : time;
        my @time = CORE::localtime($time);
        return map { ($Localtime_Keys[$_], $time[$_]) } @time;

> Off hand, I can't think of a syntactic problem with allowing
> (...){...} parallel to (...)[...]. I'm not sure what a good
> implementation would be, though. A list is a bunch of scalar values on
> the stack, and the indices would also turn into a list, so you'd want
> to do a list-list intersection. The asymptotically efficient way to do
> this would be to turn one of the lists into a hash table, but as you
> noted in another message, we can already do that explicitly by
> rewriting (foo){bar} as {foo}->{bar} (or @{foo}{bar} if you want a
> multi-element slice). You could do a separate linear search for each
> index, but that would have the danger of being unexpectedly slow for
> large slices.

Or we could do what we already do with lists when we turn them into a hash:
dump it into a temporary HV and then do normal hash operations on that.  
Internally it would be little different than:

    my $val  = do {  
        my %hash = foo();

That's the simplest way to do it.  Someone can optimize it later if it
turns out to be slow.

And before people start yelling about copying the list and the memory waste,
this is no different than the current idiom:

    my $val = {foo}->{key};

So we're no worse off than we are now, have a more consistent syntax and
it can only get faster from there.

We have returned to claim the pyramids.

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About