Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

running unknown methods

by markcsmith (Novice)
on Oct 03, 2002 at 22:39 UTC ( #202662=perlquestion: print w/replies, xml ) Need Help??

markcsmith has asked for the wisdom of the Perl Monks concerning the following question:

Monk-o-ramas, I've had great experience (2 for 2) finding answers to my questions here, so I thought I'd say thanks first of all for helping me out before. Now, the present question. I'm trying to write a method that will go through the current object (hash) and execute all methods that begin with the '_' character. This is what I have:
sub runTests { my ($self) = @_; foreach $symname (sort keys %{$self}::) { local *sym = ${$self}::{$symname}; &$symname if ((definined &sym) && ($symname =~ /_\.*/)); } } # sub runTests
I saw this example in the camel book, but Larry (or Tom or that other guy), had access to the name of the hash, where I don't (well, I'm sure I do, but I don't know how to get it) since I'm inside of an object that hasn't been created yet. I'm getting an error that says: Bad name after :: at line 68 (line 68 has the foreach in it) when I run 'perl -c' ] Thanks in advance! Mark

Replies are listed 'Best First'.
Re: running unknown methods
by elusion (Curate) on Oct 03, 2002 at 23:29 UTC
    I'm a little confused as to what you are asking. I can tell that you're getting that error because you have the :: after your dereferenced hashref though. Do you want to call all the defined methods that begin with a "_" from the class of your object? I believe you would do that like so:
    sub runTests { my ($self) = @_; my $ref = ref $paragraph; foreach $symname (sort keys %{"${ref}::"}) { next unless defined $symname; next unless $symname =~ /^.+::(_[^:]+)$/; $self->$1(); } } # sub runTests
    The first thing I changed was the foreach. The hash you were getting the keys from was the object itself. If I understand you correctly, you want the symbol table for the class/package, which is what I put. (ref will return the object's class)

    If, on the other hand, you have stored all the methods you want to call inside of your object, take out the %{"${ref}::"} and replace it with %{$self}

    Second, I moved the tests to the front. There's no need to assign something if you're not gonna use it. I also changed your regex. This makes sure that it's testing after the last :: in case you have a subclass like My::Module.

    Lastly, I didn't assign via a typoglob (*). Instead, I saved the method name from the regex and executed it as a method of the originating object. You were calling it as a subroutine, which, if I understand you right, you didn't want to do.

    I hope I understood you correctly and that this helps. All of this code is untested however, so I can't guarentee that it works.

    elusion :

    Update: I forgot to mention that if you're trying to do this and your object inherits from another class, you won't have access to the parent class's methods, because those are stored in the parent's namespace.

    Update: I had to change the symbol table hashref. I don't dabble in the symbol table too much, sorry.

Re: running unknown methods
by Ovid (Cardinal) on Oct 03, 2002 at 23:45 UTC

    Try as I might, but I can't figure out why you want to do this. Rather than guess, I'll just provide you with a working example that should point you on the right path.

    #!/usr/bin/perl -w use strict; package Foo; sub new { bless { _this => "this\n", _that => "that\n" }, shift } sub _this { print $_[0]->{_this} } sub _that { print $_[0]->{_that} } package main; my $thing = Foo->new; runTests( $thing ); sub runTests { my $object = shift; my $pkg = ref $object; no strict 'refs'; foreach my $symname (keys %{"${pkg}::"}) { my $sub = "${pkg}::$symname"; if ( defined &$sub and '_' eq substr $symname, 0, 1 ) { $sub->( $object ); # explicitly pass $object to mimic meth +od call } } }


    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: running unknown methods
by sauoq (Abbot) on Oct 04, 2002 at 00:03 UTC

    I don't think I'd really recommend it but I think you are trying to do something like this:

    #!/usr/bin/perl -w use strict; package Foo; sub new { bless { "_foo", 1, "_bar", 1, "_qux", 1 } } sub runTests { my ($self) = @_; for my $symname (sort keys %{$self}) { local *sym = ref($self)."::$symname"; &sym if defined(&sym) and $symname =~ /^_.*/; } } # sub runTests sub _foo { print "_foo called\n" } sub _bar { print "_bar called\n" } package main; my $foo = Foo->new(); $foo->runTests();

    There are a couple of issues with that approach though. One of which is that the subs won't be called as methods at all. They'll be invoked as regular old subroutine calls. The other issue is that it doesn't take inheritance into account. A better approach might be something like:

    sub runTests { my ($self) = @_; for my $symname (sort keys %$self) { next unless $symname =~ /^_/; $self->$symname() if $self->can($symname); } }

    I think that's somewhat more readable as well. It depends on exactly what behavior you want too.

    Update: After seeing some of the other posts it looks like you are actually trying to walk the symbol table of the package the object is blessed into and then to call each of those methods on the object. With that in mind, that second sub would look more like this:

    sub runTests3 { my ($self) = @_; no strict 'refs'; for my $symname (sort keys %{ref($self).'::'}) { next unless $symname =~ /^_/; $self->$symname() if $self->can($symname); } }
    "My two cents aren't worth a dime.";
Re: running unknown methods
by rbc (Curate) on Oct 03, 2002 at 23:21 UTC
    I don't I really understand what you are trying to do
    but I have found that Data::Dumper is our friend.
    And is a great tool for debug hash problems.

    Side question ... how do you know what paramters to pass
    the methods you are going to call?
      Thanks for the reply. To answer your question, this class has a prerequisite that all methods are called w/o parameters. Yeah, horrible programming, but this code is being written soley for my purposes, and not to be used by others. Mark

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://202662]
Approved by moxliukas
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (6)
As of 2021-10-27 18:47 GMT
Find Nodes?
    Voting Booth?
    My first memorable Perl project was:

    Results (94 votes). Check out past polls.