Re: Dreaming of Post Interpolation
by mdillon (Priest) on May 30, 2000 at 07:08 UTC
|
check out this Interpolation module from M-J. Dominus:
http://www.plover.com/~mjd/perl/Interpolation/
i haven't checked it out myself, but it looks pretty
interesting from just looking at the web page.
i don't think that there is a simple, transparent syntax
or function for doing what you want in Perl. at the least,
you can check out the techniques MJD uses in his Interpolation
module and go from there.
most of the time, i use (s)printf for such things, but
it does not have the nice feature of explicitly tying the
name to the postition as does symbolic variable
interpolation (i.e. it's hard to tell which '%s' goes with
which variable when there are twenty of them; 'Hello
$Recipient' is transparent). | [reply] |
|
Dude, congratulations! That was exactly what I was looking for! I wonder why it hasn't been introduced into the core! I can think of 2031 different ways of using the Interpolation.pm (and the name is so damn obvious, I don't know how I never ran across it on CPAN). I'm downloading it now to play with it a bit and see if I can get the desired results from it.
Thank you, thank you!!
#!/home/bbq/bin/perl
# Trust no1!
| [reply] |
|
i poked around CPAN a bit looking for it, but aside from a
few stale references to it's being on CPAN in Google, i
couldn't find it there.
| [reply] |
|
|
Re: Dreaming of Post Interpolation
by lhoward (Vicar) on May 30, 2000 at 05:15 UTC
|
Here's my stab at it. By storing
the original text in a function instead of a scalar
I can delay interpolation
of the $vars until call time. See this example:
$text = sub {
<<EOT;
Dear $person,
I know that this text is $adjective.
But I wish it could be...
EOT
};
local $person = 'Mom';
local $adjective = 'not interpolated';
print &$text;
I don't think this is quite what you were looking for, but
I think it is along the right path. I have a feeling that something
with eval might do the trick too, but I can't
figure out how to get that to work right now. | [reply] [d/l] |
|
Hey! That's very close to the general idea! But it doesn't deal with my previous post with numbers... The delaying part is attractive, but unfortunately you only get to do one assignment. I would like to have several variables (and variables composed from those) affected by change of one.
The best reference that pops into mind (and the simplest one) is Excel. Kinda like having an entire column defined from a cell, then cascading down the line when you change the value of that cell.
But, delaying works admirably when you're dealing with a single variable. It would just be a pain in the behind to have to do that for each (no pun intended) one of them all.
| [reply] |
|
Unless I misunderstand what you're asking for; you can do the
assignment multiple times with
different values:
$text = sub {
<<EOT;
Dear $person,
I know that this text is $adjective.
But I wish it could be...
EOT
};
my @subs=('Mom:not interpolates',
'Dad:maybe interpolated',
'Sis:who knows');
foreach (@subs){
local ($person,$adjevtive)=split ':',$_;
print &$text;
}
My technique will also
work for your number example (with everything
stored as a function). However it look slightly ugly:
$n = sub {1};
$m = sub {&$n*2};
$o = sub {&$m*2};
$s = sub {&$n." ".&$m." ".&$o."\n"};
print &$s;
$n = sub {2};
print &$s;
| [reply] [d/l] [select] |
Re: Dreaming of Post Interpolation
by Anonymous Monk on May 30, 2000 at 20:49 UTC
|
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}";
| [reply] [d/l] |
|
YES!
this is the cleanest i've seen yet. the only thing that
breaks this is unbalanced brackets, but in a 'sub interpolate',
it's easy enough to get around such restrictions.
on a side note, the Interpolate module doesn't really
help much for BBQ's problem. this solution, however, gets
perl to do real double-quotish interpolation on an
arbitrary scalar value.
| [reply] |
|
Yeah, the Interpolat module wasn't as good as what it looked like from the examples. It just does a few tricks with hashes, and seems to be directed towards maintainin string formats more than actually doing heavy linkage.
I think that what I was looking for is a new data state. Something that would cascade through whatever assignments had been done before. My numeric example was probably the best way to demonstrate. Come to think of it, cascade sounds like a cool name. Imagine it:
cascade $n = 1;
my $m = $n*2;
my $o = $m*2;
my $s = "$n $m $o\n";
print $s;
$n = 2;
print $s;
^d
1 2 4
2 4 8
now would THAT be cool? Does anyone know if there a perl ideas/wishlist somewhere?
#!/home/bbq/bin/perl
# Trust no1!
| [reply] [d/l] |
|
|
|
|
|
Re: Dreaming of Post Interpolation
by takshaka (Friar) on May 30, 2000 at 04:02 UTC
|
Eh? That's just filling in a template. You can do it with
symbolic refs (if the variables aren't lexicals) or,
preferably, with hash lookups.
my $text = q{
Dear $person,
I know that this text is $adjective.
But I wish it could be...
};
my %replace = (person => 'Mom',
adjective => 'not interpolated');
$text =~ s/\$(\w+)/$replace{$1}/g;
print $text;
| [reply] [d/l] |
|
Yes, regex... But would that be considered true interpolation?
The idea of searching within word boudaries for a string starting with \$ occured to me several times, but I have always thought of it as not being very practical. Let me put it this way (this time with math):
$n = 1;
$m = $n*2;
$o = $m*2;
$s = "$n $m $o\n";
print $s;
$n = 2;
print $s;
^d
1 2 4
2 4 8
Sure this is a simplistic example (as was my previous), but what when you have 1000+ more lines of code, wouldn't it be alot easier to control? Is the only way out to run a regex after assignment? There must be another way... Think of the possibilities!
Am I suffering from fuzzy-logic syndrome?
| [reply] [d/l] |
|
I forgot about the double-e substitution
( ie, s/(\$\w+)/$1/gee ). You can do that with lexicals.
No matter what, you end up doing some sort of substitution
and/or eval. In the second example you want to re-evaluate
$m=$n*2 whenever $n is reassigned, which isn't possible
without creating more complex data structures.
That's far different from interpolating variables
into a string.
| [reply] |
|
Re: Dreaming of Post Interpolation
by xeh007 (Sexton) on May 30, 2000 at 05:23 UTC
|
eval '$interpolated = "' . $text . '"';
$interpolated should now be the interpolated version of $text.
Yes, I know this is a cheap way of doing it, but it does work... (It even catches references, hashes, arrays, etc.!) | [reply] [d/l] |
Re: Dreaming of Post Interpolation
by Corion (Patriarch) on May 30, 2000 at 15:51 UTC
|
In that code piece of mine
I use the awkward version of interpolation
, that is, running a regex over the result until no more
matches for (in my case) "$\(\w+\)" are found and I replace
the stuff from a hash instead of the global namespace - for
security reasons, I find it more appealing to use a dedicated
hash instead of global namespace, but that's just my opinion
;D | [reply] |
Re: Dreaming of Post Interpolation
by takshaka (Friar) on May 30, 2000 at 23:43 UTC
|
Here's the module I was working on last night before
you found Interpolation.pm. It's harsh, but actually
gets the job done,
although you have to type your variables as either
string or expression. I like the way Interpolation.pm
uses import() instead of forcing you to tie your
variables yourself, so I borrowed that bit.
Update: Having had a few moments to mull over
code generated too late at night, I see it is simpler
than I was making it--none of that silly data typing is
needed....
package EvalScalar;
use Carp;
sub import {
my $caller_pkg = caller;
my $my_pkg = shift;
for (@_) {
my $var = $_;
$var =~ s/^\$//;
my $temp;
tie $temp, $my_pkg;
*{$caller_pkg . '::' . $var} = \$temp;
}
}
sub unimport {
my $caller_pkg = caller;
my $my_pkg = shift;
for (@_) {
my $var = $_;
$var =~ s/^\$//;
my $temp;
my $old_var = *{$caller_pkg . '::' . $var}{SCALAR};
*{$caller_pkg . '::' . $var} = \$temp;
untie $$old_var;
}
}
sub TIESCALAR {
my $pkg = shift;
my $type = shift;
my $temp = '';
my $self = \$temp;
bless $self, $pkg;
return $self;
}
sub STORE {
my $self = shift;
my $value = shift;
$value =~ s/\$(\w+)(?!::)/'$' . caller() . '::' . $1/ge;
$$self = $value;
}
sub FETCH {
my $self = shift;
my $value = eval $$self;
if ($@) {
carp $@;
return '';
}
else {
return $value;
}
}
1;
and the example usage...
#!/usr/bin/perl -w
use strict;
use EvalScalar qw($a $b $c);
# Only works with globals
use vars qw($person $num);
$num = 3;
# Single-quote the rhs if you want
# evaluation of the assignment
# delayed until read-time.
$a = '$num * 2';
$b = '$a + $num';
$c = '"$num, $a, $b"';
for $num (1..5) {
print "\$a=$a, \$b=$b, \$c=$c\n";
}
$a = '"Dear $person, this sorta works\n"';
for $person qw(Mom Dad BBQ) {
print $a;
}
$a = '"But unqualified subs will be called in EvalScalar namespace" .
+foo()';
print $a;
| [reply] [d/l] [select] |
Re: Dreaming of Post Interpolation
by chromatic (Archbishop) on Jun 06, 2000 at 22:16 UTC
|
| [reply] |
RE: Dreaming of Post Interpolation
by Anonymous Monk on May 30, 2000 at 22:52 UTC
|
my $text = 'Dear $person, I know that this text is $adjective.
But I wish it could be...';
my $person = "foobar";
my $adjective = "flooby";
$interpolated_text = eval($text);
| [reply] |
|
put this afterward and see what happens:
if ($@) { print "$@\n"; }
syntax error at (eval 1) line 3, at EOF
| [reply] [d/l] |
Re: Dreaming of Post Interpolation
by Aighearach (Initiate) on May 30, 2000 at 05:19 UTC
|
> interpolating single-quoted variables
Isn't this just a case of, in your dream-state, using single quotes where in reality you would have used double quotes?
Maybe I am not understanding the problem, but it seems like the sollution would either be reinventing single quotes, or eval
Paris Sinclair | 4a75737420416e6f74686572
pariss@efn.org | 205065726c204861636b6572
I wear my Geek Code on my finger.
| [reply] |
|
Yes, I guess the single-quote part was a bit of a slip-up on my part. There is no reason for the desired effect that I am looking for to be acheived exclusively with single-quotes. As a matter of fact, double-quotes would be even better since they represent (and do) interpolate.
My mess-up was based on the fact that I wanted a string to be re-assigned when it doesn't do it automatically. The single-quote part was my goof, and a bit of an exageration. Now I can't find any good reason why they couldn't be double in the first place. Thanks for pointing that out. Its important.
| [reply] |
A reply falls below the community's threshold of quality. You may see it by logging in. |