Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Re: $foo->bar = 14;

by tadman (Prior)
on Jan 03, 2003 at 02:44 UTC ( [id://223947]=note: print w/replies, xml ) Need Help??


in reply to Re^2: $foo->bar = 14;
in thread $foo->bar = 14;

I think the aversion to using lvalue subroutines is cultural. I'm quite used to putting data, any data, into a C struct, or a C++ class object. You can shoot yourself in the foot, of course, but that's why you have to be careful.

At least superficially, lvalue subroutines feel a lot more like they're real, tangible things, and not some fleeting whim of a hash key. Yes, you can put in bad data, yes you can break things, but putting rubber pads on the edge of all of your functions does not make them safe. It's just defensive programming, which in many cases is dangerous if over-done.

As far as I can tell, lvalue works fine now, and when it's replaced with something better in Perl 6, which surely it will be, then there's no reason not to upgrade.

One could just as easily argue that Perl 5 is experimental. Your points 1, 2, and 3 all apply to the same degree.

Replies are listed 'Best First'.
Re^2: $foo->bar = 14;
by adrianh (Chancellor) on Jan 03, 2003 at 14:08 UTC
    I think the aversion to using lvalue subroutines is cultural

    Not in my case :-) I came to perl after doing a lot of coding in Pop-11 and I still miss its "updaterof" idiom.

    I would like being able to do $o->foo = 12 in my perl modules. It makes it explicit when a method is a mutator without the noise of having separate setter/getter functions.

    Unfortunately (in my opinion) the perl implementation of lvalue subs is near useless since it exposes the object implementation - making it harder to change your module

    Yes, you can put in bad data, yes you can break things, but putting rubber pads on the edge of all of your functions does not make them safe.

    Nothing can make your code 100% safe :-) Having assertions on arguments, etc. can certainly make it a lot safer. It can cut development time on larger projects by a silly amount - because you get sane errors close to the location that caused them.

    It's just defensive programming, which in many cases is dangerous if over-done.

    I agree, but I see it under-done a lot more than I see it over-done.

    However, the point I was trying to make wasn't about checking arguments - it was about exposing the implementation of your class.

    For example, consider a hypothetical object that can be readable, writeable or locked. With an :lvalue based API you would have something like this:

    my $o = Foo->new; $o->locked = 1; $o->writeable = 0; $o->readable = 1;

    Now, what happens if (for whatever reason) I want to change the underlying implementation of these attributes to use a bitmask. You either have to change your API - or create some ghastly hack with tie. This is what I mean by an over-exposure of your object's implementation.

    With a traditional single accessor/mutator or separate setter/getter methods - no problem.

    As far as I can tell, lvalue works fine now, and when it's replaced with something better in Perl 6, which surely it will be, then there's no reason not to upgrade.

    Hmmm... I wonder if you could do something sane now with the aid of tie and some source filters.... I'll have to have a think when I get some spare time...

    One could just as easily argue that Perl 5 is experimental. Your points 1, 2, and 3 all apply to the same degree.

    Got to disagree with that completely. They do not apply to the same degree. Experimental features break on a regular basis (threads, some of the regex stuff, etc.). Core perl has been very solid - due to lots of care and attention by the wonderful development peeps. I've had perl4 scripts run on 5.8 without a single change.

    The 5.8 release especially has had a lot of time spent on a very nice test suite to prevent regression problems.


    Update: Cleaned up the English a little.

      You don't have to change your API, or use a tie, at least in this case. Something like this, perhaps:
      sub read : lvalue { my ($self) = @_; vec($self->{value},0,1); }
      I know it's not pretty, but it works.

      I didn't mean to say that Perl hasn't worked very well for me, but there are occasions where it has been broken, though admittedly these were in the early days of Perl 5. So far, Perl 5.8 has been wonderful, too, so less experimental than ever before, perhaps.
        I know it's not pretty, but it works.

        True :-) However, I think my basic point still stands. Perl's current implementation of lvalue subs breaks implementation encapsulation - and can therefore make life considerably more complex if you have to change that implementation.

        The classic case of this is when you have an attribute that you later decide can be calculated/set by a runtime method (trading space for speed).

        Perl's lvalue subroutine implementation does not allow you to do this without resorting to tie (or possibly a source filter).

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (7)
As of 2024-03-28 13:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found