develooper Front page | perl.perl6.language.objects | Postings from January 2001

Somewhat related to returning tied arrays/hashes from subs

From:
Branden
Date:
January 26, 2001 05:35
Subject:
Somewhat related to returning tied arrays/hashes from subs
Message ID:
OE46vtYtSGCYrRqGk8300002818@hotmail.com
Hi.

[ I don't know if this was discussed in a thread of this or other list, or
even in a RFC. I looked for it, but I didn't find it. However, it could have
been discussed. In this case, please tell me where to find it. ]

I have some questions about the new behaviour of returning tied
arrays/hashes from subs in perl6. In perl5, what I want could be done with
typeglobs, however it's very ugly. Example:

    sub whatever {
        my @r;
        tie @r, 'MyTiedArray', @_;
        return \@r;    # return a ref (???)
    }

    my *x = whatever;    # assign to a glob (???)
    # now use it as an array: @x
    print join(', ', @x), "\n";
    my $y = $x[3] + $x[4];
    # use tied to call a method to the MyTiedArray object
    tied(@x)->any_method_of_my_tied_array($y);



It's ugly, but it works. As perl6 won't have typeglobs, this will be
changed. Perhaps perl6 could improve its syntax by allowing to write

    sub whatever {
        my @r;
        tie @r, 'MyTiedArray', @_;
        return @r;    # return the array itself
    }

    my @x = whatever;    # assign to an array
    print join(', ', @x), "\n";
    my $y = $x[3] + $x[4];
    # use the array to call a method to the MyTiedArray object
    @x->any_method_of_my_tied_array($y);



Differences:
* return the array instead of a reference (it's the array you are assigning
to, why not return an array?)
* assign to an array instead of a glob (it's the array you are using, why
not assign to it instead of a meaningless glob?)
* call the method in the array (this isn't hard. perl5 makes no use of
@xyz->abc, so adding it to the perl6 syntax to behave like tied(@xyz)->abc
won't hurt.)

The problem I see is that returning a list from a sub traditionally copies
all its elements to the stack and then assigns it by popping them off the
stack (at least it's how I _think_ it's done). This would break the
behaviour of

    ($a, $b, @c) = whatever();

since ($a, $b, @c) cannot be a tied object obviously, the copying process
must be done.

I have two solutions for this problem. One is attach an attribute to the sub
indicating it returns a tied object and it *MUST* be assigned to an object
that will actually be tied to the object instead of assigned to. The other
one is make this the default behaviour of array assignment and make it copy
the list when the assignment is in the form (@a) = @b or @a = (@b), that
actually forces the copying by providing the ( ) operator, which is the one
that actually makes the copying.

The main application I see for this behaviour is implementing XML's DOM's
classes  NodeList  and  NamedNodeMap  . These classes are implemented today
as scalars, but they are inherently plural, so using an array for the former
and a hash for the latter would be much more natural. Calling methods
through the @xyz->abc instead of having to use tied(@xyz)->abc would be
necessary to actually hide the implementation details for the user of the
classes. push's and pop's could even be tied to implicitly call insertNode
and removeNode (or whatever) to guarantee the perfect array behaviour
(that's really not hard, can be done the same way in perl5, what's
problematic with perl5 is the actual syntax of having to mix references,
typeglobs, and the tied function for every method call!)

Thanks a lot, Branden.




nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About