Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Interpolation: when it occurs? another beginner question..

by Discipulus (Canon)
on Feb 25, 2013 at 11:50 UTC ( [id://1020500]=perlquestion: print w/replies, xml ) Need Help??

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

hello, yes i'm still a beginner, and yesterday i come up with something never occured to me: the interpolation of a string was not done as expected (sub class of '0 type problem': you expect something wrong).

Why this is not working?
#!perl use strict; use warnings; $|++; my ($comp,$first,@sec); $comp = "descr is ".(defined $first ? q{$first} : 'null').' and list i +s '.( @sec ? q{join ' ', @sec} : 'empty'); print "Oringinal:$comp\n"; &modify_first('UNO'); &modify_second (1);&modify_second (2); &modify_first ('DUE'); &reset_second; sub modify_first{$first = shift; print "$comp\n";} sub modify_second {push @sec, shift; print "$comp\n";} sub reset_second {@sec=qw(); print "$comp\n";} __OUTPUT__ Oringinal:descr is null and list is empty descr is null and list is empty descr is null and list is empty descr is null and list is empty descr is null and list is empty descr is null and list is empty
I have found two approach at this problem: Re: Dreaming of Post Interpolation that propose an quoting-evaluating workaround (not suitable for thinks like  @sec ? @sec : 'empty')
my $text = q{ Dear $person, I know that this text is $adjective. But I wish it could be... }; my $person = 'Mom'; my $adjective = 'not interpolated'; print eval "qq{$text}"; __OUTPUT__ Dear Mom, I know that this text is not interpolated. But I wish it could be...

Another monks come out with a sub solution:
my $n = sub {1}; my $m = sub {&$n*2}; my $o = sub {&$m*2}; my $s = sub {&$n." ".&$m." ".&$o."\n"}; print &$s; $n = sub {2}; print &$s; __OUTPUT__ 1 2 4 2 4 8
The Perl faq propose:
How can I expand variables in text strings? Let's assume that you have a string that contains placeholder vari +ables. $text = 'this has a $foo in it and a $bar'; You can use a substitution with a double evaluation. The first /e +turns $1 into $foo, and the second /e turns $foo into its value. You may + want to wrap this in an "eval": if you try to get the value of an undec +lared variable while running under "use strict", you get a fatal error. eval { $text =~ s/(\$\w+)/$1/eeg }; die if $@; It's probably better in the general case to treat those variables +as entries in some special hash. For example: %user_defs = ( foo => 23, bar => 19, ); $text =~ s/\$(\w+)/$user_defs{$1}/g;

And finally chromatic propose a real magic to create a red apple:
my $color = "red"; my $fruit = "apple"; my $name = "chromatic"; my $string = 'Hi, my name is $name. Please hand me a $color $fruit.'; print ">>$string<<\n"; # demonstrate what we have my $s2; eval "\$s2 = qq/$string/"; # the real magic print "->$s2<-\n"; # demonstrate the result __OUTPUT__ >>Hi, my name is $name. Please hand me a $color $fruit.<< ->Hi, my name is chromatic. Please hand me a red apple.<-

OK. now i know. But there is something newer then years 2000 can I profit? A cleaner solution?

L*
there are no rules, there are no thumbs..

Replies are listed 'Best First'.
Re: Interpolation: when it occurs? another beginner question..
by tobyink (Canon) on Feb 25, 2013 at 13:33 UTC

    These interpolate:

    • "$var"
    • qq{$var}

    These do not:

    • '$var'
    • q{$var}

    TL;DR: if you want interpolation, don't use single quotes!

    OK, I see what you're asking. You want delayed evaluation - I'll update with a solution to that momentarily!

    Update: OK, how about this...

    use v5.10; use strict; use warnings; sub delayed (&) { package delayed; use overload q[""] => sub { $_[0]->() }, fallback => 1; bless shift; } my $string = delayed {"Look $::person, no $::thing!"}; $::person = "Ma"; $::thing = "stringy eval"; say $string;

    Update II (about a week later): I've released String::Interpolate::Delayed using some of the ideas explored in this thread.

    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name

      This is really cool! I think i'll put it on the wall in my office - to remember. Best regards, Karl

      P.S.: I just bothered myself about this with eval and function interpolation :-(

      «The Crux of the Biscuit is the Apostrophe»

        For what it's worth, it does also work with lexical variables, but you need to declare them up-front...

        use v5.10; use strict; use warnings; sub delayed (&) { package delayed; use overload q[""] => sub { $_[0]->() }, fallback => 1; bless shift; } my ($person, $thing); my $string = delayed {"Look $person, no $thing!"}; $person = "Ma"; $thing = "stringy eval"; say $string;

        Here's a version that eliminates the need to declare variables up-front, but does the interpolation manually using s///eg. It's pretty dodgy, and I wouldn't put it anywhere near production code, but it's quite cute as an example...

        use v5.10; use strict; use warnings; use PerlX::QuoteOperator delayed => { -emulate => 'q', -with => sub ($) { package delayed; my $str = shift; use PadWalker; use overload q[""] => sub { $_[0]->() }, fallback => 1; my $get = sub { my $var = shift; my $my = PadWalker::peek_my(3); return $my->{$var} if exists $my->{$var}; my $our = PadWalker::peek_our(3); return $our->{$var} if exists $our->{$var}; die "No such variable: $var\n"; }; bless sub { my $_ = $str; s/(\$\w+)/${$get->($1)}/eg; s/(\@\w+)/join $", @{$get->($1)}/eg; return $_; }; }, }; my $string = delayed "Look $person, no @thing!"; my $person = "Ma"; my @thing = qw( stringy eval ); say $string;

        It's cute, but the code that does the interpolation is pretty dodgy.

        package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: Interpolation: when it occurs? another beginner question.. (delayed interpolation/var substitution/ is templating)
by Anonymous Monk on Feb 25, 2013 at 11:58 UTC
Re: Interpolation: when it occurs? another beginner question..
by Anonymous Monk on Feb 25, 2013 at 13:20 UTC
    Here's the rule: if the string is enclosed in double quotes, interpolation (and substitution for things like "\n") will be performed. If single, it will be treated as a literal string and none of these things will occur.
Re: Interpolation: when it occurs? another beginner question..
by Discipulus (Canon) on Feb 26, 2013 at 15:11 UTC
    for completeness and future memory.. as this is a non-problem better would be to not-resolve it. instead rethink it and achieve in another way: a sub returnig a composed string.
    #!perl use strict; use warnings; $|++; my $first; my @sec; print &compose, "\n"; $first = 'UNO'; print &compose,"\n"; push @sec, '1','2'; print &compose,"\n"; $sec[5] = 'sixt'; print &compose,"\n"; undef $first ; @sec = (); print &compose,"\n"; sub compose { my $it = 'First is '. ($first ? $first : 'not yet defined '). ' and the list is '. (@sec ? '('.(join ' ',map {$_||'UNDEFINED'}@sec ).')': ' e +mpty'); return $it; } __OUTPUT__ First is not yet defined and the list is empty First is UNO and the list is empty First is UNO and the list is (1 2) First is UNO and the list is (1 2 UNDEFINED UNDEFINED UNDEFINED sixt) First is not yet defined and the list is empty
    L*
    there are no rules, there are no thumbs..

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1020500]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (7)
As of 2024-04-18 11:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found