Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

interpolation function?

8 views
Skip to first unread message

Josh Marcus

unread,
Jan 31, 2003, 3:01:09 PM1/31/03
to
In perl5, is there a way to force the interpolation of the
value of a scalar variable? For example, if I have:

$id = "foo";
$string = 'my id is $id';

How can I force a "late" interpolation of
the value of $string, without doing something like:

$string =~ s/\$id/$id/g;

or

$statement = "\$id = \"$string\"";
eval ($statement);

--j

John Porter

unread,
Jan 31, 2003, 3:35:08 PM1/31/03
to


I have no idea what you think that eval is doing...
but a simple solution to your problem is to use
double-quotes instead of single-quotes:

$string = "my id is $id";

Please read in perlop about double-quoted (qq) and
single-quoted (q) strings.

--
John Douglas Porter


__________________________________________________
Do you Yahoo!?
Yahoo! Mail Plus - Powerful. Affordable. Sign up now.
http://mailplus.yahoo.com

nadim

unread,
Jan 31, 2003, 3:31:40 PM1/31/03
to

You pretty much have gone through the systems available.

You could tie $statement to a late evaluation module or use one of the
'Lazy' modules that can be found on CPAN.

Nadim.

Benjamin Goldberg

unread,
Jan 31, 2003, 3:56:12 PM1/31/03
to


Well, you can do:
$string = sub{ "my id is $id" };

And later on:
$foo = $string->();

Another possibility is:

my $string = 'my id is $id';

my %vars;
$vars{id} = ....;

$string =~ s/\$(\w+)/$vars{$1}/g;

Which to use depends on where $string is coming from.

--
$..='(?:(?{local$^C=$^C|'.(1<<$_).'})|)'for+a..4;
$..='(?{print+substr"\n !,$^C,1 if $^C<26})(?!)';
$.=~s'!'haktrsreltanPJ,r coeueh"';BEGIN{${"\cH"}
|=(1<<21)}""=~$.;qw(Just another Perl hacker,\n);

Christopher G Tantalo

unread,
Jan 31, 2003, 3:53:23 PM1/31/03
to
John Porter wrote:

> Josh Marcus <jo...@babel.serve.com> wrote:
> > In perl5, is there a way to force the interpolation of the
> > value of a scalar variable? For example, if I have:
> >
> > $id = "foo";
> > $string = 'my id is $id';
> >
> > How can I force a "late" interpolation of
> > the value of $string, without doing something like:
> >
> > $string =~ s/\$id/$id/g;
> >
> > or
> >
> > $statement = "\$id = \"$string\"";
> > eval ($statement);
>
> I have no idea what you think that eval is doing...
> but a simple solution to your problem is to use
> double-quotes instead of single-quotes:
>
> $string = "my id is $id";
>
> Please read in perlop about double-quoted (qq) and
> single-quoted (q) strings.
>
> --
> John Douglas Porter

yep, john beat me to the punch. why not just the double quotes?


--
-------------------------------
Just Your Friendly Neighborhood
_SPIDEY_

Malcolm Dew-Jones

unread,
Jan 31, 2003, 4:34:11 PM1/31/03
to
Josh Marcus (jo...@babel.serve.com) wrote:
: In perl5, is there a way to force the interpolation of the

: value of a scalar variable? For example, if I have:

: $id = "foo";
: $string = 'my id is $id';

: How can I force a "late" interpolation of
: the value of $string, without doing something like:

Perhaps you are really looking for a template system.

There are various template systems on cpan.

Simon Cozens

unread,
Jan 31, 2003, 4:02:04 PM1/31/03
to
Josh Marcus <jo...@babel.serve.com> writes:
> In perl5, is there a way to force the interpolation of the
> value of a scalar variable? For example, if I have:

Cool, the moderators let through a FAQ!

% perldoc -q variable
Found in /usr/lib/perl5/pod/perlfaq4.pod
How can I expand variables in text strings?

Let's assume that you have a string like:

$text = 'this has a $foo in it and a $bar';
$text =~ s/\$(\w+)/${$1}/g;

Before version 5 of perl, this had to be done with a double-eval
substitution:

$text =~ s/(\$\w+)/$1/eeg;

Which is bizarre enough that you'll probably actually need an
EEG afterwards. :-)

See also "How do I expand function calls in a string?" in this
section of the FAQ.

--
I knew that a goodly number of train operating companies had
introduced quiet coaches, but I was still a little concerned
to find that my tickets were prominently marked NOT READING.
- Geraint Jones

Philip Newton

