Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Pass an optional parameter to a subroutine

by ocs (Monk)
on Sep 15, 2006 at 07:53 UTC ( [id://573061]=perlquestion: print w/replies, xml ) Need Help??

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

Hi folks, I have an apparant simple problem. I want to pass a parameter to a function, which toggles a behavior, e.g. to write to a database or not to write. Here an extraction:
#===================================================================== sub handleVoicemailNote { #===================================================================== my $ref_mail = shift; my $db_write = shift || 1;
I call the function this way:
handleVoicemailNote($mail, 0);
or this way:
handleVoicemailNote($mail);
That means, if $db_write is set to 1, it writes to the database. The parameter $db_write has not to be set, but the default has to be 1 (if it is not passed). But it does not work. It evaluates the parameter always as 1. It apparantly does not take the parameter as it is but evaluates the passed parameter. If it is 0, it behaves the same way as there is no given parameter. How can I get this thing working? I now got the solution that I pass text strings like "true" and "false" but this is unesthetic and not satisfying. Thanks for any answers!

2006-09-15 Retitled by Arunbear, as per Monastery guidelines
Original title: 'Pass a parameter'

Replies are listed 'Best First'.
Re: Pass an optional parameter to a subroutine
by robartes (Priest) on Sep 15, 2006 at 08:17 UTC

    You're being bitten by the fact that 0 is false, so if you pass 0 in $db_write, the shift || 1 sees false || 1 and you get 1.

    You will probably want to explicitely check for definedness instead:

    my $ref_mail = shift; my $db_write = shift; # If $db_write is defined, use that, otherwise default to 1 $db_write = defined($db_write)?$db_write:1;

    CU
    Robartes-

      Wow, thank you guys. That was really fast & you got my problem solved. Great community :)
Re: Pass an optional parameter to a subroutine
by davorg (Chancellor) on Sep 15, 2006 at 08:24 UTC

    This is exactly the kind of problem that the forthcoming "defined or" (//) operator is designed to deal with. If you're using the current development version of Perl (5.9) or when the next stable version (5.10) is released, you'll be able to write

    my $db_write = shift // 1;

    Instead of

    my $db_write = shift; $db_write = 1 unless defined $db_write;

    Actually, I think that currently I'd write your code like this

    my $ref_mail = shift; my $db_write = @_ ? shift : 1;
    --
    <http://dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

      If you're using the current development version of Perl (5.9) or when the next stable version (5.10) is released, you'll be able to write
      Or if you build a 5.8.x perl with the appropriate dor-* patch from http://perl.com/CPAN/authors/id/H/HM/HMBRAND/

      Actually, I'd write it like that last way even with the // operator. It's just a good habit to be in for cases where undef actually is a legitimate value. For example, in a standard get/set object method, knowing that nothing is passed in (read-only) is a very different case from undef being passed in (setting the value to undef). Of course, I can't see using the ternary operator in that precise situation, just that it's an easy way to see the difference between no parameter and undef as a parameter.

      Of course, there are times where I don't want undef as a valid value - but I want my use of // to be an explicit statement that undef isn't allowed rather than an unintentional default.

      Actually, I think that currently I'd write your code like this
      my $ref_mail = shift; my $db_write = @_ ? shift : 1;

      That's icky, as it means more to change if there are ever more parameters than just these two. I'd suggest:

      my $ref_mail = shift; my $db_write = defined $_[0] ? shift : 1;
      <radiant.matrix>
      A collection of thoughts and links from the minds of geeks
      The Code that can be seen is not the true Code
      I haven't found a problem yet that can't be solved by a well-placed trebuchet

        Exactly! What if someone sent in something like this?

        foo(undef, 1, 2);
        Then the @_ version would shift off the undef, which is not what is wanted, I think.

        Being contemplative
        -v.

        "Perl. There is no substitute."
Re: Pass an optional parameter to a subroutine
by svenXY (Deacon) on Sep 15, 2006 at 08:22 UTC
    Hi,
    quite simple indeed:
    my $db_write = shift || 1;
    means: give me the parameter and if it is false (and '0' is false), then set it to 1.
    You might try something like this (using defined instead of just checking for true/false):
    #!/usr/bin/perl use strict; use warnings; #===================================================================== sub handleVoicemailNote { #===================================================================== my ($ref_mail,$db_write) = @_; $db_write = 1 unless defined($db_write);

    Regards,
    svenXY
Re: Pass an optional parameter to a subroutine
by GrandFather (Saint) on Sep 15, 2006 at 08:20 UTC

    Consider:

    use warnings; use strict; my @lines; test ("No switch param:"); test ("Switch param is 0", 0); test ("Switch param is -1", -1); sub test { my $param1 = shift; my $switch = shift || 1; print $param1; print " - Switch = $switch\n"; }

    Prints:

    No switch param: - Switch = 1 Switch param is 0 - Switch = 1 Switch param is -1 - Switch = -1

    Note that 0 || 1 is 1.


    DWIM is Perl's answer to Gödel

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (8)
As of 2024-04-25 11:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found