Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Iterating over *any* thing in Perl

by Schemer (Scribe)
on Dec 03, 2002 at 05:57 UTC ( #217134=perlquestion: print w/ replies, xml ) Need Help??
Schemer has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,

In a post in 'Meditations', John M. Dlugosz made a claim (that I would believe might be true) about how ``in Perl 5 the contents of anything can be inspected and iterated.''.

So I was wondering how can one iterates over the content of an object? What's the general function to access each field of an object and look for uninitialised value for exemple?

And also, it there a way to iterate over the content of a closure? Like if I'd want to kill intern references to outside objects or something?

This might be more a 'language' question than a practical one...

Thanks in advance for any insights!

Comment on Iterating over *any* thing in Perl
Re: Iterating over *any* thing in Perl
by pg (Canon) on Dec 03, 2002 at 06:25 UTC
    Object is nothing more than a blessed data structure, i.e. a hash or an arrary etc. (A hash of hash of hash is still a hash at each particular level, so we are dealing with no more than scalar, array/list and hash)

    Basically, in order to be able to iterate over a data structure, you only need two things to support you:
    1. A way to determine what the data structure is, and this is not a big deal, as we have the isa function/method. Not just to recognize hash, array etc., you can actually even determine whether it is regexp, code, REF...

      Data Dumper is one of those kind of tools that can iterate over any given data structure. But it only does some pre-determined 'hard-coded' thing for you, for example, to dump the content of the data structure.

    2. A general purpose 'iterator' should allow the user to define call-back functions, so its functionality can be extended by the user. For example, those HTML, or XML parsers support call-back functions.
      Just ignore, I don't play the semantics game well (you're right)
      use anal::retentive;
      Except that it's not. An object is nothing more than a blessed reference, not data structure. Observe:
      my %foo = (1,2,3,4); bless %boo,'bar'; __END__ Can't bless non-reference value at - line 2.
      Now you know I like to quote ;) from perldoc -f bless
      bless REF,CLASSNAME
      bless REF
              This function tells the thingy referenced by REF that it is now
              an object in the CLASSNAME package. If CLASSNAME is omitted, the
              current package is used. Because a "bless" is often the last
              thing in a constructor, it returns the reference for
              convenience. Always use the two-argument version if the function
              doing the blessing might be inherited by a derived class. See
              the perltoot manpage and the perlobj manpage for more about the
              blessing (and blessings) of objects.
      
              Consider always blessing objects in CLASSNAMEs that are mixed
              case. Namespaces with all lowercase names are considered
              reserved for Perl pragmata. Builtin types have all uppercase
              names, so to prevent confusion, you may wish to avoid such
              package names as well. Make sure that CLASSNAME is a true value.
      
              See the section on "Perl Modules" in the perlmod manpage.
      
      update: hmm, it's a weird thing, the datastructure is "blessed", but only the reference knows, weird


      MJD says you can't just make shit up and expect the computer to know what you mean, retardo!
      ** The Third rule of perl club is a statement of fact: pod is sexy.

Re: Iterating over *any* thing in Perl
by Ovid (Cardinal) on Dec 03, 2002 at 06:29 UTC

    Typically (not always), you can inspect the contents of anything, but that depends upon how you define "contents". For example, what do you mean when you say "the content of a closure"? If you wanted, as I believe you were describing, to remove an internal reference to an external object, then you would probably just undef the scalar holding the reference to the closure or have the closure internally undef an unnecessary reference. There's no way (and no need) to peer inside. As for objects, are you referring to a need to iterate over what data structure has been blessed? You can bless hash references, an array references and those are easy to iterate over. However, how would you "iterate" over a code reference or a regex that's been blessed?

    As for a general function to access each field of an object, there isn't one. This is something that is (and should be!) handled inside of the object's class and is based upon the needs of that particular object. For example, I once found a solution to a thorny problem by blessing integers. One doesn't typically iterate over a single value if you know it's always a single value.

    Cheers,
    Ovid

    New address of my CGI Course.
    Silence is Evil (feel free to copy and distribute widely - note copyright text)

Re: Iterating over *any* thing in Perl
by BrowserUk (Pope) on Dec 03, 2002 at 06:48 UTC

    Data::Dumper does a pretty good job.

    Writing your own code to do something similar isn't much harder.


    Okay you lot, get your wings on the left, halos on the right. It's one size fits all, and "No!", you can't have a different color.
    Pick up your cloud down the end and "Yes" if you get allocated a grey one they are a bit damp under foot, but someone has to get them.
    Get used to the wings fast cos its an 8 hour day...unless the Govenor calls for a cyclone or hurricane, in which case 16 hour shifts are mandatory.
    Just be grateful that you arrived just as the tornado season finished. Them buggers are real work.

      Data::Dumper does a pretty good job.

      No it doesn't. It'll fail on:

      package Pet; my (%colour, %name, %species); sub new {bless [] => shift} sub colour : lvalue {$colour {+shift}}; sub name : lvalue {$name {+shift}}; sub species : lvalue {$species {+shift}}; sub DESTROY { my $self = shift; delete $colour {$self}; delete $name {$self}; delete $species {$self}; } 1; __END__

      There's no way you can get to the attributes from the outside, other than using the interface. And that's a feature, not a bug.

      Abigail

        Agreed. I guess you'd need to use Padwalker to get at those.

        And that's a feature, not a bug

        Also agreed. That's a much better way to implement private data.


        Okay you lot, get your wings on the left, halos on the right. It's one size fits all, and "No!", you can't have a different color.
        Pick up your cloud down the end and "Yes" if you get allocated a grey one they are a bit damp under foot, but someone has to get them.
        Get used to the wings fast cos its an 8 hour day...unless the Govenor calls for a cyclone or hurricane, in which case 16 hour shifts are mandatory.
        Just be grateful that you arrived just as the tornado season finished. Them buggers are real work.

Re: Iterating over *any* thing in Perl
by Abigail-II (Bishop) on Dec 03, 2002 at 11:32 UTC
    There is no such general function. And that's because there's no general way of creating an object. See, unlike normal languages, in Perl you have to do everything yourself when creating objects (which is very non-Perl). Some people use hashrefs or arrayrefs for their objects, and stuff all the attributes in the things the references point to (and those same people will vote '++' for if someone posts a coding guideline saying "Don't use global variables"). The advantage is that you can access the attributes all the time, from everywhere - the same advance as putting all your variables in main:: gives you.

    But people preferring lexical variables over global variables; who think that encapsulation is a good thing, who simply think that variables should be appropriately scoped, or that it's nice to be able to inherit a class without having to peek inside it to do it properly, will hide the attributes, making them unaccessable from the outside.

    So, no, you cannot do so.

    Abigail

      Some people use hashrefs or arrayrefs for their objects, and stuff all the attributes in the things the references point to (and those same people will vote '++' for if someone posts a coding guideline saying "Don't use global variables"). The advantage is that you can access the attributes all the time, from everywhere - the same advance as putting all your variables in main:: gives you.

      What would you recommend should be done instead?

        Some options (in no particular order):

        • Use a proper OO language ;-)
        • Wait for Perl 6
        • Use inside out objects (for me, the neatest discovery from perlmonks so far - ++Abigail-II).
        • Hide your objects implementation behind a proxy object (Class::Delegation is handy for this sort of thing).
        • Document that you use a hash. Document the slot(s) that you use. One idiom that I've seen a few times is to do it as $object->{CLASS_NAME}->{SLOT_NAME}

        Any more for any more?

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://217134]
Approved by krujos
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (5)
As of 2014-11-28 21:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (200 votes), past polls