Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

Assignable Subroutines

by dragonchild (Archbishop)
on Jan 25, 2005 at 15:23 UTC ( #424891=perlmeditation: print w/replies, xml ) Need Help??

(I'm taking ideas generated from Experimenting with Lvalue Subs and creating a new meditation for the discussion.)

Limbic~Region, demerphq, and others in that discussion have already expressed an idea which has been, in the thread and CB, determined to be qualitatively different from the idea that TimToady is implementing called 'lvalue subs'. This is especially apparent in Re^6: Experimenting with Lvalue Subs.

Hopefully, those who want to have this feature added to Perl will hash out their ideas here. The goal, as I see it, is to end up with something that can be submitted to TimToady as a new feature - a complete RFC, so to speak.

Chat away!

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.

Replies are listed 'Best First'.
Re: Assignable Subroutines
by BrowserUk (Patriarch) on Jan 26, 2005 at 00:46 UTC

    It strikes me that the thing that prevents validation of values assigned to lvalue subs, is the way in which the lvalue is determined--by being the last line/value of the sub.

    If there were a keyword that allowed the programmer to indicate what the lvalue was, he could choose where in the sub that lvalue was positioned and control could be returned to the sub after the assignment has taken place.

    sub thing { my( @args ) = @_; ... code to determine what the lvalue should be. LVALUE{ $lvalue }; if( $lvalue eq some condition ) { ... take positive action; } else { ... take negative action; } }

    In use, the interpreter would run the code until the (or a?) LVALUE statement is encountered. This is directly equivalent to the current situation of running the sub to determine the lvalue. Once obtained, the LVALUE would be available to the calling code to use in whatever manner. Once the statement that called the sub completes, the remainder of the sub would be run, with the assigned value in place for veryification or whatever else the programmer might wish to do to it.

    There are probably a gazillion reasons why this won't work, but it seems to address most of the issues raised, whilst providing for inline, intuative validation.

    The main advantage I see of this over tieing, is that the validation code is at the same scope as the the lvalue determination code.

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

      Btw, such a mechanism exists. You're basically saying that lvalue subs could be implemented as coroutines which are expected to yield the lvalue.

      That's an interesting way of looking at this.

      Makeshifts last the longest.

        ...implemented as coroutines which are expected to yield the lvalue.

        Not really. I may appear that way, but coroutines flip back and forth. This doesn't.

        In actuality, there would be very little difference between this and using a tie/STORE method to validate.

        • The method is called to obtain the lvalue which is returned to the calling code.
        • At some point the calling code makes an assignment to the lvalue and (because that lvalue is tied) the STORE method is called.

        Except in this case the "STORE method" is the code inline from the LVALUE statement to the end of method.

        One distinct difference between this and a tie/STORE method, is that if the lvalue in question is an array or a slice of an array, the "callback code" would only be called once. Not once for every value in the list being assigned.

        I am still unsure what happens in the calling code if the STORE method (disguised or not) rejects the attempt to store a value?

        I also thought about whether the PRE/POST or ENTER/LEAVE blocks associable with a method could be used to provide for a single place in which all validation is done, but my reading of the Apos & Syns leaves me very confused about when these get called, if ever, with an lvalue sub.

        Of course, this whole discussion is a waste of time. Who are we to question whether there is a better way? Explain to plebians. Pah!

        Examine what is said, not who speaks.
        Silence betokens consent.
        Love the truth but pardon error.
Re: Assignable Subroutines
by BrentDax (Hermit) on Jan 26, 2005 at 01:38 UTC

    Untested proof-of-concept. Run it only if you don't mind your hard disks being set on fire.

    package Lvalue::GetSet; use Exporter; our @ISA=qw(Exporter); our @EXPORT=qw(get set); sub get(&@) :lvalue { unshift @_, 'get'; goto &getset; } sub set(&@) :lvalue { unshift @_, 'set'; goto &getset; } sub getset :lvalue { if(@_ == 2) { return @_; } elsif(@_ == 4) { my $var; tie $var, 'Lvalue::GetSet::Tie', @_; $var; } else { die "can't happen"; } } package Lvalue::GetSet::Tie; sub TIESCALAR { my($pkg, %obj)=@_; bless \%obj, $pkg; } sub FETCH { $_[0]->{get}->(); } sub STORE { $_[0]->{set}->($_[1]); }

    Usage would be something like:

    sub name { my $me=shift; get { $me->{name}; } set { die "Invalid name" unless $_[0] =~ /^(\w+)$/; $me->{name} = $1; } }

    What's wrong with something like this?

    --Brent Dax
    There is no sig.

Re: Assignable Subroutines
by perrin (Chancellor) on Jan 25, 2005 at 15:33 UTC
    Hmm, a way to do something we can already do easily (call a setter method), but in a new and confusing way that looks like you're doing something else? No thanks. I'd suggest the people who want it should use a source filter rather than adding it to Perl.

      We dont want to use source filters as they are are fundamentally unsafe. In order to implement this you need to be able to accurately determine when an EXPR ends, which isnt going to be an easy source filter to write, and could have bizarre side effects of its own.

      We want properties ala VB in Perl. Real nice and simple, not funkyness, no localization, just validation as part of assignment. It doesnt seem like an unreasonable request to me.


        How is it different, aside from syntax, from calling a setter method?
        Source filters are unsafe and evil, AND this language feature appears unneccessary. I'd rather not see the language overcomplicated unneccesarily for the benefit of a small few that see it as cool, hence, make it a source filter -- and leave the language clean. BECAUSE it's a source filter, hopefully far fewer people will use the "feature".

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://424891]
Approved by Limbic~Region
Front-paged by Limbic~Region
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (3)
As of 2022-09-26 18:35 GMT
Find Nodes?
    Voting Booth?
    I prefer my indexes to start at:

    Results (118 votes). Check out past polls.