Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

How can I re-program the exists function?

by greengaroo (Hermit)
on Aug 24, 2012 at 14:06 UTC ( #989548=perlquestion: print w/ replies, xml ) Need Help??
greengaroo has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

I have a good question for you.

Lets say I want to re-program the "exists" function. Of course, that is not my end goal, but I will use this as an example because it will be easier to explain.

Consider this module:

package MyExists; use Exporter qw( import ); @EXPORT = qw(my_exists); sub my_exists { my ($string) = @_; if ( eval("exists($string)") ) { return "Yes!"; } else { return "No!"; } } 1;

Now this script:

use MyExists qw(my_exists); my %hash = ( 'test1' => 'value1', 'test2' => 'value2' ); print "Real exists: "; print exists( $hash{'test1'} ); print "\n"; print "My exists: "; print my_exists( $hash{'test1'} ); print "\n"; print "Real exists: "; print exists( $hash{'test3'} ); print "\n"; print "My exists: "; print my_exists( $hash{'test3'} ); print "\n";

The result is:

Real exists: 1 My exists: No! Real exists: My exists: No!

Now, my real question is: How can you create a function that would act like the "exists" function? In other words, I need to build a function that is able to receive an expression and not a value (like "my_exists" actually does). According to perldoc, "exists" receives and "EXPR". How can I do that myself?

If I pass '$hash{"test1"}' as a string, then I could probably evaluate it right? Wrong! My function doesn't know what $hash is because its not declared in the Module!

I started to look at the prototypes for subroutines and I didn't find a solution. No luck with Google either.

I have a workaround. In short, I pass two arguments, first the HashRef: \%hash, then the string: '$hash{"test1"}'. It works but I would really like to know how to do it the "exists" way .

Thank you!

There are no stupid questions, but there are a lot of inquisitive idiots.

Comment on How can I re-program the exists function?
Select or Download Code
Re: How can I re-program the exists function?
by moritz (Cardinal) on Aug 24, 2012 at 14:24 UTC
    Now, my real question is: How can you create a function that would act like the "exists" function?

    I'd be happy to be proven wrong, but I'd say you can't. At least not in pure Perl. Maybe with XS code when you hook into the parser.

    In some cases you can tie variables, in which exists will call your EXISTS method. But depending on what you actually want to achieve, that might not be a good solution.

    So, in the spirit of XY Question, what is the larger problem your are trying to solve?

      Well, as I said it was easier to explain using the exists example, but basically, my goal is to test an entry from a hashref, these entries contains objects and I wanted to create a generic function that receive a hashref path (just like the build-in exists function do) then test if the entry exists (using exists) then do some more tests on the object if it exists. I am able to do it with a workaround, it's just that I wanted to be fancy and be able to send only on parameter to my function, instead of two, like I am doing now.

      I hope this explanation is clear enough. I cannot get into more details and I don't want to start a "why-don't-you-do-this-instead" thread, I just wanted to know if it was possible to emulate the exists function.

      Thanks very much for your reply!

      There are no stupid questions, but there are a lot of inquisitive idiots.
        my goal is to test an entry from a hashref, these entries contains objects

        A reference to an object can't be undef() or even false (unless you do some strange overloading) so what you want is trivial:

        mytest( $hash{object} || '' ); sub mytest { my( $obj ) = @_; return if ! $obj; }

        The "|| ''" is there just to ensure that autovivification doesn't happen. I believe current versions of Perl actually avoid autovivification for this case if you don't assign to $_[0] in the mytest sub, but that's the kind of detail that is subject to change so I tend to "play it safe" on such issues.

        - tye        

Re: How can I re-program the exists function?
by cheekuperl (Monk) on Aug 24, 2012 at 14:31 UTC
    I am not sure about what exactly you are trying to achieve. However, your statement
    According to perldoc, "exists" receives and "EXPR".
    seems only half correct.
    See expr.
    It says
    Note that the EXPR can be arbitrarily complicated as long as the final operation is a hash or array key lookup or subroutine name
Re: How can I re-program the exists function?
by BrowserUk (Pope) on Aug 24, 2012 at 14:32 UTC

    In a nutshell, you can't.

    In the same way, you cannot program your own expression form of map or grep (eg. @squares = map $_**2, 1 .. 10;).

    Many of perl's built-ins cannot be directly emulated with Perl code.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    The start of some sanity?

Re: How can I re-program the exists function?
by tobyink (Abbot) on Aug 24, 2012 at 15:35 UTC

    I think the closest you could get would be to create your my_exists function taking a separate hashref and string as you already have, then use something like Devel::Declare or Devel::CallParser (perhaps coupled with PPI) to hook into the Perl compiler and translate this:

    my_exists($hash{key})

    to this during the parse/compile stage:

    my_exists(\%{hash}, 'key')

    It's not an easy task though.

    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

      t's not an easy task though.

      See Method::Signatures , it looks easy enough to copy that :)

      Thanks, but I don't think it's worth it. It is not that important since I managed to make it work.

      There are no stupid questions, but there are a lot of inquisitive idiots.
Reaped: Re: How can I re-program the exists function?
by NodeReaper (Curate) on Aug 25, 2012 at 04:38 UTC

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (8)
As of 2014-12-27 12:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (177 votes), past polls