Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re^4: Experimenting with Lvalue Subs

by theorbtwo (Prior)
on Jan 25, 2005 at 02:18 UTC ( [id://424773]=note: print w/replies, xml ) Need Help??


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

Really? I always thought the purpose of an lvalue sub is to let $x->location='over there'; Just Work.

That's what the user wants, that's what the API designer wants. The rest, nobody wants to see except for the languge theorist. While their needs are sometimes interesting, they shouldn't get in the way of the users and the API designers.


Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).

Replies are listed 'Best First'.
Re^5: Experimenting with Lvalue Subs
by TimToady (Parson) on Jan 25, 2005 at 03:31 UTC
    Would you also like:
    $x->location++;
    to Just Work? How 'bout:
    my_increment($x->location);
    presuming that the argument is declared rw. And what about:
    $ref = \$x->location; $$ref++;
    and such?

    You've got yer blinders on if you think that's all just "language theory".

    Though it's kind of nice to be accused of being a language theorist for a change. Usually I'm accused of sacrificing theory on the altar of practicality.

      It seems to me that you are viewing :lvalues as a C programmer would, something that behaves as a piece of memory. Wheras most people here are viewing lvalues as a VB or Java programmer would: disguised method calls. Maybe the solution is to provide both? I sure would like to have a way for

      $obj->method=$foo;
      be the same as
      $obj->method($foo);

      It would be nice if Perl automagically made

      $obj->method++;

      be the same as

      $obj->method($obj->method()+1);

      But it wouldn't bother me too much if it didn't.

      The point here is that folk would be happy to forgo some of the more extreme uses of :lvalue subs like you and ysth post if they could just easily write validation code for the simpler cases. And we'd really like to do it in Perl 5. :-)

      UPDATE: This was discussed in the CB and there seemed to be some agreement that there is room for the souped up, can do anything :lvalue as well as a more constrained :assignable version that has much simpler semantics. In fact it seems to me that the :assignable version could probably be implemented with :lvalue and better callbacks once Perl 6 is around tested and stable.

      ---
      demerphq

        I sure would like to have a way for $obj->method=$foo; be the same as $obj->method($foo);

        Oh ... that just looks horrible. You're creating a syntax that has side-effects that aren't obvious from reading the code. Then again, the entire lvalue thing is ... it's just plain stupid, in my opinion. Function calls that, depending on if they're being assigned to, will behave one way or another. And, frankly, unless you bring a lot of outside knowledge to the table, you don't know which ones can do it and which ones can't.

        lvalue subs work in Javascript because Javascript is built to treat methods and attributes identically - it's a slot-based OO language like Self. And, I still have problems with the entire concept. It assumes that I, the programmer, don't need to know what is data and what is behavior. I may not want to know it at times, but I would certainly like to be able to know it, if I want to see the difference.

        Perl5 is not like Self. Perl5 is like C. Perl6 may be more like Self, in which case lvalue subs will be built into the language and they will work and they will work just fine. I have complete faith in Larry, Damian, et al that they will not screw this up. But, C does not have lvalue functions. C++ doesn't have lvalue functions.

        You know what - lvalue mutators just seem wrong to me. What's the client doing screwing around inside the object's internals? That's what lvalue mutators mean you to do ...

        Being right, does not endow the right to be rude; politeness costs nothing.
        Being unknowing, is not the same as being stupid.
        Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
        Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

      If any of those take the value of the attribute outside it's defined range, then no, I don't want it to "Just work". I want it to "Just NOT work".


      Examine what is said, not who speaks.
      Silence betokens consent.
      Love the truth but pardon error.

        If any of those take the value of the attribute outside it's defined range, then no, I don't want it to "Just work". I want it to "Just NOT work".

        Most of the time, this isn't needed. A normal variable $foo can have any value and I don't understand why instance variables should be different in this.

        Still, because value validation is a nice thing to have, tie with a STORE handler isn't a bad idea. But this shouldn't be specific to OO - the solution should apply to all variables. Our implementation, however, cheats by ignoring normal variables. This was easier :)

        sub foo : Property { $_ < 10 } main->foo = 9; main->foo++; # dies

        Perl 6 will provide a real solution, with a nice syntax even! In fact, more than one nice syntax!

        has $foo where { $_ < 10 };
        This extends to non-instance variables too. Just use "our" or "my" instead of "has".
        my $foo where { $_ < 10 }; $foo = 9; $foo++; # dies

        Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re^5: Experimenting with Lvalue Subs
by Aristotle (Chancellor) on Jan 25, 2005 at 03:09 UTC

    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.

      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.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (5)
As of 2024-04-19 15:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found