Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re^5: Experimenting with Lvalue Subs

by Aristotle (Chancellor)
on Jan 25, 2005 at 03:09 UTC ( #424777=note: print w/ replies, xml ) Need Help??


in reply to Re^4: Experimenting with Lvalue Subs
in thread Experimenting with Lvalue Subs

How do you want to make

local $foo->bar = 'baz';

work, then? BrowserUk and I are struggling with that elsewhere in the thread, too.

Larry is right, if you do anything else than return an lvalue from the sub, then this is not really possible. As I said in the other subthread, I suppose validation could be handled inline anyway, but there really is no getting around the fact that an lvalue sub must return an lvalue if you want to support dynamically scoped assignments.

Makeshifts last the longest.


Comment on Re^5: Experimenting with Lvalue Subs
Download Code
Re^6: Experimenting with Lvalue Subs (trade-offs)
by tye (Cardinal) on Jan 25, 2005 at 04:24 UTC

    I'd prefer not supporting applying local to :lvalue subs over requiring them to return an lvalue.

    Requiring that a second routine be written in order to even look at the rvalue is ugly. But even uglier is forcing all such 'set this' operations to create an lvalue.

    Consider an object that interfaces to some 'thing' outside the process.

    99% of the time, when someone writes $obj->Prop= $value; they won't be using local with it. But the design requires that even in those 99% of cases, the 'set' method must not only create a dummy variable, but it must query the external 'thing' to initialize this dummy lvalue just in case local is being used.

    I'd like to be able to write lvalue-only methods. And I'd like to write 'set' methods that don't directly store their rvalue argument(s) anywhere.

    I like the blurring of methods and member variables, so I don't mind that someone might try to use my lvalue-only method in a non-assignment scenario. I'd just throw an exception for such. So $obj->Prop= $value; can return $value even if $obj has no way to query the external 'thing' to ask it what its Prop currently is. So writing $value= $obj->Prop; can throw an exception.

    So I think local should produce code nearly identical to:

    my $temp= $obj->Prop; $obj= $newValue; ... $obj->Prop= $temp;

    and support local well w/o forcing the "return an lvalue" design which has preventing from ever want to use :lvalue in Perl5 and sounds like it will do that same for me in Perl6.

    - tye        

      Other problems:

      How would this work in the proposed scheme?

      sub double { $_[0] *= 2; } double($o->foo);

      Also currently

      $o->foo+ *= 2;
      calls foo() once whereas it would need to call twice in the proposed scheme.

        Yes, for the rare cases, it increases the number of calls. For the common cases, it can reduce the number of calls and complexity.

        But this brings me back to my original suggestion, which was to leave :lvalue alone and provide :sassign (s=scalar) and :aassign (a=array since both 'list' and 'left' start with 'l') alternatives that make the easy stuff easy (and faster) but may not support the rare stuff (and, obviously, wouldn't support flipping between scalar and list contexts at run time).

        Though you could still support general lvalue emulation for :sassign. For example, when an :sassign is used in an lvalue context other than a simple assignment (and perhaps a few other optimized cases), create a single closure that basicly curries the 'get' part of the method call and give this closure magic which means that assignments to it call it with the value to be assigned as the only parameter.1

        So authors can choose to write 'set' routines in one piece instead of two while allowing their users to use assignment statements while Perl can automatically create a light-weight 'tied' closure only if the user uses the lvalue in a more complicated fashion.

        But those who prefer to write 'set' methods in two pieces can optimize for the complex cases using :lvalue.

        - tye        

        1 I don't know if such makes sense for :aassign cases in Perl6 (it wouldn't in Perl5 because lists get flattened and supporting flattening of :aassign looks like a mine field to me).

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://424777]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (6)
As of 2014-11-27 18:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (186 votes), past polls