http://www.perlmonks.org?node_id=424770


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

The purpose of an lvalue sub is to return an lvalue.

Replies are listed 'Best First'.
Re^4: Experimenting with Lvalue Subs
by theorbtwo (Prior) on Jan 25, 2005 at 02:18 UTC

    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).

      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

        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.

      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        

Re^4: Experimenting with Lvalue Subs
by BrowserUk (Patriarch) on Jan 25, 2005 at 02:15 UTC

    Which by the testimony of this thread will be as near useless and unuseable in P6 as they are in p5.


    Examine what is said, not who speaks.
    Silence betokens consent.
    Love the truth but pardon error.
      Then the testimony of this thread is simply wrong. By explicit design, lvalue subs in Perl 6 will be just as usable as variables, which the testimony of this thread does not seem to understand are useful in many more places than just on one side of an = or the other. It's only the writing of lvalue subs that you're carping about, and that will definitely be easier in Perl 6 than in Perl 5. I see no new data here to warrant reopening the case.

        Then, with respect, I think that you and I are reading different threads.

        And that maybe you have missed all the discussion around the use of lvalue subs for accessors and mutators over the past 2 1/2 years. Literally every time the subject has come up, their use has been nearly universally rejected because of the absence of the ability to validate the assignment, without the resort to hookey, repetative and slow tieing of the underlying lvalue that is assigned. Every time.

        Even with the slightly streamlines syntax outlined in Apo6, it is still forcing the programmer to code additional and complicated code for every attribute of every class. Extra work in what will be the common case for--as best as I can tell--the purpose of avoiding it in the particular and less common case.

        For me, that renders the one feature of P6 that, aboe all others, I was looking forward to, almost useless. Better to stick with the current:

        sub getset { my self = shift; return $self->{thing} unless @_; die "Bad value" unless $_[0] =~ /valid/; $self->{thing} = $_[0]; }

        It's easier to code. Easier to read. Easier to debug. And probably quicker.

        I'll refrain from passing further comments on P6 related matters, because I think I just joined that band of people who will probably never use P6.


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