我可以在Perl中模拟C风格的宏吗?

时间:2012-02-20 09:08:23

标签: perl

代码:

my $tmp='x $i y';  # define a macro or whatever

for my $i (0..5){
    my $var;
    #    eval { $var=$tmp; };       # A
    #    eval { $var="x $i y"; };   # B
    $var="x $i y";                  # C
    print $var."\n";
}

B和C会打印

x 0 y
x 1 y
x 2 y

打印

x $i y
x $i y
x $i y

A有什么问题?

4 个答案:

答案 0 :(得分:2)

如果您评估$tmp,它将只返回其中的字符串,这意味着您将执行:$var = 'x $i y'。您需要在$tmp中评估字符串,而不是$var。此外,你不能直接评估字符串,你需要用双引号括起来,以允许插入$i,如下所示:

$tmp = '"x $i y"';  # note double quotes inside
...
$var = eval $tmp;

然而,eval对任何此类问题都是一种野蛮的解决方案。大多数时候你认为你需要它,你需要再考虑一下。您的解决方案可能是代​​码引用:

my $tmp = sub { my $num = shift; return "x $num y" };

for my $i (0 .. 5) {
    print $tmp->($i);
}

在这里,您不会尝试在for循环中使用实际的$i参数,而是将$i作为参数传递给sub,后者使用它并返回字符串。

答案 1 :(得分:2)

eval BLOCK仅捕获异常,因此与问题无关。所以这给我们留下了以下代码:

my $i;
my $tmp = 'x $i y';
$i = 3;
my $var = $tmp;

在两种情况下,赋值的右侧都是相同的字符串,那么为什么期望$tmp$var最终得到不同的值?这毫无意义。

那么如何解决您的问题呢?如果您希望将$tmp的内容用作Perl代码,则需要使用eval EXPR,而$tmp的内容实际上必须是Perl代码。

my $i;
my $tmp = '"x $i y"';   # Quotes added to make it valid Perl.
$i = 3;
my $var = eval $tmp;    # eval EXPR instead of eval BLOCK.

但那是错的。您正在使用eval EXPR作为模板系统。使用真实的tempalte系统,如Template-Toolkit。但是,如果您想继续使用x $i y表单的模板,请查看String::Interpolate

答案 2 :(得分:0)

双引号字符串中的变量名称被替换为值,单引号字符串中的变量(称为interpolation)。这就是A选项打印$i而不是值的原因。

A与:

完全相同
my $var = 'x $i y';
print $var."\n";     # prints 'x $i y\n';

答案 3 :(得分:0)

对于初学者来说,当你将一个字符串放在单引号中时,它不会将你的变量解释为它们的值,而是你输入的文字字符串。

现在就“制作一个宏”来说,这就是你想要做的事情。这是一种在perl中执行此操作的方法,但老实说,您编写的代码永远不应该执行此类操作。

use strict;

# This is your "counter" variable
my $i = 0; 

# This is your "Macro"
my $macro = sub{ return 'x ' . ${\$i} . ' y'}; 

for my $x (0..5){

    $i = $x;
    print &{$macro}, "\n";

}

结果是:

x 0 y
x 1 y
x 2 y
x 3 y
x 4 y
x 5 y