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

Hello all Monks

I've got a strange problem .. inside a sub I've declared a variable as my with three possible values ..

1. 'limit $nmbr1,$nmbr2'

2. 'limit $nmbr2'

3. not defined/false/null .. whatever ..

Here is the code.

sub get_all_artid_from_kategoriid { my ($self) = shift; my (%params) = @_; my $LIMIT = 'limit ' . $params{'limitantal'} if (($params{'lim +itantal'}) && (!$params{'limitstart'})); $LIMIT = 'limit ' . $params{'limitstart'} . "," . $params{' +limitantal'} if (($params{'limitantal'}) && ($params{'limitstart'})); my $ORDNING = " order by $params{'order'} " if ($params{'order'}); my $GROUP = " group by $params{'groupby'} " if ($params{'groupb +y'}); print STDERR "LIMIT = $LIMIT || limitantal = $params{'limitantal'} +\n"; . some other code..... . }

The problem is that if I call the sub without the values 'limitstart' and 'limitantal' the STDERR row prints out

LIMIT = limit 20,20 || limitantal =

NOW comes the strange part ,, atleast for me....

If I change the code like this.

. . my $LIMIT; $LIMIT = 'limit ' . $params{'limitantal'} if (($params{'limita +ntal'}) && (!$params{'limitstart'})); $LIMIT = 'limit ' . $params{'limitstart'} . "," . $params{' +limitantal'} if (($params{'limitantal'}) && ($params{'limitstart'})); . .

Then the STDERR row prints out the following.

LIMIT = || limitantal =

Which I think the first code-example would do too..

Any ideas?? Am I still to tired? .. (GMT+1 = 11.34am)

Best regards

Jocke, Sweden

Replies are listed 'Best First'.
Re: 'my' problems
by chb (Deacon) on May 23, 2005 at 10:16 UTC
    You've got a conditional tacked onto a my-declaration. This has rather unintuitive effects: it contructs a local static variable (in c-speak). This feature/bug is deprecated, and not what you want to do anyway, so you are safe to stick to your second version.
      Is this also true for ternary conditionals? I use stuff like
      my $var = $condition ? "a" : "b";
      all the time and never had any problems.


      holli, /regexed monk/
        I should be more specific, as dave_the_m below: you get problems if you use statement modifiers on a my. AFAIK the ternary conditional is an expression.
Re: 'my' problems
by dave_the_m (Monsignor) on May 23, 2005 at 10:17 UTC
    Don't use a statement modifier on a my declaration. It tickles a bug in perl which causes the my variable not to re-initialised at the next entry to the block.

    Dave.

Re: 'my' problems
by wazoox (Prior) on May 23, 2005 at 10:16 UTC
    Your code works perfectly for me. Check this :
    #!/usr/bin/perl use strict; use warnings; sub get_all_artid_from_kategoriid { my ($self) = shift; my (%params) = @_; my $LIMIT = 'limit ' . $params{'limitantal'} if (($params{'lim +itantal'}) && (!$params{'limitstart'})); $LIMIT = 'limit ' . $params{'limitstart'} . "," . $params{' +limitantal'} if (($params{'limitantal'}) && ($params{'limitstart'})); my $ORDNING = " order by $params{'order'} " if ($params{'order'}); my $GROUP = " group by $params{'groupby'} " if ($params{'groupb +y'}); print STDERR "LIMIT = $LIMIT || limitantal = $params{'limitantal'} +\n"; } my $toto=get_all_artid_from_kategoriid(1); # got limit= || limitantal= $toto=get_all_artid_from_kategoriid(1, 'limitantal', 20); # got limit=20 || limitantal=20 $toto=get_all_artid_from_kategoriid(1, 'limitantal', 20, 'limitstart', + 42 ); # got limit=42,20 || limitantal=20
Re: 'my' problems
by reasonablekeith (Deacon) on May 23, 2005 at 10:11 UTC
    ...The problem is that if I call the sub without the values 'limitstart' and 'limitantal' the STDERR row prints out ...

    LIMIT = limit 20,20 || limitantal =

    ... I'd be surprised if this it true, you must have something else strange going on. Can you post a working example which demonstrates this?

    ---
    my name's not Keith, and I'm not reasonable.

      Hi Keith

      Wrote a small program that will reproduce the problem.

      #!/usr/bin/perl my $limitstart = 20; my $limitantal = 20; strange_sub(limitstart => $limitstart, limitantal => $limitantal); strange_sub(); sub strange_sub { my (%params) = @_; my $string = 'limit ' . $params{'limitantal'} if ((!$params{'l +imitstart'}) && ($params{'limitantal'})); $string = 'limit ' . $params{'limitstart'} . ", " . $params{'l +imitantal'} if (($params{'limitstart'}) && ($params{'limitantal'})); print STDERR "limitstring = " . $string . "\n"; }

      /jocke

        I'm surprised. :-o

        You have your answers below, but I'd thought I'd post a simple example, which shows quite explictly that the 'my' does scope a variable, but doesn't re-initialise it if you have a conditional which evaluates to false.

        print count() . "\n"; print count() . "\n"; print count() . "\n"; sub count { my $counter = 'whatever' if 0; # declare local 'static' variable $counter++; } __OUTPUT__ 0 1 2

        PS. Don't actually do this though

        ---
        my name's not Keith, and I'm not reasonable.
{pun,ot} [was:"Re: 'my' problems"]
by blazar (Canon) on May 23, 2005 at 10:22 UTC
    Not our problem!
Re: 'my' problems
by jockel (Beadle) on May 23, 2005 at 10:31 UTC

    Thanks all!!

    That explain things!

    But it's strange that wazoox's example works .. it works for me too, so it's not a perl-version problem.

    Tried to mess up wazooxs example so that it produce the same errors but without any results ..

    Well.. the problem is solved.. now I must try to search through my code for ocurrences of this type, because I know this wasn't the first time I did like this.... *yawn*

    Thanks again!

    Regards

    Jocke

Re: 'my' problems
by mrpeabody (Friar) on May 23, 2005 at 22:06 UTC
    Others have correctly answered this question; here is the documentation for reference (perlsyn):

    NOTE: The behaviour of a "my" statement modified with a statement modifier conditional or loop construct (e.g. "my $x if ...") is undefined. The value of the "my" variable may be "undef", any previously assigned value, or possibly anything else. Don't rely on it. Future versions of perl might do something different from the version of perl you try it out on. Here be dragons.