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

Hello monks,

I am using the following code:

if ($_ =~ /^DATA\:/) { $LINE = join("", $LINE, $_); }
The code does work, but I recieve the following error

Use of uninitialized value in join or string at C:\Test.pl line 5.

Is there a way to initialize the variable with a value before I join it, or should I switch my join statement around?

Thanks

Replies are listed 'Best First'.
Re: recursive join
by BrowserUk (Patriarch) on Dec 21, 2002 at 14:35 UTC

    You'd be better off (and more efficient) to code that as

    $LINE = ''; ... $LINE .= $_ if /^DATA\:/;

    Examine what is said, not who speaks.

      Thanks for the tip

      While we're on the subject of efficiency, how could I make this a little more efficient?

      if ($_ =~ /^FOO \=/) { $_ =~ s/^FOO \=\s//; $_ =~ s/\\$//; push @array, $_; }

        Firstly, you don't need to reference $_ for the m// or the s///, as it is the default. Second, you can capture the bit you want in the m//. It's also better to use a different delimiter if you have /'s in your regex

        push @array, $1 if m[^FOO\s=\s(.*?)/$];
        should capture everything after the first space after the '=' and before the trailing '/'. If the number of spaces might vary then

        push @array, $1 if m[^FOO\s+=\s+(.*?)/$];

        This wouldn't harm if there is only one space before and after.


        Examine what is said, not who speaks.

        if (s/^FOO =\s//){ s/\\$//; push @array, $_; }
        Basically, the only real change for efficiency is to do the replace once instead of twice. The rest is style, though style counts. I might suggest, though, making the first one a bit less strict, something like
        if (s/^FOO\s*=\s*//){
        So it doesn't matter if there's more than one space, or a tab, or...whatever. But that's for your code to do with as it will.
Re: recursive join
by adrianh (Chancellor) on Dec 21, 2002 at 14:44 UTC
    Is there a way to initialize the variable with a value before I join it
    Yes, just declare it with something like my $LINE = "" before you start doing your joins.

    You are also using join to do concatenation of two strings. Much better to use the "." operator which expresses exactly what you are doing:

    $LINE = $LINE . $_;

    or even more succinctly

    $LINE .= $_;
      The big win with the second is not that it is shorter to write, it is that it executes more efficiently because you do not have to recopy the existing string. Try this:
      my $t = ''; $t .= "test" for 1..50_000;
      versus
      my $t = ''; $t = $t . "test" for 1..50_000;
      See what I mean?
Re: recursive join
by demerphq (Chancellor) on Dec 21, 2002 at 21:24 UTC
    If you use the concat operator . in its mutator form .= then you don't need to preinitialize the variable. The mutator forms of the plus (+= and ++) and minus (-= and --) operators as well as the concatenation operator are special cased so that they dont raise a warning when the variable they act on is undefined.
    use warnings; use strict; my ($str,$x,$y,$c,$d); $str.=chr($_) for 65..90; $x++; --$y; $c += 10; $d -= 2; print "$str $x $y $c $d\n"; __END__ ABCDEFGHIJKLMNOPQRSTUVWXYZ 1 -1 10 -2
    I believe this is because things like
    $hash{foo}.=$foo; next if $dupe{$_}++;
    are so common.

    And just to nitpick, but there's no recursion in your example. ;-)

    --- demerphq
    my friends call me, usually because I'm late....