Implicit iterator variable $_ changing to ### upon variable assignment?

Discussion in 'Perl Misc' started by Derek Basch, Aug 11, 2006.

  1. Derek Basch

    Derek Basch Guest

    Hello all,

    I have ran into a very confusing problem and I hoped someone could help
    me. This function is supposed to return a hash of the accessors and
    their associated values for a given class.


    ------------------------------------------
    package Test;

    sub accessors_values {
    my $self = shift;
    my %accessors_values;

    foreach $_ ($self->accessors()) {
    print "$_\n";
    my $value = $self->_accessor_class($_)->get($_);
    print "$_ : $value\n";
    }
    return %accessors_values;
    }

    .........

    ------------------------------------------

    Gives this output:
    ------------------------------------------
    password
    ### : carefree
    user_id
    ### : 323227
    first_login
    ### : 2006.08.08.12.47.13
    last_login
    ### : 2006.08.08.12.47.13
    ------------------------------------------

    Where the heck is the '###' coming from? How is assigning a value to
    the $value variable causing the implicit iterator variable $_ to become
    '###' ?

    The functions that the code calls are large so I will give a synopsis
    of what they return:

    $self->accessors returns an array of accessor names
    $self->_accessor_class returns a hash ref to a class
    $self->get returns a scalar value

    Any help is greatly appreciated.

    Thanks,
    Derek Basch
     
    Derek Basch, Aug 11, 2006
    #1
    1. Advertising

  2. Derek Basch

    Derek Basch Guest

    Derek Basch wrote:
    > Hello all,
    >
    > I have ran into a very confusing problem and I hoped someone could help
    > me. This function is supposed to return a hash of the accessors and
    > their associated values for a given class.
    >
    >
    > ------------------------------------------
    > package Test;
    >
    > sub accessors_values {
    > my $self = shift;
    > my %accessors_values;
    >
    > foreach $_ ($self->accessors()) {
    > print "$_\n";
    > my $value = $self->_accessor_class($_)->get($_);
    > print "$_ : $value\n";
    > }
    > return %accessors_values;
    > }
    >
    > ........
    >
    > ------------------------------------------
    >
    > Gives this output:
    > ------------------------------------------
    > password
    > ### : carefree
    > user_id
    > ### : 323227
    > first_login
    > ### : 2006.08.08.12.47.13
    > last_login
    > ### : 2006.08.08.12.47.13
    > ------------------------------------------
    >
    > Where the heck is the '###' coming from? How is assigning a value to
    > the $value variable causing the implicit iterator variable $_ to become
    > '###' ?
    >
    > The functions that the code calls are large so I will give a synopsis
    > of what they return:
    >
    > $self->accessors returns an array of accessor names
    > $self->_accessor_class returns a hash ref to a class
    > $self->get returns a scalar value
    >
    > Any help is greatly appreciated.
    >
    > Thanks,
    > Derek Basch


    I answered my own question. The implicit iterator was apparently being
    set to "##" by one of the functions that I called from within the sub.
    I didn't realize that it could be affected in such a way. Live and
    learn I guess.

    Thanks Anyways,
    Derek Basch
     
    Derek Basch, Aug 11, 2006
    #2
    1. Advertising

  3. Derek Basch

    Derek Basch Guest

    Derek Basch wrote:
    > Derek Basch wrote:
    > > Hello all,
    > >
    > > I have ran into a very confusing problem and I hoped someone could help
    > > me. This function is supposed to return a hash of the accessors and
    > > their associated values for a given class.
    > >
    > >
    > > ------------------------------------------
    > > package Test;
    > >
    > > sub accessors_values {
    > > my $self = shift;
    > > my %accessors_values;
    > >
    > > foreach $_ ($self->accessors()) {
    > > print "$_\n";
    > > my $value = $self->_accessor_class($_)->get($_);
    > > print "$_ : $value\n";
    > > }
    > > return %accessors_values;
    > > }
    > >
    > > ........
    > >
    > > ------------------------------------------
    > >
    > > Gives this output:
    > > ------------------------------------------
    > > password
    > > ### : carefree
    > > user_id
    > > ### : 323227
    > > first_login
    > > ### : 2006.08.08.12.47.13
    > > last_login
    > > ### : 2006.08.08.12.47.13
    > > ------------------------------------------
    > >
    > > Where the heck is the '###' coming from? How is assigning a value to
    > > the $value variable causing the implicit iterator variable $_ to become
    > > '###' ?
    > >
    > > The functions that the code calls are large so I will give a synopsis
    > > of what they return:
    > >
    > > $self->accessors returns an array of accessor names
    > > $self->_accessor_class returns a hash ref to a class
    > > $self->get returns a scalar value
    > >
    > > Any help is greatly appreciated.
    > >
    > > Thanks,
    > > Derek Basch

    >
    > I answered my own question. The implicit iterator was apparently being
    > set to "##" by one of the functions that I called from within the sub.
    > I didn't realize that it could be affected in such a way. Live and
    > learn I guess.
    >
    > Thanks Anyways,
    > Derek Basch


    Note that the way I found this error was by trying to do this:

    %accessors_values = map { $iter =>
    $self->_accessor_class($iter)->get($iter) } $self->accessors();

    The foreach above was my attempt to break the problem into smaller
    units for testing.
    So, you can solve this problem by not using the implicit iterator with
    a foreach loop.

    What I didn't mention was that the get function above uses a "while
    <FILEHANDLE>"
    loop. The "while <FILEHANDLE>" loop uses an implicit iterator and the
    map function also uses an implicit iterator.

    So, if you use map with an EXPR that uses the "while <FILEHANDLE>"
    idiom the map implicit iterator value will be replaced with the "while
    <FILEHANDLE>" implicit iterator value. You must use foreach instead of
    map.

    I hope that helps someone in the future :)

    Derek Basch
     
    Derek Basch, Aug 11, 2006
    #3
  4. Derek Basch

    Derek Basch Guest

    Michele Dondi wrote:
    > On 11 Aug 2006 13:34:56 -0700, "Derek Basch" <> wrote:
    >
    > > foreach $_ ($self->accessors()) {
    > > print "$_\n";
    > > my $value = $self->_accessor_class($_)->get($_);

    > ^^ ^^
    > ^^ ^^
    >
    > [snip]
    >
    > >$self->accessors returns an array of accessor names

    >
    > So far so fine.
    >
    > >$self->_accessor_class returns a hash ref to a class

    >
    > Which happens to be... what?!?


    A subclass of Class::Accessor.

    > And what does it expect as an argument?


    An accessor name.

    >
    > >$self->get returns a scalar value

    >
    > And what does it expect as an argument?


    An accessor name.

    > But most importantly in the code above get() is not a method of $self,
    > but of the object _accessor_class($_).


    Yes, $self is an aggregated class and the get methods are different for
    each aggregated class.

    Class_B <---has a---$self----has a---> Class_A
    | |
    v v
    sub get() sub get()

    > All in all it seems *strange*, although not strictly impossible, that
    > you want to pass $_ to both methods above.


    $self uses the name of the accessor (_accessor_class) to determine
    which aggregated class has the proper get function. get takes the
    accessor name to know which value to get.

    > Also the fact that
    > accessors() returns an array of accessor names suggest that you are
    > fiddling with symrefs. You may return proper $method refs, and call
    > them like thus instead:
    >
    > my $value = $self->$method(...);


    I suppose calling:

    get('accessor_name')

    is essentially like using a symref but I think this is what would be
    what would be considered a true symref call:

    foreach $_ ($self->accessors()) {
    my $value = $self->_accessor_class($_)->$_;
    }

    The only other way I can think of to handle this would be to return a
    hash of method references from the accessors() function:

    foreach $_ ($self->accessors()) {
    my $value = $self->_accessor_class($_)->{'$_'};
    }

    and isn't that exactly what a class hash reference is in Perl?

    I apologize for not being verbose enough with my example but I didn't
    want to put 300 lines of code in my message. 300 lines would have been
    the concise version too.

    Thanks for the help,
    Derek Basch





    OkbridgeDatabase::Gps->mk_accessors(OkbridgeDatabase::Gps->accessors());

    sub accessors {
    my @accessors = (
    'password',
    'user_id',
    'first_login',
    'last_login',




    >
    > To make a long story short: hard to say anything without looking at
    > the rest of your code. So, as usual, may you prepare a suitable
    > minimal but complete example exhibiting the problem? Also you'd better
    > state more clearly what you're actually trying to do.
    >
    >
    > Michele
    > --
    > {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    > (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    > .'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    > 256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
     
    Derek Basch, Aug 11, 2006
    #4
  5. Derek Basch

    Mumia W. Guest

    On 08/11/2006 04:22 PM, Derek Basch wrote:
    > Derek Basch wrote:
    >> Derek Basch wrote:
    >>> Hello all,
    >>>
    >>> I have ran into a very confusing problem and I hoped someone could help
    >>> me. This function is supposed to return a hash of the accessors and
    >>> their associated values for a given class.
    >>>
    >>>
    >>> ------------------------------------------
    >>> package Test;
    >>>
    >>> sub accessors_values {
    >>> my $self = shift;
    >>> my %accessors_values;
    >>>
    >>> foreach $_ ($self->accessors()) {
    >>> print "$_\n";
    >>> my $value = $self->_accessor_class($_)->get($_);
    >>> print "$_ : $value\n";
    >>> }
    >>> return %accessors_values;
    >>> }
    >>>
    >>> ........
    >>>
    >>> ------------------------------------------
    >>>
    >>> Gives this output:
    >>> ------------------------------------------
    >>> password
    >>> ### : carefree
    >>> user_id
    >>> ### : 323227
    >>> first_login
    >>> ### : 2006.08.08.12.47.13
    >>> last_login
    >>> ### : 2006.08.08.12.47.13
    >>> ------------------------------------------
    >>>
    >>> Where the heck is the '###' coming from? How is assigning a value to
    >>> the $value variable causing the implicit iterator variable $_ to become
    >>> '###' ?
    >>>
    >>> The functions that the code calls are large so I will give a synopsis
    >>> of what they return:
    >>>
    >>> $self->accessors returns an array of accessor names
    >>> $self->_accessor_class returns a hash ref to a class
    >>> $self->get returns a scalar value
    >>>
    >>> Any help is greatly appreciated.
    >>>
    >>> Thanks,
    >>> Derek Basch

    >> I answered my own question. The implicit iterator was apparently being
    >> set to "##" by one of the functions that I called from within the sub.
    >> I didn't realize that it could be affected in such a way. Live and
    >> learn I guess.
    >>
    >> Thanks Anyways,
    >> Derek Basch

    >
    > Note that the way I found this error was by trying to do this:
    >
    > %accessors_values = map { $iter =>
    > $self->_accessor_class($iter)->get($iter) } $self->accessors();
    >
    > The foreach above was my attempt to break the problem into smaller
    > units for testing.
    > So, you can solve this problem by not using the implicit iterator with
    > a foreach loop.
    >
    > What I didn't mention was that the get function above uses a "while
    > <FILEHANDLE>"
    > loop. The "while <FILEHANDLE>" loop uses an implicit iterator and the
    > map function also uses an implicit iterator.
    >
    > So, if you use map with an EXPR that uses the "while <FILEHANDLE>"
    > idiom the map implicit iterator value will be replaced with the "while
    > <FILEHANDLE>" implicit iterator value. You must use foreach instead of
    > map.
    >
    > I hope that helps someone in the future :)
    >
    > Derek Basch
    >


    Indeed it probably will; it'll remind people to use local ;-)

    #!/usr/bin/perl

    package Tryit;
    use strict;
    use warnings;

    my @fun = map { get(); $_ } (1..4);
    print "@fun\n";

    sub get {
    # What happens when you comment out the "local"
    # below?
    local $_;
    while (<DATA>) {
    last if /###/;
    }
    }

    __DATA__
    nothing here
    ### more hash marks ###
     
    Mumia W., Aug 12, 2006
    #5
  6. Derek Basch

    Ben Morrow Guest

    Quoth Michele Dondi <>:
    > On 11 Aug 2006 13:34:56 -0700, "Derek Basch" <> wrote:
    >
    > you want to pass $_ to both methods above. Also the fact that
    > accessors() returns an array of accessor names suggest that you are
    > fiddling with symrefs.


    Methods are looked up by name at runtime, so they're effectively symrefs
    anyway.

    > You may return proper $method refs, and call
    > them like thus instead:
    >
    > my $value = $self->$method(...);


    ....but whay would be the advantage in doing so, except in rather weird
    circumstances?

    Ben

    --
    Although few may originate a policy, we are all able to judge it.
    Pericles of Athens, c.430 B.C.
     
    Ben Morrow, Aug 12, 2006
    #6
  7. Derek Basch

    Uri Guttman Guest

    Re: Implicit iterator variable $_ changing to ### upon variableassignment?

    >>>>> "MW" == Mumia W <> writes:

    MW> On 08/11/2006 04:22 PM, Derek Basch wrote:

    >> Note that the way I found this error was by trying to do this:
    >> %accessors_values = map { $iter =>
    >> $self->_accessor_class($iter)->get($iter) } $self->accessors();
    >> The foreach above was my attempt to break the problem into smaller
    >> units for testing.
    >> So, you can solve this problem by not using the implicit iterator with
    >> a foreach loop.
    >> What I didn't mention was that the get function above uses a "while
    >> <FILEHANDLE>" loop. The "while <FILEHANDLE>" loop uses an implicit
    >> iterator and the map function also uses an implicit iterator.
    >> So, if you use map with an EXPR that uses the "while <FILEHANDLE>"
    >> idiom the map implicit iterator value will be replaced with the
    >> "while <FILEHANDLE>" implicit iterator value. You must use foreach
    >> instead of map.
    >> I hope that helps someone in the future :)
    >> Derek Basch
    >>


    MW> Indeed it probably will; it'll remind people to use local ;-)

    better if it reminds people to not use $_ all the time. with loops it is
    much better to use a lexical var and then you never can have anything
    like this happen. and your code becomes easier to read as you have a
    named variable for each loop and it is lexical and never is seen by any
    called subs or maps.

    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, Aug 12, 2006
    #7
  8. Derek Basch

    Derek Basch Guest


    > It seems that in the end you're more knowledgeable than I am, because
    > as above I don't have the slightest idea of what a "class hash
    > reference" could be. A class is a package. The only hash that comes to
    > mind speaking of the latter, is its stash. Or else objects are often
    > implemented by means of blessed hash references "containing" the data,
    > but that's just one implementation choice. In any case I'm not really
    > sure about what you're talking about and I must be missing something,
    > sorry!



    I guess I should read up more on the differences between a package
    stash and blessed hash references as objects. I had been thinking they
    were the same thing but apparently they are not.

    Thanks for the help everyone,
    Derek Basch
     
    Derek Basch, Aug 12, 2006
    #8
  9. Derek Basch

    Ben Morrow Guest

    [please attribute quotes]

    Quoth "Derek Basch" <>:
    > Michele Dondi <> wrote:
    > >
    > > It seems that in the end you're more knowledgeable than I am, because
    > > as above I don't have the slightest idea of what a "class hash
    > > reference" could be. A class is a package. The only hash that comes to
    > > mind speaking of the latter, is its stash. Or else objects are often
    > > implemented by means of blessed hash references "containing" the data,
    > > but that's just one implementation choice. In any case I'm not really
    > > sure about what you're talking about and I must be missing something,
    > > sorry!

    >
    > I guess I should read up more on the differences between a package
    > stash and blessed hash references as objects. I had been thinking they
    > were the same thing but apparently they are not.


    Don't worry about package stashes: they are an advanced topic that
    you'll likely never need to worry about. The source of Michele's
    confusion is that you are mixing up the terms 'class' and 'object'. What
    you meant to say instead of 'a class hash reference' was 'a reference to
    an object' or 'a reference to a blessed hash'. The former is preferable
    as the fact that the object is implemented as a blessed hash is not (or
    should not be) important to users of that object.

    A class is a type of object. It is represented in Perl by its name,
    either as a string or as a bareword. So in

    my $fb = Foo::Bar->new;

    'Foo::Bar' is a class. The ->new method will be passed the string
    'Foo::Bar' as its first argument.

    An object is an instance of a class: that is, an object is to a class as
    '1' is to 'the integers'. If ->new in the above is a normal constructor,
    then $fb will hold a reference to an object. Objects in Perl can only be
    accessed through references to them.

    An object responds to certain methods: these are defined in the class in
    class-based OO systems (which Perl's is, usually). However, it is
    important to realize that calling a method on an object and calling it
    on the class are quite different operations; most methods can only be
    called on one or the other.

    Ben

    --
    Musica Dei donum optimi, trahit homines, trahit deos. |
    Musica truces mollit animos, tristesque mentes erigit.|
    Musica vel ipsas arbores et horridas movet feras. |
     
    Ben Morrow, Aug 12, 2006
    #9
    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. George
    Replies:
    6
    Views:
    2,626
    George
    Feb 4, 2005
  2. bb
    Replies:
    3
    Views:
    1,703
    peter koch
    Apr 30, 2007
  3. David Bilsby
    Replies:
    5
    Views:
    2,052
    David Bilsby
    Oct 9, 2007
  4. BillGatesFan
    Replies:
    1
    Views:
    447
    Nathan Sokalski
    Feb 15, 2008
  5. Simon Strandgaard

    RAA-stream implicit iterator maybe offbyone ?

    Simon Strandgaard, Sep 14, 2003, in forum: Ruby
    Replies:
    2
    Views:
    164
    Simon Strandgaard
    Sep 17, 2003
Loading...

Share This Page