unread,
Feb 2, 2003, 7:23:08 AM2/2/03
to
On 31 Jan 2003 13:34:11 -0800, yf...@victoria.tc.ca (Malcolm Dew-Jones)
wrote:

> There are various template systems on cpan.

I've seen it described as a kind of "rite of passage": Every new Perl
programmer must re-invent at least one of: a template system, a
date/time class, a recursive directory scanner, or (forgot the other
ones).

My sin: recursive directory scanner reporting info a bit à la du(1).
Using readdir() and so on. Before I found out about File::Find.

Cheers,
Philip
--
Philip Newton <nospam...@gmx.li>
That really is my address; no need to remove anything to reply.
If you're not part of the solution, you're part of the precipitate.

Simon Cozens

unread,
Feb 2, 2003, 8:40:22 AM2/2/03
to
Philip Newton <clp...@newton.digitalspace.net> writes:
> I've seen it described as a kind of "rite of passage": Every new Perl
> programmer must re-invent at least one of: a template system, a
> date/time class, a recursive directory scanner, or (forgot the other
> ones).

An XML/HTML parser, and a DBI abstraction layer.

--
Last week I forgot how to ride a bicycle. -- Steven Wright

Jarkko Hietaniemi

unread,
Feb 2, 2003, 9:35:45 AM2/2/03
to
> Philip Newton <clp...@newton.digitalspace.net> writes:
>> I've seen it described as a kind of "rite of passage": Every new Perl
>> programmer must re-invent at least one of: a template system, a
>> date/time class, a recursive directory scanner, or (forgot the other
>> ones).
>
> An XML/HTML parser, and a DBI abstraction layer.

An Acme:: module that enables writing Perl source in a "funny" and
"original" way using the Filter module.

--
Jarkko Hietaniemi <j...@iki.fi> http://www.iki.fi/jhi/ "There is this special
biologist word we use for 'stable'. It is 'dead'." -- Jack Cohen

Mark Jason Dominus

unread,
Feb 2, 2003, 10:03:00 AM2/2/03
to
Simon Cozens <si...@simon-cozens.org>:

> Josh Marcus <jo...@babel.serve.com> writes:
> > In perl5, is there a way to force the interpolation of the
> > value of a scalar variable? For example, if I have:
>
> Cool, the moderators let through a FAQ!

It's a great example of a FAQ question with a really crappy answer.
Perl already has a complete interpolation function built into it, so
there's no good reason why you can't just say

> $text = interpolate('this has a $foo in it and a $bar[3+4*$baz]');

and get exactly the same result that Perl would have produced if the
string had appeared in the source code. But instead the best the FAQ
list can do is to cobble up a partial,obscure, broken solution out of
s///eeg.

Why is the FAQ answer so crappy when a good solution is available? I
don't really understand. I do remember this coming up on p5p a couple
of years ago, where it turned into one of those inexplicable
discussions in which the consensus is that even though the code is
already written, the feature is already in place, and the problem
comes up on the FAQ list, it is somehow not worth solving. Usually
these discussions include the phrase 'code bloat', which is only ever
used in the context of this sort of trivial change, and never in
connection with, say, pseudo-hashes.

Now, I might be wrong about how easy it would be, but I don't recall
that anyone raised that argument at the time.


brian d foy

unread,
Feb 3, 2003, 1:01:34 AM2/3/03
to
In article <2003020215030...@plover.com>, Mark Jason Dominus
<m...@plover.com> wrote:

> Simon Cozens <si...@simon-cozens.org>:
> > Josh Marcus <jo...@babel.serve.com> writes:
> > > In perl5, is there a way to force the interpolation of the
> > > value of a scalar variable? For example, if I have:

> > Cool, the moderators let through a FAQ!

> It's a great example of a FAQ question with a really crappy answer.
> Perl already has a complete interpolation function built into it, so
> there's no good reason why you can't just say

> Why is the FAQ answer so crappy when a good solution is available?

the FAQ answer is still crappy because no one has rewritten it and
given the new answer to me so i can commit it.

patches welcome. :)

--
brian d foy, com...@panix.com

Brian McCauley

unread,
Feb 3, 2003, 8:04:24 AM2/3/03
to
Mark Jason Dominus <m...@plover.com> writes:

