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

I have a hashref cat with a key dog,and statements like:

 $x='$cat->{dog}/mouse'; $y=localtime(); $_=$x; $z = "$_:$y";

my result is, unexpectedly,

$cat->{dog}/mouse:Mon Jul 31 13:54:17 2023

So $y was interpolated as expected, but $cat->{dog}/mouse was not? I also tried to force it to interpolate with eval. No joy. The value in $cat->{dog}/mouse was read from a mysql table, so I really dont have control over the types of quotes around it. I guess the issue is, interpolation is only at the top level - NOT recursive? So although $_ was interpolated as $x=$cat->{dog}/mouse, $cat->{dog} was not. How can I force interpolation to continue until there is nothing left to interpolate? Or, alternatively, how can I pre-process $x to force IT to interpolate? $x was read in from mysql and the value in it is not interpolated.

Cheers!

Replies are listed 'Best First'.
Re: Why is this string only PARTIALLY interpolated?
by stevieb (Canon) on Jul 31, 2023 at 18:54 UTC

    Single quotes do not interpolate.

    In the $y example, you've got unbalanced quotes. The opener is a single quote, the end one is double. I'll bet you've mistyped the opening quote as single instead of double when you wrote this post.

    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Why is this string only PARTIALLY interpolated?
by tybalt89 (Monsignor) on Jul 31, 2023 at 19:40 UTC
    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11153644 use warnings; $SIG{__WARN__} = sub { die @_ }; my $cat = { dog => 'golden retriever' }; my $x='$cat->{dog}/mouse'; my $y=localtime(); $_=$x; my $z = "$_:$y"; my $z2 = eval qq("$_:$y"); print "$z\n"; print "$z2\n";

    Outputs:

    $cat->{dog}/mouse:Mon Jul 31 12:36:50 2023 golden retriever/mouse:Mon Jul 31 12:36:50 2023
Re: Why is this string only PARTIALLY interpolated?
by ikegami (Patriarch) on Aug 02, 2023 at 17:57 UTC

    The first string literal uses single quotes. These don't interpolate.

    The second string contains $_ and $y. Both were interpolated.

    • $_ was replaced with its value, $cat->{dog}/mouse.
    • $y was replaced with its value, Mon Jul 31 13:54:17 2023.

    $x was read in from mysql and the value in it is not interpolated.

    What I hear is that you stored incomplete Perl code (partial string literals) in the database as a template.

    Some earlier posts show how to attempt to fix the incomplete Perl code (by adding double quotes) and how to execute that code (by using eval EXPR). But this isn't a good idea.

    The better solution is to use a proper template system!

      Can you help me understand what you mean by "a proper template system" and how to implement it in MYSQL? I know what a template is, not sure I'm familiar with the set of "proper" ones. TY
        #!/usr/bin/env perl use strict; use warnings; use Template; my $from_db = q/Oh this year I'm off to Sunny [% country %]! /; my $tmpl = Template->new; for my $dest (qw/Greece Italy Spain/) { $tmpl->process (\$from_db, { country => $dest }); }

        $from_db is the immutable thing (the template) which you store in and retrieve from the DB. We then use Template to perform the required modifications. Template is one of the "proper" ones as you can find it listed in Task::Kensho. There are others, of course.


        🦛

        You're processing the template in Perl, not MySQL. Template-Toolkit is my go-to template system. The template would look like

        [% cat.dog %]/mouse
        instead of
        $cat->{dog}/mouse
Re: Why is this string only PARTIALLY interpolated?
by tybalt89 (Monsignor) on Jul 31, 2023 at 19:48 UTC

    Alternate...

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11153644 use warnings; $SIG{__WARN__} = sub { die @_ }; my $cat = { dog => 'golden retriever' }; my $x='$cat->{dog}/mouse'; $x = eval qq("$x"); my $y=localtime(); $_=$x; my $z = "$_:$y"; print "$z\n";
    A reply falls below the community's threshold of quality. You may see it by logging in.