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

Dear Monks

I realize that my title is very bad but I couldn't think of a better one, sorry!
Anyway, I need to construct a string out of variables, like
$str = $a.$b.$c.$d.$e.$f.$g etc $w.$x.$y.$z ;
Now, lets say $e is a 10 digit number representing the position inside this string of the word added by variable $x. However I only know $e when I've added $w(because I can calculate the length of the string)
So, if this is not clear enough, let me give an other example.
$a = '' ; $str = "blabla${a}blabla" ; $a = "XXX" ; print "$str\n" ;
Although I know that this examples doesn't do what I need, I would like it to print: blablaXXXblabla
Is something like this possible ?

Thanks a lot
Luca

Replies are listed 'Best First'.
Re: Create string with a delay
by davorg (Chancellor) on Jun 14, 2006 at 12:34 UTC
Re: Create string with a delay
by eric256 (Parson) on Jun 14, 2006 at 13:28 UTC

    Well you know the position of $e? If so then fill it in with 10 0's the first time through. When you get to adding $x calculate its starting position and replace the first 10 zeros. Alternately don't contstruct the string until you know $a - $x.

    my $a = "this"; my $b = "is"; my $c = "a"; my $d = "test"; my $x = "here is the data"; my $e = sprintf("%010d", len($a . $b . $c . $d . $x) + 10); $str = "$a$b$c$d$e$x";

    That code is obviously shortened, but you get the idea. Also you could add len's instead of len'ing the concated whole, doesn't realy matter. The 10 is the buffer for your position info.


    ___________
    Eric Hodges
Re: Create string with a delay
by diotalevi (Canon) on Jun 14, 2006 at 13:54 UTC

    This is easy. Use Data::Postponed. I wrote this module to handle just this kind of task.

    use Data::Postponed 'postpone_forever'; $a = ''; $str = postpone_forever( "blabla" . $a . "blabla" ); $a = "XXX"; print "$str\n"; # prints blablaXXXblabla

    [Edit. I originally goofed by using $x instead of $a. Sorry. That typo is gone now. I also made the string "$blabla${a}blala" nicer to read.]

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

      Surely, that module isn't capable of reversing the concatenation of its arguments, and then performing it again, is it? Perhaps you meant something more like this:
      $a = ''; $str = "blabla" . postpone_forever( $a ) . "blabla"; $a = "XXX"; print "$str\n";

        Oh, yeah, you're right. $a = postpone_forever( '' ) would have been ok as well as $str = postpone_forever( "blabla" ); $str .= $a; $str .= "blabla";. Anything like that would be ok.

        ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: Create string with a delay
by Zaxo (Archbishop) on Jun 14, 2006 at 14:39 UTC

    Another way is to use substr's ability to insert strings.

    # $str is built past $e's position, with $e omitted. # $x is now known substr $str, length($a)+length($b)+length($c)+length($d), 0, sprintf '%010d', length($x);

    After Compline,
    Zaxo

Re: Create string with a delay
by Tanktalus (Canon) on Jun 14, 2006 at 13:06 UTC

    Isn't that just a sum of lengths?

    $w_pos = length($a) + length($b) + length($c) + length($d) + 10 # length of $e + ... + length($v); # everything up to $w $e = sprintf("%010d", $w_pos);
    Of course, this would be a whole lot easier if you had all these vars in a single array...

      You're right, but in my situation the construction of that string is very complex!
Re: Create string with a delay
by rodion (Chaplain) on Jun 14, 2006 at 16:34 UTC
    I think what the OP is trying to do is to assemble the string once, in a single pass. In his added info, jeanluca, he said the assembling code is "very complex!".

    I think eric256 in Re: Create string with a delay and Zaxo in Re: Create string with a delay are both on the right track, but eric256's "len($a . $b . $c . $d . $x)" represents a separate pass through the complexity. For Zaxo's solution, the second argument of the sprintf needs to be "length($str)+10", calculated just before $x is added.

    Combining and extending the two approaches a little, I'd suggests

    $str = $a . $b . $c .$d; $xpos_spot = length( $str ); $e = '0000000000'; $xpos_len = length($e); $str .= $e; $str .= $f; ... $str .= $w; substr $str, $xpos_spot, $xpos_len, sprintf('%${xpos_len}d',length($str)); $str .= $x; ...
    Note that this automatically adjusts for the length of the "fill-in" zeroes, if we change that part in a later revision, usually a good idea. Also the code still works if we insert a "$str .= $aplus", somewhere in the complexities of assembling the first part of the string.

    There's a way to set up a kind of pointer into the part of the string you want to modify later, one that you can assign to. It uses a reference to "substr" with pre-defined parameters (known as currying). See BrowserUK's excellent Re: lhs substr(): refs vs. scalars writeup.

A reply falls below the community's threshold of quality. You may see it by logging in.