> Simon Cozens <si...@simon-cozens.org>:
> > Josh Marcus <jo...@babel.serve.com> writes:
> > > In perl5, is there a way to force the interpolation of the
> > > value of a scalar variable? For example, if I have:
> >
> > Cool, the moderators let through a FAQ!
>
> It's a great example of a FAQ question with a really crappy answer.
> Perl already has a complete interpolation function built into it, so
> there's no good reason why you can't just say
>
> > $text = interpolate('this has a $foo in it and a $bar[3+4*$baz]');
>
> and get exactly the same result that Perl would have produced if the
> string had appeared in the source code. But instead the best the FAQ
> list can do is to cobble up a partial,obscure, broken solution out of
> s///eeg.
>
> Why is the FAQ answer so crappy when a good solution is available?

What do you mean by "available"?

Are you saying that interpolate() is in the Perl core?

There's no built-in interpolate() available by default. If it's
there, how do I get at it?

Was writing String::Interpolate a total waste of time?

> Now, I might be wrong about how easy it would be, but I don't recall
> that anyone raised that argument at the time.

Ah, you are saying that the interpolation engine is there so it would
be easy to make available an interpolate() function?

Actually String::Interpolate would not be a total waste of time
because its 'Safe'-mode features are probably still valuable.

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\

Mark Jason Dominus

unread,
Feb 3, 2003, 10:27:15 AM2/3/03
to
Brian McCauley <nob...@mail.com>:

> Mark Jason Dominus <m...@plover.com> writes:
> > It's a great example of a FAQ question with a really crappy answer.
> > Perl already has a complete interpolation function built into it...

> Are you saying that interpolate() is in the Perl core?

That is similar to what I said, yes. You will note that Perl already
does interpolation, even without your module. So the interpolation
must be in there somewhere. Writing a module for interpolation is
like writing a module for addition.

> There's no built-in interpolate() available by default.

Yes, that is exactly the problem. The functionality is already there
and written, but it is not available. Why not?

> Was writing String::Interpolate a total waste of time?

I don't know the answer to that, and I don't think that answering that
question would be constructive.

But I will note that

(a) The module is large and complicated. I particularly enjoyed this line:

sub STORE { ${${$_[0]}}->{pos}[$_[1]-1]=$_[2] }

Are you proud of having written that?

(b) The module has a lot of fancy features of limited usefulness, but
the basic functionality is incorrect:

use String::Interpolate 'interpolate';

$z = 12;
my $z = 14;

print interpolate('z=$z'), "\n";;
print "z=$z\n";

(c) So therefore it doesn't really do what it claims to do, which is
some permutation of :

Wrapper for builtin the Perl interpolatation engine.

If it were really a wrapper for builtin the Perl interpolation engine,
it would produce the same results that the Perl interpolation engine
produces. It does not.

> Actually String::Interpolate would not be a total waste of time
> because its 'Safe'-mode features are probably still valuable.

Those seem to me to be less valuable than the rest of the module. Why
would the user want to use the Safe-mode features when Safe itself is
already available? Why not

my $compartment = Safe->new(...);
$compartment->permit(...);
...
my $result = $compartment->reval('interpolate($my_string)');

Brian McCauley

unread,
Feb 3, 2003, 12:51:09 PM2/3/03
to

Really? A year ago in message <200220020429530067%com...@panix.com>
you told me "the purpose of this answer is not to explain eval() and
its dangers but to expand variables in text strings. i don't see how
adding this makes the answer any more clear or simple. i think the
necessary lengthy explanation that explained what this did isn't worth
the addition."

If I'm following this thread correctly the "good solution" to which
MJD refers is exactly the same thing as the "this" that you didn't
think worth the addition a year ago.

If you've changed your mind I'll happily re-submit my proposed change
as a proper patch file. I didn't bother last time because you gave
the impression it would be rejected.

Brian McCauley

unread,
Feb 3, 2003, 12:50:19 PM2/3/03
to
Mark Jason Dominus <m...@plover.com> writes:

> Brian McCauley <nob...@mail.com>:
> > Mark Jason Dominus <m...@plover.com> writes:
> > > It's a great example of a FAQ question with a really crappy answer.
> > > Perl already has a complete interpolation function built into it...
>
> > Are you saying that interpolate() is in the Perl core?
>
> That is similar to what I said, yes. You will note that Perl already
> does interpolation, even without your module. So the interpolation
> must be in there somewhere. Writing a module for interpolation is
> like writing a module for addition.
>
> > There's no built-in interpolate() available by default.
>
> Yes, that is exactly the problem. The functionality is already there
> and written, but it is not available. Why not?

Well it's not realy all that hard to get at now.

chop ( my $interpolated = eval "<<_END_\n$my_string\n_END_\n" );
die $@ if $@;

I've repeatedly said that this answer should be in the FAQ.

> > Was writing String::Interpolate a total waste of time?
>

