2012-02-20 69 views
3

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

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 

在什么一个是错的?在双引号字符串

+0

任何错误的'sub not_macro {“x $ _ [0] y”};打印not_macro($ _),“\ n”为0 .. 5;'? – 2012-02-20 09:43:45

+0

klortho#11903。 – zgpmax 2012-02-20 17:10:50

回答

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

0

变量名替换值,单引号字符串变量(这就是所谓的interpolation)。这就是为什么A选项正在打印$i而不是值。

A不会完全一样:

my $var = 'x $i y'; 
print $var."\n";  # prints 'x $i y\n'; 
2

如果你EVAL $tmp,它只是返回它里面的字符串,这意味着你会做什么:$var = 'x $i y'。您需要评估$tmp中的字符串,但不是$var。此外,您不能直接EVAL的字符串,你需要把它们放在双引号,以使插值$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); 
} 

在这里,你会不会尝试使用实际$i参数在for循环,而是通过$i作为参数传递给子,谁使用它,并返回字符串。

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 
相关问题