【问题标题】:Can a var concatenated to a string be manipulated by reference可以通过引用操作连接到字符串的var吗
【发布时间】:2013-03-15 05:16:07
【问题描述】:

我需要用连接到变量的固定文本来初始化一个字符串,如下所示:

   my $id = 0;
   my $text ="This is an example, id: ".$id."\n";

现在,在 0->9 的想象循环中,我只想修改 $id 值而不更改固定文本。 我猜想使用引用应该像这样工作

for($i = 0; $i < 9; $i++) {
    my $rid = \$id;
    ${$rid}++;
    print $text;
}

想要的输出是

This is an example, id: 0
This is an example, id: 1
This is an example, id: 2

等等……但它不起作用。

我误解了引用系统吗?

【问题讨论】:

  • 实际上有一个模块可以让你做这样的事情。精氨酸!不记得叫什么了。完全没有。

标签: string perl reference concatenation


【解决方案1】:

您误解了参考系统。

my $id = 0;
my $text ="This is an example, id: ".$id."\n";

该文本在该点与 id 的值连接,在本例中为 0。该文本失去了与变量 $id 的所有连接。然后在循环中

for($i = 0; $i < 9; $i++) {
    my $rid = \$id;
    ${$rid}++;
    print $text;
}

您正在使用$rid( 增加$id 变量,这将成为my $rid = \$id;$id 的另一个名称,但这不会影响文本,因为它没有引用变量$id

做你想做的最干净的方法是使用闭包

my $id = 0;
my $textfunc = sub { return "This is an example, id: ".$id."\n" };

然后在你的循环中做

for($i = 0; $i < 9; $i++) {
    $id++;
    print $textfunc->();
}

【讨论】:

  • print $textfunc(); 是否正确?因为我在这一行收到以下错误:Not a GLOB reference
  • 不,最干净的方法是print "This is an example, id: $_\n" for 0 .. 9;闭包?!只是将变量插入字符串?世界会变成什么样子?!
  • @SinanÜnür 如果循环在同一个地方是的,但问题暗示循环位于程序的某个遥远部分,或者它们也不需要引用。
  • 在这种情况下,不要关闭变量,只需传递子引用。为什么不将参数传递给$textfunc,而不是在“程序的某个遥远部分”对某个变量进行调用。
【解决方案2】:

正如 Sinan 指出的那样,有一种更简单的方法可以做到这一点。如果您想将$text 字符串分开以便维护和/或重用,您也可以考虑使用sprintf,例如:

my $id = 0;
my $max_id = 9;
my $text = "This is an example, id: %d\n";

for (my $i = $id; $i < $max_id; $i++) {
    print sprintf($text, $i+1);
}

【讨论】:

  • 您可以使用printf 代替print sprint(...)
  • Perl 不是 C.for my $id (0 .. 9) ...
【解决方案3】:

您似乎对引用感到困惑。也许您正在考虑以下 C 指针场景:

char text[] = "This is a test xx\n";
char *cursor = text + 15;
*cursor = ' 1';

不知道是什么思维过程会带来这样的印象,一旦将$id的内容插入my $x = "Test string $id",就可以通过改变$id的值来改变插入字符串的值。

正如我所说,你真的很困惑。

现在,如果您希望某个地方的子例程能够格式化某些输出而不在子例程中嵌入输出格式,您可以将消息格式化程序作为参数之一传递给子例程,如下所示:

my $formatter = sub { sprintf 'The error code is %d', $_[0] };

forbnicate([qw(this that and the other)], $formatter);

sub frobnicate {
    my $args = shift;
    my $formatter = shift;

    # ...

    for my $i (0 .. 9) {
       print $formatter->($i), "\n";
    }

    return;
}

这肯定会变得乏味,所以你基本上可以拥有一个格式化程序包,并让潜艇使用他们需要的任何格式化程序:

package My::Formatters;

sub error_code {
    my $class = shift;
    return sprintf 'The error code is %d', $_[0];
}

在主脚本中:

use My::Formatters;

for my $i (0 .. 9) {
    My::Formatters->error_code($i);
}

【讨论】:

    猜你喜欢
    • 2012-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-09
    • 2011-09-20
    • 2019-07-13
    相关资源
    最近更新 更多