> (a) The module is large and complicated.

Yeah rather bloated, I got carried away.

> I particularly enjoyed this line:
>
> sub STORE { ${${$_[0]}}->{pos}[$_[1]-1]=$_[2] }
>
> Are you proud of having written that?

Neither proud nor ashamed. It's an old C++ habit. I tend to write
trivial accessor methods without any variables because some C++
compilers can't inline functions with variables.

> (b) The module has a lot of fancy features of limited usefulness, but
> the basic functionality is incorrect:
>
> use String::Interpolate 'interpolate';
>
> $z = 12;
> my $z = 14;
>
> print interpolate('z=$z'), "\n";;
> print "z=$z\n";

Yes in the third line of the SYNOPSIS section documentation I point
out that String::Interpolate can't handle lexical variables. I think
this probably needs to be mentioned again later on.

> (c) So therefore it doesn't really do what it claims to do, which is
> some permutation of :
>
> Wrapper for builtin the Perl interpolatation engine.

It's it great how one never spots typos in the titles of ones own documents!

> > Actually String::Interpolate would not be a total waste of time
> > because its 'Safe'-mode features are probably still valuable.
>
> Those seem to me to be less valuable than the rest of the module. Why
> would the user want to use the Safe-mode features when Safe itself is
> already available?

Why use any higher level module when the lower level modules on which
it is based are available?

> Why not
>
> my $compartment = Safe->new(...);
> $compartment->permit(...);
> ...
> my $result = $compartment->reval('interpolate($my_string)');

Because [...] above is actually quite complex.

Slaven Rezic

unread,
Feb 3, 2003, 2:53:06 PM2/3/03
to
Mark Jason Dominus <m...@plover.com> writes:

> Brian McCauley <nob...@mail.com>:
> > Mark Jason Dominus <m...@plover.com> writes:
> > > It's a great example of a FAQ question with a really crappy answer.
> > > Perl already has a complete interpolation function built into it...
>
> > Are you saying that interpolate() is in the Perl core?
>
> That is similar to what I said, yes. You will note that Perl already
> does interpolation, even without your module. So the interpolation
> must be in there somewhere. Writing a module for interpolation is
> like writing a module for addition.
>
> > There's no built-in interpolate() available by default.
>
> Yes, that is exactly the problem. The functionality is already there
> and written, but it is not available. Why not?
>

What about eval? Just put double quotes at the beginning and end of
the eval'ed string:

my $z = 14;
warn eval('"z=$z"');

Regards,
Slaven

--
Slaven Rezic - sla...@rezic.de
babybike - routeplanner for cyclists in Berlin
handheld (e.g. Compaq iPAQ with Linux) version of bbbike
http://bbbike.sourceforge.net

Mark Jason Dominus

unread,
Feb 3, 2003, 4:48:03 PM2/3/03
to

sla...@rezic.de:

> What about eval? Just put double quotes at the beginning and end of
> the eval'ed string:
>
> my $z = 14;
> warn eval('"z=$z"');

That fails if the argument string contains double quotes already.
Brian's here-document solution is better. It would be better still if
Perl could intenally generate a here-terminator that was guaranteed to
be safe and then use that.

Michael Carman

unread,
Feb 3, 2003, 5:14:13 PM2/3/03
to
On 2/3/2003 1:53 PM, Slaven Rezic wrote:
>
> Mark Jason Dominus <m...@plover.com> writes:
>>
>> Brian McCauley <nob...@mail.com>:
>>>
>>> There's no built-in interpolate() available by default.
>>
>> Yes, that is exactly the problem. The functionality is already
>> there and written, but it is not available. Why not?
>
> What about eval?

Isn't that rather heavy-handed? It's like using a sledgehammer on a
finishing nail, and about as dangerous.

my $dir = '/';
my $string = '`rm -rf $dir`';
$a = eval $string;
$b = interpolate($string);

MJD's point (if I understand him correctly) is that Perl is already
capable of providing an interpolate() function which would make risky
eval trickery unneeded.

-mjc

Mark Jason Dominus

unread,
Feb 3, 2003, 5:34:59 PM2/3/03
to
Michael Carman <mjca...@mchsi.com>:

> > What about eval?
>
> Isn't that rather heavy-handed? It's like using a sledgehammer on a
> finishing nail, and about as dangerous.

Interpolation is like that. It is riskier than people realize.
Any solution will necessarily involve 'eval' in some form or another.
Consider:

$x = interpolate('$a[system("blurf")]');

Here the value of $x depends on the success of the external command
"blurf". This is exactly analogous to

