Sweetest Accessor?

Discussion in 'Perl Misc' started by Xiong Changnian, Mar 27, 2007.

  1. I'm learning, so I'm trying different idioms. Perhaps in the end it
    doesn't matter but I've been working on particularly terse idioms.

    One particular demand is for object data accessor methods. There are a
    lot of them and they all look somewhat alike -- sounds like a demand for
    laziness. What's the shortest, "sweetest" accessor sub?

    Here's what I've got (eg):

    METHOD1:

    sub name {
    my $obj = shift;
    $obj->{NAME} = shift ||
    $obj->{NAME};
    };

    This allows both gets and puts:

    $oldname = $obj->name;
    $obj->name ($newname);

    It still doesn't satisfy me. The needless assignment-to-self irks. Note
    that it does no good to change the order of precedence so that
    $obj->{NAME} is returned (without assigning it) if shift tests false; by
    then it's too late and shift has clobbered the old value. So here I test
    shift within the right-hand side expression before making the
    assignment.

    Here's another:

    METHOD2:

    sub name {
    $_[1] ? $_[0]->{NAME} =
    $_[1] : $_[0]->{NAME};
    };

    This avoids the needless assignment but now there's a second get of
    $_[1]. Supposing that the object is more complex and that hitting the
    object is more expensive than hitting the param, I'd guess this second
    version is more efficient. Also, no assignment to a temp $obj. It looks
    a bit odd to line break the statement after the assignment operator.

    I realize that some oppose needlessly terse or obscure code but I'll ask
    for forgiveness here. After all, an accessor method is simple. In the
    end, it's a wash anyway; I'm just experimenting. I'll take comments on
    either method shown and I'd love to see suggestions.
    --
    Xiong Changnian
    xiong102ATxuefangDOTcom

    --
    Posted via a free Usenet account from http://www.teranews.com
    Xiong Changnian, Mar 27, 2007
    #1
    1. Advertising

  2. Xiong Changnian

    -berlin.de Guest

    Xiong Changnian <> wrote in comp.lang.perl.misc:
    > I'm learning, so I'm trying different idioms. Perhaps in the end it
    > doesn't matter but I've been working on particularly terse idioms.
    >
    > One particular demand is for object data accessor methods. There are a
    > lot of them and they all look somewhat alike -- sounds like a demand for
    > laziness. What's the shortest, "sweetest" accessor sub?
    >
    > Here's what I've got (eg):
    >
    > METHOD1:
    >
    > sub name {
    > my $obj = shift;
    > $obj->{NAME} = shift ||
    > $obj->{NAME};
    > };
    >
    > This allows both gets and puts:
    >
    > $oldname = $obj->name;
    > $obj->name ($newname);
    >
    > It still doesn't satisfy me. The needless assignment-to-self irks. Note
    > that it does no good to change the order of precedence so that
    > $obj->{NAME} is returned (without assigning it) if shift tests false; by
    > then it's too late and shift has clobbered the old value. So here I test
    > shift within the right-hand side expression before making the
    > assignment.
    >
    > Here's another:
    >
    > METHOD2:
    >
    > sub name {
    > $_[1] ? $_[0]->{NAME} =
    > $_[1] : $_[0]->{NAME};
    > };
    >
    > This avoids the needless assignment but now there's a second get of
    > $_[1]. Supposing that the object is more complex and that hitting the
    > object is more expensive than hitting the param, I'd guess this second
    > version is more efficient. Also, no assignment to a temp $obj. It looks
    > a bit odd to line break the statement after the assignment operator.
    >
    > I realize that some oppose needlessly terse or obscure code but I'll ask
    > for forgiveness here. After all, an accessor method is simple. In the
    > end, it's a wash anyway; I'm just experimenting. I'll take comments on
    > either method shown and I'd love to see suggestions.


    You have noticed one problem with your accessors (multiple assignment).
    Another problem is that you won't be able to assign a boolean false
    value that way.

    The standard get-set accessor in Perl is

    sub name {
    my $obj = shift;
    $obj->{ name} = shift if @_;
    $obj->{ name};
    }

    It hinges on the presence of two arguments, not on the value of the
    second argument, so you can assign boolean false values, (including
    undef).

    For low-level read-write access I am partial to lvalue accessors
    these days:

    sub name : lvalue { shift()->{ name} }

    These are (usually) not for the class user (because you can't check
    lvalues), but for your own use when you write the class code. Give
    them an initial "_" if you want to make that clear.

    Anno
    -berlin.de, Mar 27, 2007
    #2
    1. Advertising

  3. Xiong Changnian

    Mumia W. Guest

    On 03/27/2007 08:08 AM, Xiong Changnian wrote:
    > I'm learning, so I'm trying different idioms. Perhaps in the end it
    > doesn't matter but I've been working on particularly terse idioms.
    > [...]


    perldoc perltoot
    perldoc Class::Struct
    perldoc Class::Accessor
    Mumia W., Mar 27, 2007
    #3
  4. In article <>,
    -berlin.de wrote:

    > Another problem is that you won't be able to assign a boolean false
    > value that way.


    Well, I'm not sure that's a problem. I abhor boolean false values as a
    matter of taste. Reserving FALSE demands that every value assigned to a
    variable have a TRUE value (obviously) and I think that's good style. I
    realize that someone else will be quite comfortable with, say, integer
    zero values in some places and require an accessor that permits them. I
    just don't.

    If I ever thought I would want deliberately to set a variable inside a
    complex data structure to 0, "", or undef, I'd write a distinct "clear"
    method.


    > The standard get-set accessor in Perl is
    >
    > sub name {
    > my $obj = shift;
    > $obj->{ name} = shift if @_;
    > $obj->{ name};
    > }


    No offense, but that's neither short nor sweet. I particularly don't
    care for mixing shift and @_ in the same sub -- visually.

    Of course, a working accessor might be written in any number of ways and
    perhaps there are several idioms that will all compile to equivalent
    byte code or be equally efficient. My immediate goal here is terseness,
    sweetness -- "niftyness", if you will. Sorry if that sounds trivial.


    > sub name : lvalue { shift()->{ name} }


    I really, really like the idea of lvalue subs. They make calling syntax
    much more symmetrical and "natural". I was scared off by dire warnings
    (eg):

    "WARNING: Lvalue subroutines are still experimental and the
    implementation may change in future versions of Perl."

    I'd welcome comments. Are lvalue subs coming or going? Will my code blow
    up next release?

    I would like to see what sort of Frankenstein's Monsters I can build
    with lvalue subs, prototypes, and overloading. I'm sure any code I post
    from that lab will raise eyebrows.


    In article <ddaOh.131662$>,
    "Mumia W." <> wrote:

    > perldoc Class::Accessor


    I'm sure you mean well but you must be a get-the-job-done type. It's
    useless to me to let George do it; I'm experimenting.

    FWIW, here's what the indicated module's doc says it generates:

    # Your foo may vary.
    sub foo {
    my($self) = shift;
    if(@_) { # set
    return $self->set('foo', @_);
    }
    else {
    return $self->get('foo');
    }
    }

    That is definitely not a terse idiom.

    I dunno, but maybe my METHOD2 is as far as one can go in my chosen
    direction:

    METHOD2:

    sub name {
    $_[1] ? $_[0]->{NAME} =
    $_[1] : $_[0]->{NAME};
    };

    Still, nothing can beat the lvalue sub for sheer terse beauty. If only
    we could depend on it?
    --
    Xiong Changnian
    xiong102ATxuefangDOTcom

    --
    Posted via a free Usenet account from http://www.teranews.com
    Xiong Changnian, Mar 28, 2007
    #4
  5. Xiong Changnian

    -berlin.de Guest

    Xiong Changnian <> wrote in comp.lang.perl.misc:
    > In article <>,
    > -berlin.de wrote:
    >
    > > Another problem is that you won't be able to assign a boolean false
    > > value that way.

    >
    > Well, I'm not sure that's a problem. I abhor boolean false values as a
    > matter of taste. Reserving FALSE demands that every value assigned to a
    > variable have a TRUE value (obviously) and I think that's good style. I
    > realize that someone else will be quite comfortable with, say, integer
    > zero values in some places and require an accessor that permits them. I
    > just don't.
    >
    > If I ever thought I would want deliberately to set a variable inside a
    > complex data structure to 0, "", or undef, I'd write a distinct "clear"
    > method.


    I don't think you'll be happy with that in the long run. Many fields
    take values that happen to be false in the normal course of things.
    Suppose you have a field "score" you want to count up and down:

    if ( $won ) {
    $player->score( $player->score + 1);
    } else {
    $player->score( $player->score - 1);
    }

    That would fail to change the score if the score would have reached
    zero. You'd need an ugly workaround, even if you have a special method
    "->clear_score" to set it to zero.

    > > The standard get-set accessor in Perl is
    > >
    > > sub name {
    > > my $obj = shift;
    > > $obj->{ name} = shift if @_;
    > > $obj->{ name};
    > > }

    >
    > No offense, but that's neither short nor sweet.


    I'm not claiming short and sweet. It's standard.

    > I particularly don't
    > care for mixing shift and @_ in the same sub -- visually.


    Why?

    > Of course, a working accessor might be written in any number of ways and
    > perhaps there are several idioms that will all compile to equivalent
    > byte code or be equally efficient. My immediate goal here is terseness,
    > sweetness -- "niftyness", if you will. Sorry if that sounds trivial.
    >
    >
    > > sub name : lvalue { shift()->{ name} }

    >
    > I really, really like the idea of lvalue subs. They make calling syntax
    > much more symmetrical and "natural". I was scared off by dire warnings
    > (eg):
    >
    > "WARNING: Lvalue subroutines are still experimental and the
    > implementation may change in future versions of Perl."


    I'm not much worried by that. There seems to be little ongoing
    discussion of lvalue subs. I think they are here to stay.

    Anno
    -berlin.de, Mar 28, 2007
    #5
  6. In article <>,
    -berlin.de wrote:

    > Many fields
    > take values that happen to be false...


    Well, yes; depends on your application. The stuff I'm doing now, this
    doesn't usually come up. I make it *not* come up.

    Please remember this is all a learning project for me; I'm going in
    directions that have nothing to do with getting-the-job-done. With my
    background, Perl is a novel and exciting language with amazingly
    succinct ways of doing things. I'm pushing the edges of that as far as
    possible.

    Just to put a little contrast on that, I'm also designing, for the
    benefit of some of my students, a set of relay logic gates; I've got up
    to the full adder. This has been done before, of course, but perhaps not
    with my particular design restrictions: all lines high or low, nothing
    open or float; all coils grounded at one end. The intent is to make the
    circuits 74CXX compatible and the most fundamental operations of a
    binary digital computer as transparent as possible to the student
    without sacrificing rigor. Obviously, I could get-the-job-done a lot
    more easily.

    Sorry if I seem to be banging my head deliberately against the wall.


    Xiong wrote:

    > > I particularly don't
    > > care for mixing shift and @_ in the same sub -- visually.

    >
    > Why?


    I'd like to respond to your question but I'm not sure how; it's just a
    stylistic or gut feeling. For complex subs, I like the idiom of shifting
    all the params into my variables; it puts a nice little self-documenting
    declaration block up top. Now that I've been fooling around awhile, I'm
    starting to see the limitations and inefficiencies in this and I'm
    trying things the other way. One bone I have to pick with @_ is that it
    allows me to clobber the actual param, which I generally don't want to
    do. Also, after a lifetime of subscripting, I'm straining now to avoid
    it. On the other hand, there are elegant @_ and $_[$n] approaches.

    If it makes me look like a more reasonable person, my generic new shifts
    for the class, then passes @_ to init.


    > > "WARNING: Lvalue subroutines are still experimental and the
    > > implementation may change in future versions of Perl."

    >
    > I'm not much worried by that. There seems to be little ongoing
    > discussion of lvalue subs. I think they are here to stay.


    Well, I *really* appreciate that assurance. I'm going to take your
    comment as a license to go hog wild. The lvalue accessor you posted may
    well be the shortest distance between two points -- and looks good in
    the calling context. Throw in prototypes and a little overloading and I
    can imagine writing some lucid code in the caller. Now, if I could only
    figure out how to get rid of those superfluous commas....

    Of course, it's all fake and heaven help the intrepid who use my modules
    without reading the docs. But then, I don't expect my stuff to be on
    CPAN any time soon.

    Thanks again.
    --
    Xiong Changnian
    xiong102ATxuefangDOTcom

    --
    Posted via a free Usenet account from http://www.teranews.com
    Xiong Changnian, Mar 28, 2007
    #6
  7. Xiong Changnian

    -berlin.de Guest

    Xiong Changnian <> wrote in comp.lang.perl.misc:
    > In article <>,
    > -berlin.de wrote:
    >
    > > Many fields
    > > take values that happen to be false...

    >
    > Well, yes; depends on your application. The stuff I'm doing now, this
    > doesn't usually come up. I make it *not* come up.


    Well, your question came around as being about the style of general-
    purpose accessors. I would not recommend a general-purpose accessor
    that doesn't transfer certain values.

    [snip]

    > > > I particularly don't
    > > > care for mixing shift and @_ in the same sub -- visually.

    > >
    > > Why?

    >
    > I'd like to respond to your question but I'm not sure how; it's just a
    > stylistic or gut feeling. For complex subs, I like the idiom of shifting
    > all the params into my variables; it puts a nice little self-documenting
    > declaration block up top.


    That isn't tied to shifting. The most self-documenting way of
    parameter assignment would have to be:

    my ( $name, $age, $occupation) = @_;

    Shifting parameters off @_ is done for various reasons:

    - You want to deal with each parameter individually before you
    enter the body of the sub

    my $name = shift || 'anonymous';
    my $age= shift || 0;
    my $occupation = $default_occupation[ $age];

    - You want to get things out of the way and deal with the
    remaining arguments uniformly

    my $mode = shift;
    for ( @_ ) { # ...

    - In method calls, you shift off the invocant (class or object)
    to make the content of @_ conform to the parameters given at
    the call site;

    $obj->meth( $name, $age, $occupation);

    # corresponds to

    my $obj = shift;
    my ( $name, $age, $occupation) = @_;

    > Now that I've been fooling around awhile, I'm
    > starting to see the limitations and inefficiencies in this and I'm
    > trying things the other way. One bone I have to pick with @_ is that it
    > allows me to clobber the actual param, which I generally don't want to
    > do. Also, after a lifetime of subscripting, I'm straining now to avoid
    > it. On the other hand, there are elegant @_ and $_[$n] approaches.


    These are usually restricted to small (one-line) subs. If anything
    substantial goes on in the sub body, assignment of parameters to
    named variables is the norm. Unless you *want* to change an argument,
    or do other things that don't work on a copy.

    BTW, shift() as such doesn't stop you from changing a parameter.
    "

    > If it makes me look like a more reasonable person, my generic new shifts
    > for the class, then passes @_ to init.


    Right, that's one of the cases I mentioned. And congratulations for
    providing a separate initializer. It's all too often forgotten.

    [snip lvalue, except]

    > the calling context. Throw in prototypes and a little overloading and I
    > can imagine writing some lucid code in the caller. Now, if I could only


    You can't throw prototypes into an OO design. Prototypes are ignored
    in method calls. In general, prototypes appear to introduce more
    problems than they solve. It is true that they let you (sometimes)
    design a particularly intuitive interface. Restrict prototypes to
    such cases, don't use them as a matter of course.

    Overloading goes a much longer way in the direction of intuitive
    interfaces, but is also not without problems. In a general-purpose
    class the user should be able to opt out of overloading.

    Anno
    -berlin.de, Mar 28, 2007
    #7
  8. Shifting Away

    In article <>,
    -berlin.de wrote:

    > BTW, shift() as such doesn't stop you from changing a parameter.


    That statement baffles me. Perhaps I'm missing something. Here's my
    understanding -- not to lecture, but please tell me where I run off the
    bridge.

    All in all -- as I've thanked this poster before -- I like the lvalue
    sub syntax if I'm going to set an actual param value. I've been
    sidestepping this issue for the most part because I'm writing object
    methods, which are *expected* to take an object (hash ref) as a param
    and tinker with the referent.

    * * *

    @_ contains aliases to actual params -- the "stuff" supplied as params
    by the calling context. Thus, in:

    $, = " "; $\ = "\n";
    $foo = 'goodstuff';
    $bar = 'morestuff';
    $error = dosomething($foo, $bar);
    print $foo, $bar;

    SUB1:
    sub dosomething {
    $_[0] = 'bang';
    print $_[0], $_[1];
    return 0;
    };

    The literal 'bang' clobbers the calling context's value ('goodstuff') of
    $foo -- bug, feature, or sloppy coder, you decide. In essence, it's a
    call-by-reference but no dereffing is expected. Output reads:

    bang morestuff
    bang morestuff

    .... $bar is untouched.

    However:

    SUB2:
    sub dosomething {
    my $stuff = shift;
    $stuff = 'bang';
    print $_[0], $_[1], '\n';
    return 0;
    };

    Now nothing is clobbered; output reads:

    morestuff
    goodstuff morestuff

    .... because shift -- implicitly, shift(@_) -- takes on the value of
    $_[0] and then makes $_[0] an alias to $bar, so:

    SUB3:
    sub dosomething {
    my $stuff = shift;
    $_[0] = 'bang';
    print $_[0], $_[1], '\n';
    return 0;
    };

    gives output:

    bang
    goodstuff bang

    The assignment inside the sub now clobbers $bar but $foo is untouched.

    This will clobber neither $foo nor $bar:

    SUB4:
    sub dosomething {
    my $stuff = shift;
    $_[1] = 'bang';
    print $_[0], $_[1];
    return 0;
    };

    Output:

    morestuff bang
    goodstuff morestuff

    Explanation being that at the time of shift-ing, $_[1] became undef --
    and stayed that way until defined by literal assignment; the alias to
    $bar is lost.

    BTW:

    SUB5:
    sub dosomething {
    @_ = ('bang', 'whimper');
    print $_[0], $_[1];
    return 0;
    };

    Output:

    bang whimper
    goodstuff morestuff

    Assigning to @_ itself, as opposed to a subscripted element, does *not*
    clobber the actual params. It has to be the whole bananna:

    SUB6:
    sub dosomething {
    @_[0,1] = ('bang', 'whimper');
    print $_[0], $_[1];
    return 0;
    };

    Output:

    bang whimper
    bang whimper

    Array slice isn't good enough.

    * * *

    I read an argument against using @_ even in the case of throwaway actual
    params; you don't care if they get clobbered. What if your caller
    doesn't read docs?

    Calling SUB1 with:

    $error = dosomething('nixon', 'agnew');

    raises a fatal exception because attempting to assign to $_[0] is an
    attempt to assign to a literal. Calling SUB2 is fine. FWIW, even SUB4
    works okay; 'nixon' is shifted off and 'agnew' ducks the bullet.

    Naturally, this is no barrier to using @_ but it's a caution. ("Do I
    know what I'm doing? Okay then.")

    * * *

    So, it's my understanding that if I consistently shift off all my
    params, I *can't* clobber them. If I use $_[$n] then it's up to me
    either to keep it on the right side or deliberately clobber. If I mix
    shift and $_[$n] then I'd better *really* be careful because whether I
    want to clobber or not, I won't get what I want unless either I get
    lucky or pay close attention to what I'm doing.

    Of course, I can always shift all params and then proceed to assign
    freely to $_[$n] -- but then I'm just using it as a scratch variable.

    I suppose I can always test something, maybe assign a default to $_[$n],
    then later shift something off. But tell me honestly: If you knew I'd
    done that without good and sufficient reason, would you rush to switch
    off the machine when I got my fingers caught in the gears?
    --
    Xiong Changnian
    xiong102ATxuefangDOTcom

    --
    Posted via a free Usenet account from http://www.teranews.com
    Xiong Changnian, Mar 29, 2007
    #8
  9. Re: Shifting Away

    Xiong Changnian wrote:
    > In article <>,
    > -berlin.de wrote:
    >
    >> BTW, shift() as such doesn't stop you from changing a parameter.

    >
    > That statement baffles me. Perhaps I'm missing something. Here's my
    > understanding -- not to lecture, but please tell me where I run off the
    > bridge.
    >
    > All in all -- as I've thanked this poster before -- I like the lvalue
    > sub syntax if I'm going to set an actual param value. I've been
    > sidestepping this issue for the most part because I'm writing object
    > methods, which are *expected* to take an object (hash ref) as a param
    > and tinker with the referent.
    >
    > * * *
    >
    > @_ contains aliases to actual params -- the "stuff" supplied as params
    > by the calling context. Thus, in:
    >
    > $, = " "; $\ = "\n";
    > $foo = 'goodstuff';
    > $bar = 'morestuff';
    > $error = dosomething($foo, $bar);
    > print $foo, $bar;


    [ snip ]

    > However:
    >
    > SUB2:
    > sub dosomething {
    > my $stuff = shift;
    > $stuff = 'bang';
    > print $_[0], $_[1], '\n';
    > return 0;
    > };
    >
    > Now nothing is clobbered; output reads:
    >
    > morestuff
    > goodstuff morestuff


    No, the output *should* read:

    morestuff \n
    goodstuff morestuff


    > ... because shift -- implicitly, shift(@_) -- takes on the value of
    > $_[0] and then makes $_[0] an alias to $bar, so:
    >
    > SUB3:
    > sub dosomething {
    > my $stuff = shift;
    > $_[0] = 'bang';
    > print $_[0], $_[1], '\n';
    > return 0;
    > };
    >
    > gives output:
    >
    > bang
    > goodstuff bang


    It *should* look more like:

    bang \n
    goodstuff bang


    I take it you didn't test this stuff? :)



    John
    --
    Perl isn't a toolbox, but a small machine shop where you can special-order
    certain sorts of tools at low cost and in short order. -- Larry Wall
    John W. Krahn, Mar 29, 2007
    #9
  10. Xiong Changnian

    Dr.Ruud Guest

    Re: Shifting Away

    Xiong Changnian schreef:

    > The literal 'bang' clobbers the calling context's value ('goodstuff')
    > of $foo -- bug, feature, or sloppy coder, you decide. In essence,
    > it's a call-by-reference but no dereffing is expected.


    You should stop making such statements until you understand why it is
    like it is.
    But even if you don't, I won't notice it, goodbye.

    --
    Affijn, Ruud

    "Gewoon is een tijger."
    Dr.Ruud, Mar 29, 2007
    #10
  11. Xiong Changnian

    -berlin.de Guest

    Re: Shifting Away

    Xiong Changnian <> wrote in comp.lang.perl.misc:
    > In article <>,
    > -berlin.de wrote:
    >
    > > BTW, shift() as such doesn't stop you from changing a parameter.

    >
    > That statement baffles me. Perhaps I'm missing something. Here's my
    > understanding -- not to lecture, but please tell me where I run off the
    > bridge.


    Well, it's true, and not stranger than the existence of lvalue subs,
    but it's harder to demonstrate than I thought. I had intended to delete
    that sentence and dodge an explanation, but since I let it stand,
    here goes.

    The result of shift() is an alias to the list element that is shifted
    off and allows write access. This can be seen subs like

    sub x1 { $_ = 13 for shift }

    sub x2 { my $ref = \ shift; $$ref = 13 }

    which both set their argument to 13 if they can.

    sub x3 { shift() = 13 }

    doesn't compile (probably a good thing), but in the light of the
    other two that restriction is artificial.

    Anno
    -berlin.de, Mar 29, 2007
    #11
  12. Re: Shifting Away

    In article <BxUOh.20674$6z3.11150@edtnps82>,
    "John W. Krahn" <> wrote:

    > I take it you didn't test this stuff? :)


    I started writing code in MT-NewsWatcher, then decided indeed to switch
    to BBEdit, code and test before blatting my opinions in *.perl.*. For
    reasons which elude me now, I did not copy the code back out of BBEdit.
    During test, about the time I realized I needed to double-quote "\n", I
    decided to slim it down with:

    $, = " "; $\ = "\n";

    .... making all the trailing newlines obsolete. You caught me; you win a
    fully-operational Mac SE, loaded with important and useful software. You
    must collect your prize in person taxes are the winner's responsibility
    employees and family members are ineligible read fine print for contest
    details.

    In any case, the point of my post was all about shift and clobbering
    actual params, not about my doofus print formatting.

    Here's the actual code, in full, with output. Sorry, but you have to
    change the sub call on each run. Uncomment if you want to raise Nixon
    and Agnew from the grave; this *will* raise a fatal exception.

    sub1: clobbers $foo only
    sub2: clobbers neither
    sub3: clobbers $bar only
    sub4: clobbers neither
    sub5: clobbers neither
    sub6: clobbers both

    * * *

    use strict;

    my $foo;
    my $bar;
    my $error;

    $, = " "; $\ = "\n";

    $foo = 'goodstuff';
    $bar = 'morestuff';
    $error = sub1($foo, $bar);
    print $foo, $bar;

    #$error = sub1('nixon', 'agnew');

    sub sub1 {
    $_[0] = 'bang';
    print $_[0], $_[1];
    return 0;
    };
    # bang morestuff
    # bang morestuff

    sub sub2 {
    my $stuff = shift;
    $stuff = 'bang';
    print $_[0], $_[1];
    return 0;
    };
    # morestuff
    # goodstuff morestuff

    sub sub3 {
    my $stuff = shift;
    $_[0] = 'bang';
    print $_[0], $_[1];
    return 0;
    };
    # bang
    # goodstuff bang

    sub sub4 {
    my $stuff = shift;
    $_[1] = 'bang';
    print $_[0], $_[1];
    return 0;
    };
    # morestuff bang
    # goodstuff morestuff

    sub sub5 {
    @_ = ('bang', 'whimper');
    print $_[0], $_[1];
    return 0;
    };
    # bang whimper
    # goodstuff morestuff

    sub sub6 {
    @_[0,1] = ('bang', 'whimper');
    print $_[0], $_[1];
    return 0;
    };
    # bang whimper
    # bang whimper

    * * *
    --
    Xiong Changnian
    xiong102ATxuefangDOTcom

    --
    Posted via a free Usenet account from http://www.teranews.com
    Xiong Changnian, Mar 31, 2007
    #12
  13. Re: Shifting Away

    In article <>,
    "Dr.Ruud" <> wrote:

    > Xiong Changnian schreef:
    >
    > > The literal 'bang' clobbers the calling context's value ('goodstuff')
    > > of $foo -- bug, feature, or sloppy coder, you decide. In essence,
    > > it's a call-by-reference but no dereffing is expected.

    >
    > You should stop making such statements until you understand why it is
    > like it is.
    > But even if you don't, I won't notice it, goodbye.


    Well, no need to be snooty. Enlighten me. I'm not even sure what part of
    my questionable statement offends.

    Are you questioning "call-by-reference"? I weaseled with "in essence". I
    don't think it *is* a call-by-value if I *can* clobber it. On the other
    hand, it's not a ref as Perl defines such things.

    It seems to me that the call-by-ref nature of perl is something that can
    be put to use but at times, it's exactly what's not wanted. So if actual
    params get clobbered, you can blame Perl, acclaim Perl, or blame the
    coder. I suppose I should have included the possibility of acclaiming
    the coder for his brilliant decision. I can't for the life of me think
    why you'd find this objectionable.

    But, as I suggested, you're welcome to fill me in.

    * * *

    For other posters who are wondering why I dare to talk back to the
    esteemed Dr. Rude, just let me say that I'm not going to apologize for
    thinking or speaking -- today, tomorrow, or next week. If I'm wrong, I'm
    wrong; I've been wrong before, I'll be wrong again. I'm always willing
    to correct my mistakes but I'll never stop making them.

    A strength of any community is the willingness and ability to welcome
    newcomers on an equal footing.
    --
    Xiong Changnian
    xiong102ATxuefangDOTcom

    --
    Posted via a free Usenet account from http://www.teranews.com
    Xiong Changnian, Mar 31, 2007
    #13
  14. Re: Shifting Away

    In article <>,
    -berlin.de wrote:

    > ...it's harder to demonstrate than I thought.


    To recap, I understand you to claim that actual params can be clobbered
    within a called sub that shift-s.


    > sub x3 { shift() = 13 }
    >
    > doesn't compile...


    Well, here you're trying to assign to shift itself; I believe shift is
    never an lvalue.

    > sub x1 { $_ = 13 for shift }


    That does indeed clobber the actual param. As I understand it, your code
    shifts off the first (or only) param -- by definition, not a list --
    then treats it as a single-element list; the first (and only) trip
    through the foreach loop, $_ is set to the first (and only) element of
    that list. And $_ is an alias to the thing itself.

    I guess if you try hard enough, you can break anything.

    > I had intended to delete
    > that sentence and dodge an explanation...


    Why? This is what it's all about: finding the edges. Now, I'll be sure
    not to do *that*. Thank you.
    --
    Xiong Changnian
    xiong102ATxuefangDOTcom

    --
    Posted via a free Usenet account from http://www.teranews.com
    Xiong Changnian, Mar 31, 2007
    #14
  15. Re: Shifting Away

    On 2007-03-31 01:05, Xiong Changnian <> wrote:
    > In article <>,
    > "Dr.Ruud" <> wrote:
    >> Xiong Changnian schreef:
    >> > The literal 'bang' clobbers the calling context's value ('goodstuff')
    >> > of $foo -- bug, feature, or sloppy coder, you decide. In essence,
    >> > it's a call-by-reference but no dereffing is expected.

    >>
    >> You should stop making such statements until you understand why it is
    >> like it is.
    >> But even if you don't, I won't notice it, goodbye.

    >
    > Well, no need to be snooty. Enlighten me. I'm not even sure what part of
    > my questionable statement offends.
    >
    > Are you questioning "call-by-reference"? I weaseled with "in essence". I
    > don't think it *is* a call-by-value if I *can* clobber it. On the other
    > hand, it's not a ref as Perl defines such things.


    It is call-by-reference. In other languages which pass parameters by
    reference you don't have to explicitely dereference them either.

    > It seems to me that the call-by-ref nature of perl is something that can
    > be put to use but at times, it's exactly what's not wanted. So if actual
    > params get clobbered, you can blame Perl, acclaim Perl, or blame the
    > coder.


    It wasn't clear who you were blaming of "sloppy coding". Larry Wall or
    the coder of the subroutine which clobbers its arguments?

    I think we can rule out that the fact that perl uses call-by-reference
    is the result of sloppy coding. That was a design decision. We can
    debate whether it was a good or a bad decision, but I think there is no
    question that Larry thought about whether he wanted to implement
    call-by-value or call-by-reference and decided for call-by-reference.

    As for the coder of the routine: That may be sloppyness, or it may be
    intentional.

    > I suppose I should have included the possibility of acclaiming
    > the coder for his brilliant decision.


    Yes. That possibility does exist. If there would never be a reason for
    clobbering an argument then implementing call-by-reference was a mistake
    in the first place. You will notice that many of perls built-in
    functions do clobber one of their arguments.

    hp


    --
    _ | Peter J. Holzer | Blaming Perl for the inability of programmers
    |_|_) | Sysadmin WSR | to write clearly is like blaming English for
    | | | | the circumlocutions of bureaucrats.
    __/ | http://www.hjp.at/ | -- Charlton Wilbur in clpm
    Peter J. Holzer, Mar 31, 2007
    #15
  16. Re: Shifting Away

    In article <>,
    "Peter J. Holzer" <> wrote:

    > It wasn't clear who you were blaming of "sloppy coding"....


    Sorry. I guess I took it for granted that any reader would understand
    what I meant. I'm not sure I can be more lucid but I'll try.

    When you deliberately pass refs to params, you must explicitly deref
    them inside the sub. Therefore, there is a bit of confusion involved
    when saying that Perl passes all params as refs. It's true; but a little
    bit deeper in the machinery, the ref is dereffed for you. That's
    probably an inexact statement but that's not the issue. As you say,
    Peter, it *is* call-by-ref, even if the syntax says you're just passing
    a scalar.

    (This distinction is important to me because I avidly pass refs as
    params when it's reasonable to do so; and because my code is seriously
    OO and all objects are refs.)

    Now, this can be a useful thing or it can cause problems -- like any
    feature of any tool. You can choose to see it as a bug to be worked
    around or a feature to be used; and if it bites you, you can blame
    yourself -- or, if you want to be bullheaded, blame Perl. In my last
    post, I covered the fourth possibility, in which you use the feature to
    good effect and give yourself a pat on the back.

    I hope I haven't stepped into some fanatic defense of Perl here. I
    *like* it; I think it's better than competing P*'s; and I wouldn't
    recommend Ruby due to immaturity -- **IMHO**! I assume that everyone
    here thinks Perl is a Good Thing -- otherwise, why be here?

    Is there some shibboleth I must pronounce to bypass this rigorous
    loyalty-checking? I'm not really interested in fighting over the
    Rightness of Perl -- on either side. I just want to know how it works. I
    come here to ask questions and learn. I'm not trying to rewrite the
    docs.
    --
    Xiong Changnian
    xiong102ATxuefangDOTcom

    --
    Posted via a free Usenet account from http://www.teranews.com
    Xiong Changnian, Mar 31, 2007
    #16
  17. Xiong Changnian

    Uri Guttman Guest

    Re: Shifting Away

    >>>>> "XC" == Xiong Changnian <> writes:

    XC> In article <>,
    XC> "Peter J. Holzer" <> wrote:

    XC> When you deliberately pass refs to params, you must explicitly deref
    XC> them inside the sub. Therefore, there is a bit of confusion involved
    XC> when saying that Perl passes all params as refs. It's true; but a little
    XC> bit deeper in the machinery, the ref is dereffed for you. That's
    XC> probably an inexact statement but that's not the issue. As you say,
    XC> Peter, it *is* call-by-ref, even if the syntax says you're just passing
    XC> a scalar.

    ok, let's try to clear up some stuff. first off all sub args are passed by
    alias, not exactly by ref. it isn't deliberate or accidental, but all
    the time. the callee has the aliases in @_ and can do with them what it
    wants. the act of copying an alias is not dereferencing it but removing
    the alias nature and making a copy of the original argument. it does not
    break the alias which is still in @_. and i reiterate they are NOT refs
    but aliases (similar to aliasing in foreach). you can't call ref on them
    and get a ref type:

    perl -le 'sub foo { print ref $_[0] } foo( 1 ) ;'

    perl -le 'sub foo { print ref $_[0] } foo( [] ) ;'
    ARRAY


    XC> (This distinction is important to me because I avidly pass refs as
    XC> params when it's reasonable to do so; and because my code is seriously
    XC> OO and all objects are refs.)

    refs are not aliases. you explicitly pass a ref since you want a real
    ref to be used in the sub/method. you can't use @_ aliases as object or
    other refs. so stop calling them refs.

    XC> Now, this can be a useful thing or it can cause problems -- like any
    XC> feature of any tool. You can choose to see it as a bug to be worked
    XC> around or a feature to be used; and if it bites you, you can blame
    XC> yourself -- or, if you want to be bullheaded, blame Perl. In my last
    XC> post, I covered the fourth possibility, in which you use the feature to
    XC> good effect and give yourself a pat on the back.

    the only bug in in your understanding. @_ aliases are not refs. consider
    this: when you assign (via indexing or shift) an alias from @_ to any
    variable, it loses it alias nature. yet you can assign a ref to anything
    else and it keeps its ref nature. @_ aliases are special. and one reason
    they were made that way was for speed. it is much cheaper to push a list
    of aliases onto a stack then to copy all of the arguments. and it allows
    for the direct modification of the original arguments IF YOU WANT to do
    that via aliases. if you don't you can always pass refs and copy those
    as normal and modify away. YOUR CHOICE. in general it is always better
    to pass refs yourself but there are some small cases where modifying via
    aliases is a useful idea. not common but they exist.

    XC> I hope I haven't stepped into some fanatic defense of Perl here. I
    XC> *like* it; I think it's better than competing P*'s; and I wouldn't
    XC> recommend Ruby due to immaturity -- **IMHO**! I assume that everyone
    XC> here thinks Perl is a Good Thing -- otherwise, why be here?

    you are not talking about the same thing so there is no fanatic
    defense. you don't seem to understand aliases vs refs. that is the
    problem, not perl.

    XC> Is there some shibboleth I must pronounce to bypass this rigorous
    XC> loyalty-checking? I'm not really interested in fighting over the
    XC> Rightness of Perl -- on either side. I just want to know how it works. I
    XC> come here to ask questions and learn. I'm not trying to rewrite the
    XC> docs.

    yes, you must come to an understanding of the actual topic first before
    you flame away and babble incoherently. @_ aliases are not refs. you
    think that because they refer to the original value that this is pass by
    reference but it is not the same as most times you copy the args and
    then they become pass by value. only a few subs should ever directly
    modify their args via @_. and only a few more should directly access
    @_. @_ is usually assigned to my vars or shifted (or both which can be
    useful).

    that is all.

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
    Uri Guttman, Mar 31, 2007
    #17
  18. Xiong Changnian

    -berlin.de Guest

    Re: Shifting Away

    Xiong Changnian <> wrote in comp.lang.perl.misc:
    > In article <>,
    > -berlin.de wrote:
    >
    > > ...it's harder to demonstrate than I thought.

    >
    > To recap, I understand you to claim that actual params can be clobbered
    > within a called sub that shift-s.


    Quite so.

    > > sub x3 { shift() = 13 }
    > >
    > > doesn't compile...

    >
    > Well, here you're trying to assign to shift itself; I believe shift is
    > never an lvalue.


    Pardon the pedantry, but I'm not trying to assign to "shift itself",
    but to the return value of the function "shift" or, if you will, the
    result of the list operator "shift". In view of the existence of lvalue
    subs and other operators (substr for instance) that allow assignment to
    their results that isn't entirely unreasonable. As I said before, the
    restriction is syntactical and rather arbitrary.

    > > sub x1 { $_ = 13 for shift }

    >
    > That does indeed clobber the actual param. As I understand it, your code
    > shifts off the first (or only) param -- by definition, not a list --
    > then treats it as a single-element list; the first (and only) trip
    > through the foreach loop, $_ is set to the first (and only) element of
    > that list. And $_ is an alias to the thing itself.
    >
    > I guess if you try hard enough, you can break anything.


    One-shot for loops aren't that exotic in Perl. With for loops over
    lists you get aliasing, which means that the loop variable ($_ in
    this case) becomes another name for the list element. Assignment to
    the loop variable changes the list element, unlike assignment to
    a copy. Sometimes aliasing is all you want, there is only a single
    element to loop over. Fortunately, the meaning of "for" (but not
    the non-word "foreach") covers the one-shot case nicely.

    That is what happens in "sub x1 { $_ = 13 for shift }". If you will,
    it is nothing but a syntactically acceptable form of "shift() = 13".
    It proves that what shift() returns *is* an lvalue and can be used to
    clobber the actual parameter. What makes the parameter safe is
    assignment to a (usually) lexical variable in the sub body. That
    creates a copy of the value that has nothing to do with the original
    parameter.

    > > I had intended to delete
    > > that sentence and dodge an explanation...

    >
    > Why? This is what it's all about: finding the edges. Now, I'll be sure
    > not to do *that*. Thank you.


    Perl's "postmodern", non-orthogonal design entails lots and lots of
    edge cases where the actual behavior can't be derived from general
    principles, but is geared to the particular case. It is often
    distracting and sometimes impossible to discuss all that may be
    relevant to a topic.

    Normally, the use of shift() in a sub means the sub is not going
    to change the parameter in question. If the form is the standard

    my $var = shift;

    you *know* that, because the only original is gone and all the sub
    has is a copy[1]. If shift() is used in other ways, you must look
    closer.

    Anno

    [1] If I were to discuss all ramifications I'd have to mention the
    possibility that the same parameter could appear a second time
    in the argument list and the sub could still change that.
    -berlin.de, Mar 31, 2007
    #18
  19. Xiong Changnian

    -berlin.de Guest

    Re: Shifting Away

    Uri Guttman <> wrote in comp.lang.perl.misc:
    > >>>>> "XC" == Xiong Changnian <> writes:

    >
    > XC> In article <>,
    > XC> "Peter J. Holzer" <> wrote:
    >
    > XC> When you deliberately pass refs to params, you must explicitly deref
    > XC> them inside the sub. Therefore, there is a bit of confusion involved
    > XC> when saying that Perl passes all params as refs. It's true; but a little
    > XC> bit deeper in the machinery, the ref is dereffed for you. That's
    > XC> probably an inexact statement but that's not the issue. As you say,
    > XC> Peter, it *is* call-by-ref, even if the syntax says you're just passing
    > XC> a scalar.
    >
    > ok, let's try to clear up some stuff. first off all sub args are passed by
    > alias, not exactly by ref.


    Here lies the terminological difficulty.

    Traditionally, two (or more) styles of parameter passing are
    distinguished: "by value", and "by reference", where "by reference"
    allows the routine to change a value for the calling program and
    "by value" does not. In this terminology, Perl's parameter passing
    is clearly "by reference". Unfortunately, "reference" has a distinct
    meaning in Perl terminology, and it is *not* the mechanism by which
    Perl manages parameter passing, though conceivably it could be.
    Instead, as you rightly say, Perl uses "aliasing" to realize its
    parameter passing "by reference".

    Terminology is that way.

    [good stuff snipped]

    Anno
    -berlin.de, Mar 31, 2007
    #19
  20. Re: Shifting Away

    In article <>,
    Uri Guttman <> wrote:

    > first off all sub args are passed by
    > alias, not exactly by ref.


    Yes. I think we can hammer at this distinction all night long without
    letting any more light into the room. I've tried to make it abundantly
    clear that an alias is not, as Perl defines it, a ref(erence). However,
    Perl does implement param passing via call-by-reference, generally
    speaking. Otherwise, it would not be possible to do anything within a
    sub that could clobber a param within the calling context.

    Somebody at this point might say that an evil demon might pass a param
    *value*, then look to see if $_[$i] had been changed and if so, go back
    and put the new value back in the old mailbox. I don't know anything
    about Perl internals but I'll bet a dollar to a doughnut that this is
    not the case. Rather, I'll bet that $_[$i] points directly to the
    mailbox itself. Please correct me if I'm wrong.

    At this, my chosen level of abstraction, there are only two ways to pass
    a param to a sub: call-by-reference or call-by-value. Perl does the
    former. Am I mistaken? If so, how?

    > it isn't deliberate or accidental,
    > but all the time.


    It is deliberate (on the part of the Perl maintainers) and it is all the
    time. When somebody writing code in Perl fails to understand this
    mechanism he may, by accident, screw up -- and if foolish, blame Perl,
    if wise, study and learn. When somebody who understands it makes
    deliberate use of it, he may thank Larry Wall, wisely, or compliment
    himself, foolishly.

    Have I finally and for all time covered these bases explicitly and
    without ambiguity? I wrote:

    > XC> (This distinction is important to me....)


    .... and so it is. It is crystal clear in my mind -- both that params are
    not automatically refs, as defined by Perl; and that @_ is a list of
    parameters that are passed by the mechanism of call-by-reference. One
    thing is not the other; I don't know how to make it any clearer. I've
    done my best and I'm sorry if I've still come up short.

    May the heavens guide the poor man who stumbles onto this thread,
    thinking about passing a Perl ref as a param. It certainly can be done
    (and often is) and this has nothing to do with the alias nature of @_.

    > @_ aliases are not refs. you
    > think that because they refer to the original
    > value that this is pass by reference but it is
    > not the same as most times you copy the args and
    > then they become pass by value.


    If you copy the value, that doesn't make the calling mechanism
    call-by-value. A language that implements parameter passing via
    call-by-value will not (by default) pass anything to the sub that will
    allow it to modify anything outside the sub (except, perhaps, global
    variables and a return value, neither of which are enabled by the
    parameter passing mechanism). That is:

    use pseudocode;

    sub foo (whang:integer) {
    whang = 47;
    };

    main {

    counter = 1;
    foo (counter);
    print counter;

    };

    .... will print 1, not 47. It *has* to print 1, because foo just does not
    have any way at all to get *at* counter. When foo wakes up, it sees the
    value 1 in whang, which it can use or ignore but cannot jimmy in any way
    to reach "beyond" and grab hold of counter.

    A language that implements pass-by-reference will print 47. That's all;
    there is no in-between. An alias is a high-level abstraction that
    encapsulates a reference -- not a Perl ref, not something that can be
    interpreted as a Perl ref or explicitly dereffed. An alias is implicitly
    dereffed when used.

    Let me say again (in case it helps) that my primary orientation is way
    down the ladder. When a sub invokes in most languages, it pops its
    params off the stack. Now, at the moment of the pop, that word popping
    off the stack is either the value that the calling routine had in "mind"
    when deciding to call the sub; or that popped word is a pointer into the
    heap or possibly another part of the stack, at which location the actual
    value is found. The first case is call-by-value; the second
    call-by-reference.

    > ... you must come to an understanding
    > of the actual topic first before
    > you flame away and babble incoherently.


    I believe I understand *this* point as clearly as possible; that leaves
    a great deal of room for my education.

    I've read others of this gentleman's posts and while it's not clear to
    me whether he knows his stuff or not, he *seems* to me to lean rather
    hard into other posters who don't appear to speak his language, his way.
    Either way, I certainly don't want to insult him -- or anyone else. Yet
    I would appreciate being allowed the same courtesy and I'm afraid I'm
    not going to get it.

    Am I right, in which case I should from now on ignore him? Or am I a
    babbling fool? I leave it to the group to set me straight.
    --
    Xiong Changnian
    xiong102ATxuefangDOTcom

    --
    Posted via a free Usenet account from http://www.teranews.com
    Xiong Changnian, Apr 1, 2007
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?QmlsbCBCb3Jn?=

    Need "get" accessor to return property name

    =?Utf-8?B?QmlsbCBCb3Jn?=, Oct 26, 2004, in forum: ASP .Net
    Replies:
    4
    Views:
    400
    =?Utf-8?B?QmlsbCBCb3Jn?=
    Oct 26, 2004
  2. Leon
    Replies:
    4
    Views:
    406
  3. =?Utf-8?B?TWljaGHFgiBKYW51c3pjenlr?=

    DataView data accessor aware of sorting used

    =?Utf-8?B?TWljaGHFgiBKYW51c3pjenlr?=, Nov 22, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    379
    =?Utf-8?B?TWljaGHFgiBKYW51c3pjenlr?=
    Nov 22, 2004
  4. -
    Replies:
    3
    Views:
    330
  5. -
    Replies:
    2
    Views:
    328
Loading...

Share This Page