Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re: can sub check context for lvalue vs rvalue context?

by LanX (Saint)
on May 08, 2018 at 23:11 UTC ( [id://1214238]=note: print w/replies, xml ) Need Help??


in reply to can sub check context for lvalue vs rvalue context?

I don't think so, that's why you are not recommended to use lvalue methods as combined getter and setters.

It initially works but if you ever need to do validation on the setter you are lost.

use strict; use warnings; package Test; my $test; sub test :lvalue { return $test; } package main; Test->test =5; print Test->test; #> 5

Though there was a costly workaround by returning a tied value (from TheDamian IIRC) which catches the STORE.

update

Well, if you are willing to install XS, you could use Devel::Callsite to find and parse the OP-Tree.

Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
Wikisyntax for the Monastery

Replies are listed 'Best First'.
Re^2: can sub check context for lvalue vs rvalue context?
by perl-diddler (Chaplain) on May 09, 2018 at 03:12 UTC
    Yeah, returning a tied value is what I was grudgingly working on, as I didn't think it would be very efficient.

    I was hoping I could return a non-tied value for rvalue context as 'reading' a var is often a more frequent operation than 'writing' to it.

    I've used lvalues for many functions, where I don't need to check the value, but do want assignments to structures to be checked for valid member names. I use structures more often than objects, which is why I shook my head at the discouragement against lvalue accessor subs.

    Of course if you want to do something contingent on value change...then it seems perl only offers a tied-type solution.

    It's too bad a "wantlvalue" keyword wasn't introduced with lvalue subs -- it would have been at least as useful as 'wantarray'. Imagine all the dual-use functions that return different values based on scalar or array context that would not be do-able w/o knowing return context. It seems that's an equivalent case to knowing whether or not the return context is lvalue or not.

      Of course if you want to do something contingent on value change...then it seems perl only offers a tied-type solution.

      The documentation Lvalue subroutines does make a reference to Sentinel, which, from a quick look at the docs, appears to implement something like a tied scalar, in XS.

      The tied scalar solution appears to already have been implemented with Sub::Lvalue, and in fact a search for "lvalue" on CPAN will show that the wheel has been reinvented several times, including making object accessors lvalues. One of the most comprehensive ones appears to be Contextual::Return (which implements its LVALUE/RVALUE blocks using tied scalars, too).

        The perldocs mention Sentinel?

        Now I'm considering writing a POD differ who shows me all perldoc differences for new versions once per year... ;-)

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Wikisyntax for the Monastery

      Yeah :lvalue is kind of orphaned and I rarely see it in use.

      An implementation by scanning the IP tree shouldn't be too difficult, so maybe habe look into CPAN.

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Wikisyntax for the Monastery

      > Yeah, returning a tied value is what I was grudgingly working on, as I didn't think it would be very efficient

      There is probably a solution without XS ...

      You could compare the caller in the tied STORE and set a flag $islvalue for the next call.

      Like that only your first call would be inefficient.

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Wikisyntax for the Monastery

        I thought of that ... it was tempting, but being extra rigorous w/my stuff, I wanted the values inspected through direct inspection $p->{one} to be consistent with the ones done through the accessor $p->one.

        FWIW, in my case, I don't need to check the value before the assignment, but immediately AFTER the assignment. For example -- wanted to be able to have a URL object where I break it down into proto,site[:port]/path, then, if I assign to $p->path, it would automatically be reflected in $p->url.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2024-04-19 20:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found