$x = qq{$a[system("blurf")]};

So the conclusion to draw is that you can't satisfy the promise
"behaves just like Perl's built-in interpolator" unless you are
willing to execute pretty much anything, including external commands.

> MJD's point (if I understand him correctly) is that Perl is already
> capable of providing an interpolate() function which would make risky
> eval trickery unneeded.

I hadn't realized this until a few hours ago, but it now seems to me
that the most straightforward implementation of a putative
'interpolate' function would call 'eval' to do most of the work.
Consider even something as simple as

"foo$bar"

the way Perl handles this interpolation when it appears in the program
text is to compile it as if you had written

"foo" . $bar

To emulate Perl's interpolation semantics with

interpolate('foo$bar')

the 'interpolate' function would need to compile 'foo$bar' to the same
code and then execute the code. That is essentially 'eval'. That
being the case, you could do an XS version of something like this:

# I hope I did not omit anything obvious here
sub interpolate {
my $string = shift;
my $terminator = 'AAAAAAAAAAAAAA';
$terminator++ until $string !~ /^$terminator$/m;
chop(my $result = eval "<<$terminator\n$string\n$terminator\n");
$result;
}

You still need an XS version because you must perform the 'eval' in
the caller's lexical environment.

Juho Snellman

unread,
Feb 3, 2003, 5:47:31 PM2/3/03
to
<mjca...@mchsi.com> wrote:
>my $string = '`rm -rf $dir`';
>$a = eval $string;
>$b = interpolate($string);
>
>MJD's point (if I understand him correctly) is that Perl is already
>capable of providing an interpolate() function which would make risky
>eval trickery unneeded.

If perl's current routines for interpolating double quoted strings
was exported to the user, wouldn't equal security problems exist
there? I.e.

interpolate '@{[`rm -rf $dir`]}';

--
Juho Snellman

Greg Bacon

unread,
Feb 3, 2003, 8:45:12 PM2/3/03
to
In article <2003020322350...@plover.com>,

Mark Jason Dominus <m...@plover.com> wrote:

: [...]
:
: You still need an XS version because you must perform the 'eval' in


: the caller's lexical environment.

Wow, I really hope the Tcl folks aren't sneering "uplevel" at this
discussion. :-)

Greg, who's been writing way too much Tcl lately
--
.. the FBI's appetite for irrelevant information and public gossip about
individuals is insatiable. On the other hand, when the brother of an FBI
agent comes in and says he thinks his brother is spying for the Soviet
Union, the FBI ignores it. -- Charley Reese

Benjamin Goldberg

unread,
Feb 3, 2003, 11:07:49 PM2/3/03
to
Mark Jason Dominus wrote:
[snip]

> You still need an XS version because you must perform the 'eval' in
> the caller's lexical environment.

Ohh, I dunno -- you might be able to get away with using Padwalker and
Devel::LexAlias to fake up variables of the appropriate names.

Eg, consider:

sub fake_eval_in_context {
my $depth = shift();
local $lexes = peek_my($depth);
my $code = "";
$code .= "my (" . join(", ", keys %$lexes) . " );\n"
if %$lexes;
for my $lex (keys %$lexess) {
$code .= "Devel::LexAlias::lexalias(0, '$lex', " .
"\${*lexes}->{$lex} );\n" .
}
eval $code . "package ".caller($depth).";\n" . shift();
}
[untested]

The reason $lexes is local, is so that if one of the lexicals of the
scope being dealt with also happens to be named '$lexes', it won't be a
problem.

Another alternative is to enable debugging, and perform an 'ordinary'
eval() while in package DB, which will have the special semantic of
performing the eval in the calling context.

--
"So, who beat the clueless idiot today?"
"Well, we flipped for it, but when Kuno
landed, he wasn't in any shape to fight."
"Next time, try flipping a *coin.*"

brian d foy

unread,
Feb 3, 2003, 10:57:53 PM2/3/03
to
In article <u9d6m9x...@wcl-l.bham.ac.uk>, Brian McCauley
<nob...@mail.com> wrote:

> brian d foy <com...@panix.com> writes:
>
> > In article <2003020215030...@plover.com>, Mark Jason Dominus
> > <m...@plover.com> wrote:

> > > Why is the FAQ answer so crappy when a good solution is available?

> > the FAQ answer is still crappy because no one has rewritten it and
> > given the new answer to me so i can commit it.

> > patches welcome. :)

> Really?

i didn't like the partial answer you suggested, but if we got rid
of the whole answer and started over, it can work.

send a suggestion to perlfaq...@perl.org. i've only got
spotty internet access for a while, so somebody else might be
able to fix it up.

