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

Consider the following code:
sub somefunction { while (expression) { . . $concatstring = &concat ($string1, $string2, $string3); print “$concatstring\n”; } } sub concat { }
I wish to write a function “concat” such that the variable $concatstring will contain a concatenation of the three string variables listed. The function needs to be called from within various functions, and the name $concatstring may not be the same each time. Each of the string variables will require either one or two \t characters adding to it before concatenation, depending on the length of the string. This code is to be executed within the concat subroutine. I wish to achieve an output that looks something like the following:
longstring longstring X X X longstring X longstring longstring
My problem comes because I do not know how to return the finished string from the concat function. I have no problem with the basic logic of appending \t to a string. Any help would be greatly appreciated.

edited: Sun Jan 19 00:35:04 2003 by jeffa - title change (was: Help with subroutines)

Replies are listed 'Best First'.
Re: Concatenating strings with tabs between and returning the result
by Aristotle (Chancellor) on Jan 18, 2003 at 18:19 UTC
    Why not simply use join which takes care of most of what you want? Btw, $string1 and co are useless names for variables. The names should describe what is supposed to be in the variable. my $concatstring = join "\t", $string1, $string2, $string3; To take care of adding another tab for short strings, use map:
    my $concatstring = join "\t", map length() < 8 ? "$_\t" : $_, $string1, $string2, $string3;
    But just to answer your question on how to return the result: quite coincidentally :), you can do that using return.

    Makeshifts last the longest.

Re: Concatenating strings with tabs between and returning the result
by poj (Abbot) on Jan 18, 2003 at 22:06 UTC
    If you are not comfortable with map then consider
    sub concat { my @s = @_ ; # strings my $max = $#s ; # last index # add extra tab to short strings except last one for my $n (0..$max-1){ $s[$n] .= "\t" if (length($s[$n]) < 8); } return join "\t",@s; # sub returns last expression # evaluated so this works too # join "\t",@s; }
    poj
      Don't use for(;;), it's a source of fencepost (or off-by-one) errors when you don't get your condition right. It's also the least efficient form of loop in Perl. Perl understands lists natively, so you should only rarely need counter variables to index an array.
      sub concat { my @s = @_; for (@s) { $_ .= "\t" if 8 > length; } return join "\t", @s; }
      Update: switched order on comparison operands.

      Makeshifts last the longest.

        I got these errors
        Warning: Use of "length" without parens is ambiguous Unterminated <> operator
        fixed it with
        $_ .= "\t" if length() < 8;
        poj
Re: Concatenating strings with tabs between and returning the result
by OM_Zen (Scribe) on Jan 18, 2003 at 18:39 UTC
    Hi ,

    sub concat { map { length($_) < 8 ? {$_=$_."\\t";$_.=$_;return $_;}:{$_.=$_;ret +urn $_;}@_; }

      You can't use naked blocks like that in a ternary operator. You also appear to be using map in void context as a loop to catenate elements to $_. Unfortunately you seem to misunderstand that map returns a list and also that the $_ you are assigning to is aliased to each element of the array in turn, so you are not catenating to the $_ you previously had. Not surprisingly you make no attempt to concatenate the list of elements map returns.

      I tried to reconstruct what you probably meant, but the $_.=$_; return $_ part doesn't make any sense at all, so I don't have any idea what you were thinking.

      Please make at least a token effort to verify your code next time.

      Makeshifts last the longest.

      I can't get your code to compile, is it correct ?
      poj