Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Is it a scalar or a hash?

by DrZaius (Monk)
on May 13, 2001 at 21:39 UTC ( [id://80066]=perlmeditation: print w/replies, xml ) Need Help??

Good day, fellow patrons. I've been toying with this for every since I woke this morning. I was working on this problem before I went to bed.

Imagine you are writing code. Imagine you have a subroutine, foo(), that you think will only ever require one argument, ever.

You're code base is growing and growing. Soon, there are many calls to this mysterious subroutine.

One day, you realize your shortsightedness. You need to pass your subroutine a hash of data. A lot of stuff is using this subroutine and you don't want to break this code, or update it yet. Basically, too much uses the interface to change it.

One solution I've toyed with is creating a wrapper to the old subroutine with a bit of magic like this:

sub foo { return _foo_scalar(@_) if(@_==1); return _foo_hash(@_) unless(scalar(@_) % 2); }
Of course, java/c++ have built in answers for this, but you also have to use subroutine prototypes everywhere to accomplish this.

How do you elegantly solve this problem if foo() originally required 2 arguments?

Replies are listed 'Best First'.
Re (tilly) 1: Is it a scalar or a hash?
by tilly (Archbishop) on May 13, 2001 at 22:53 UTC
    My solution in the past has been either to write 2 functions or else to pull the following trick:
    sub foo { my %args = (1 == @_) ? (named_arg => shift) : @_; # etc }
    or pull it as follows:
    sub foo { my $args = shift; if (! ref($args)) { # <- test depends on usage $args = {named_arg => $args); } # etc }
    Now it can be called two ways. Internally that is turned into a hash of named arguments, and then I can proceed to supply defaults for whatever is missing.
Re: Is it a scalar or a hash?
by Masem (Monsignor) on May 13, 2001 at 22:20 UTC
    Try the function isa, as described in perlobj. The test would be
    sub foo { isa( $_[0], 'HASH' ) ? _foo_hash( $_[0] ) : _foo_scalar( $_[0] ); }

    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
      This is assuming you are passing in a hash ref instead of a hash. This is probably the better way of doing it anyway though, as you aren't passing a bunch of stuff around on each subroutine call.
        Polymorphism is generally less stressful if you are passing and polymorphing on references. There really is no uncludgy way to discriminate between a list of two items and a hash, if not passed by reference.
           MeowChow                                   
                       s aamecha.s a..a\u$&owag.print
      What if someone passes in a blessed scalar reference from the "HASH" class?
        Then they deserve a severe beating, for naming a class after a built-in datatype.
           MeowChow                                   
                       s aamecha.s a..a\u$&owag.print
Re: Is it a scalar or a hash?
by Beatnik (Parson) on May 13, 2001 at 21:54 UTC
    wantarray is pretty handy for scalar vs list testing...

    Greetz
    Beatnik
    ... Quidquid perl dictum sit, altum viditur.
      But wantarray is for use in calling context. Here, we are testing what has been passed in as arguments.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://80066]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (6)
As of 2024-04-18 20:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found