Ilya Zakharevich

unread,
Feb 4, 2003, 1:59:04 AM2/4/03
to
[A complimentary Cc of this posting was sent to
Mark Jason Dominus
<m...@plover.com>], who wrote in article <2003020215030...@plover.com>:

> Perl already has a complete interpolation function built into it, so
> there's no good reason why you can't just say

> > $text = interpolate('this has a $foo in it and a $bar[3+4*$baz]');

I do not know how such a statement found a way into clpm; since nobody
would refute it, I'm forced to intervene.

perl most definitely does not have any "complete interpolation
function built into it". All there is is a special state of a lexer.

There *may be not* interpolate() function, since it is never needed:
qq()-strings are seen by the compiler; what compiler generates is not
the *result* of interpolation, but opcodes needed to *calculate*
interpolation. These opcodes are not called until much later - if ever.

When lexer sees qq/ (or a moral equivalent thereof) it (essentially
[1]) switches to a special state. In this state all the chars until
the next $ or @ result in a generated constant value (I forget about
\U etc thingies). When $ or @ are seen, a CONCAT or JOIN opcode is
generated, and the lexer switches to the more-or-less "usual" state;
the only difference is that it returns back to qq-state when the
expression-for-variable ends. This is why

"system $foo @bar"

results in

CONCAT(CONST("system "), VAR(*foo), CONST(" "), JOIN($", ARRAY(*bar)))

*Especially* curious may want [not!] to look at toke.c; pay attention
to all these LEX_INTERPEND etc. states.

Hope this helps,
Ilya

[1] As described in "Gory details...", the lexer first finds the end
of the string to know when it should switch back to the normal mode.

Benjamin Goldberg

unread,
Feb 3, 2003, 11:44:30 PM2/3/03
to
Simon Cozens wrote:
>
> Philip Newton <clp...@newton.digitalspace.net> writes:
> > I've seen it described as a kind of "rite of passage": Every new
> > Perl programmer must re-invent at least one of: a template system, a
> > date/time class, a recursive directory scanner, or (forgot the other
> > ones).
>
> An XML/HTML parser, and a DBI abstraction layer.

I've written an XML parser and a recursive directory scanner (one which
didn't recursive function calls), but not the others...

What would one want with a date/time class?

Or an abstraction of the DBI class?

Mark Jason Dominus

unread,
Feb 4, 2003, 10:08:07 AM2/4/03
to
Ilya Zakharevich <nospam...@ilyaz.org>:

> <m...@plover.com>], who wrote in article <2003020215030...@plover.com>:
>
> > Perl already has a complete interpolation function built into it, so
> > there's no good reason why you can't just say
>
> > > $text = interpolate('this has a $foo in it and a $bar[3+4*$baz]');
>
> perl most definitely does not have any "complete interpolation
> function built into it". All there is is a special state of a lexer.

Perl performs interpolation. It contains all the code necessary for
interpolation. At present this code is usually invoked at compile
time for literal string constants. There is no reason in principle
that it could not also be invoked at run time for the contents of a
variable.

I originally imagined that this 'interpolate()' function would work by
invoking the lexer directly and then executing the resulting code.
But since this is essentially what 'eval' does, it seems that it would
be simpler to use 'eval'.

> There *may be not* interpolate() function, since it is never needed:

Sorry, but "There may be not interpolate() function" is not
well-formed English, so I cannot understand it. I can think of at
least two different things that you might have meant, but I don't feel
confident that I would be able to guess right.

> Hope this helps,

Of course I did not mean to say that there was literally an
'interpolate' function inside of Perl in the sense of there being a
single block of code named 'interpolate'. I meant 'function' in the
more abstract sense of a capability. I hope nobody else was confused
by this, but thanks for helping to clear it up if so.

Malte Ubl

unread,
Feb 4, 2003, 10:49:34 AM2/4/03
to
Simon Cozens wrote:
> Philip Newton <clp...@newton.digitalspace.net> writes:
>
>>I've seen it described as a kind of "rite of passage": Every new Perl
>>programmer must re-invent at least one of: a template system, a
>>date/time class, a recursive directory scanner, or (forgot the other
>>ones).
>
>
> An XML/HTML parser, and a DBI abstraction layer.

which is later ported to be a DBIx::Recordset abstraction layer.

Malcolm Dew-Jones

unread,
Feb 4, 2003, 12:51:01 PM2/4/03
to
Mark Jason Dominus (m...@plover.com) wrote:

: # I hope I did not omit anything obvious here


: sub interpolate {
: my $string = shift;
: my $terminator = 'AAAAAAAAAAAAAA';
: $terminator++ until $string !~ /^$terminator$/m;
: chop(my $result = eval "<<$terminator\n$string\n$terminator\n");
: $result;
: }

: You still need an XS version because you must perform the 'eval' in
: the caller's lexical environment.


from which the obvious useful (but untested) function arises

sub interpolatible

{
my $string = shift;
my $terminator = 'AAAAAAAAAAAAAA';
$terminator++ until $string !~ /^$terminator$/m;

return "<<$terminator\n$string\n$terminator\n"
}

eval interpolatible($string) ;

Mark Jason Dominus

unread,
Feb 4, 2003, 11:53:00 AM2/4/03
to
"Philip 'Yes, that's my address' Newton" <nospam...@gmx.li>:

> On 31 Jan 2003 13:34:11 -0800, yf...@victoria.tc.ca (Malcolm Dew-Jones)
> wrote:
>
> > There are various template systems on cpan.
>
> I've seen it described as a kind of "rite of passage": Every new Perl
> programmer must re-invent at least one of: a template system

My conclusion from a brief survey of twenty-odd templating modules was
that their functionality didn't overlap as much as one would think.

I invented a template system, but it was in 1995, and I'm not sure it
counts as a 're-invent'.

> a recursive directory scanner,

I seem to be writing a book about recursive directory scanners.

> or (forgot the other ones).

Simon mentioned:

Simon> An XML/HTML parser,

Here I did even worse. Not only did I reinvent an XML parser, but I
reinvented XML first. I was rather startled when I heard about XML
later on.

The parser was written for Parse::RecDescent. Parse::RecDescent was
too slow, so I turned the parser into a compiler that turned the XML
into a binary format that could be parsed quickly.

Simon> and a DBI abstraction layer.

I did this too.

> My sin: recursive directory scanner reporting info a bit à la du(1).
> Using readdir() and so on. Before I found out about File::Find.

Everyone does that. It's not a sin. You use the tools you have.
When you learn about more tools, you use them. Ignorance isn't a
sin. The only real sin is when you know about a tool that does what
you want and reinvent it anyway.

Here is a program I wrote in March 1988:

/* Take a man page and strip out the _^H's. */
#include <stdio.h>
#define CTLH 8 /* Code for a control-H */

main()
{
char c;
int ulflag = 0; /* set this if I just read an underline character */

while ((c= getchar()) != EOF)
{
if (ulflag == 1)
{
ulflag = 0;
if (c != CTLH)
printf("_%c",c);
}
else
{
if (c == '_')
ulflag = 1;
else
printf("%c",c);
}
}
}

Apparently I was not yet familiar with either the Unix 'col' command
or with 'sed'.

One funny thing about this is that when I read it just now I said to
myself, "Oh, I can do better than that now," and produced this:


while ((c = getchar()) != EOF) {
switch(c) {
int c2;
case '_':
switch (c2 = getchar()) {
case '\010': break;
case EOF: putchar(c); break;
default: putchar(c); putchar(c2); break;
}
break;
default: putchar(c); break;
}
}

which is worse.

I don't think anyone mentioned reinventing 'getopt' yet. People like
to reinvent getopt so that they can add just another feature.


Ilya Zakharevich

unread,
Feb 4, 2003, 3:01:38 PM2/4/03
to
[A complimentary Cc of this posting was sent to
Mark Jason Dominus
<m...@plover.com>], who wrote in article <200302041508...@plover.com>:
> > perl most definitely does not have any "complete interpolation
> > function built into it". All there is is a special state of a lexer.

> Perl performs interpolation.

AFAIK, no.

> It contains all the code necessary for interpolation.

All you said is that Perl is Turing-complete.

> At present this code is usually invoked at compile time for literal
> string constants.

As I wrote, there is no such code; so it is not invoked. Perl never
"performs interpolation"; as I wrote, what Perl does is compiling a
qq-string into opcodes, which is a very different thing.

> I originally imagined that this 'interpolate()' function would work by
> invoking the lexer directly and then executing the resulting code.
> But since this is essentially what 'eval' does, it seems that it would
> be simpler to use 'eval'.

Exactly. Especially if Safe.pm would be safe...

> > There *may be not* interpolate() function, since it is never needed:
>
> Sorry, but "There may be not interpolate() function" is not
> well-formed English, so I cannot understand it.

Me too. I think I wanted something like what I wrote above: since
Perl never *performs* an interpolation, it would be silly to have code
which does this...

Ilya

Michael R. Wolf

unread,
Feb 5, 2003, 2:40:12 AM2/5/03
to
Mark Jason Dominus <m...@plover.com> writes:

[...]

> I don't think anyone mentioned reinventing 'getopt' yet. People
> like to reinvent getopt so that they can add just another feature.

Seems Damian's been /(re-)+writing/ 'em since at least 1994, though he
calls 'em "Declarative command line interfaces".

http://www.csse.monash.edu.au/cgi-bin/pub_search?publication_type=0&year=&authors=Conway&title=

As for me, I was a beta tester for the Korn Shell when it finally got
a builtin 'getopts' that would prevent some of the hoops I had to do
to use the external 'getopt'. At that time I threw away all the ones
I'd built up over the years. I didn't re-invent it -- I pre-invented
it, but not so well that I preferred my pre-inventions to what Dave
Korn eventually integrated into ksh.

--
Michael R. Wolf
All mammals learn by playing!
MichaelRu...@att.net

Simon Cozens

unread,
Feb 5, 2003, 5:51:51 AM2/5/03
to
"Michael R. Wolf" <MichaelRu...@att.net> writes:
> > I don't think anyone mentioned reinventing 'getopt' yet. People
> > like to reinvent getopt so that they can add just another feature.
>
> Seems Damian's been /(re-)+writing/ 'em since at least 1994, though he
> calls 'em "Declarative command line interfaces".

I recently reinvented getopt because even Getopt::Long was forcing me
to actually write code, and I'm developing an aversion to writing code.

http://search.cpan.org/author/SIMON/Getopt-Auto-1.00/Auto.pm

--
King's Law of Clues : Common sense is inversely proportional to the
academic intelligence of the person concerned.

Stephen O. Lidie

unread,
Feb 5, 2003, 8:39:15 AM2/5/03
to
Simon Cozens <si...@simon-cozens.org> wrote:
> "Michael R. Wolf" <MichaelRu...@att.net> writes:
>> > I don't think anyone mentioned reinventing 'getopt' yet. People
>> > like to reinvent getopt so that they can add just another feature.
>>
>> Seems Damian's been /(re-)+writing/ 'em since at least 1994, though he
>> calls 'em "Declarative command line interfaces".

> I recently reinvented getopt because even Getopt::Long was forcing me
> to actually write code, and I'm developing an aversion to writing code.

> http://search.cpan.org/author/SIMON/Getopt-Auto-1.00/Auto.pm

And my "declarative option processor" pre-dates even Damian's, and includes
ideas now used by the Getopt in the Perl distribution (;

--
@_=map{eval"100${_}"}split/!/,'/5!*2!+$]!/10+$]';use Tk;$m=tkinit;$t='just an'.
'other perl hacker';$z='createText';$c=$m->Canvas(-wi,$_[1],-he,25)->grid;$c->$
z(@_[2,3],-te,$t,-fi,'gray50');$c->$z($_[2]-$],$_[3]-$],-te,$t);$m->bind('<En'.
'ter>',sub{$y=int(rand($m->screenheight));$m->geometry("+$y+$y")});MainLoop;

Benjamin Goldberg

unread,
Feb 5, 2003, 8:03:59 PM2/5/03
to
"Stephen O. Lidie" wrote:
[snip]

> @_=map{eval"100${_}"}split/!/,'/5!*2!+$]!/10+$]';use Tk;$m=tkinit;$t='just an'.
> 'other perl hacker';$z='createText';$c=$m->Canvas(-wi,$_[1],-he,25)->grid;$c->$
> z(@_[2,3],-te,$t,-fi,'gray50');$c->$z($_[2]-$],$_[3]-$],-te,$t);$m->bind('<En'.
> 'ter>',sub{$y=int(rand($m->screenheight));$m->geometry("+$y+$y")});MainLoop;

Cute. Fortunatly the <Enter> doesn't go off when the mouse only
enters the titlebar :) However... it's not a *real* japh if the
letters for "Just another Perl hacker," are in clear text. :)

Michael R. Wolf

unread,
Feb 5, 2003, 6:01:01 PM2/5/03
to
"Stephen O. Lidie" <lu...@Pandora.cc.lehigh.edu> writes:
[...]

> And my "declarative option processor" pre-dates even Damian's, and
> includes ideas now used by the Getopt in the Perl distribution (;

I know it's preaching to the choir and all, but I love that good ideas
can get folded into the main body of knowledge (for what else is code,
but distilled knowledge?) from the backwater thinking spots scatterd
around the universe.

Hip hip, hurray!

0 new messages