【问题标题】:Perl sub returns a subroutinePerl sub 返回一个子程序
【发布时间】:2020-04-27 16:05:39
【问题描述】:

我已经有 20 年没有使用 Perl 了,这让我很困惑。我已经 g******d 了,但我显然没有使用合适的搜索字符串,因为我没有找到任何与此相关的内容......

我为什么要执行以下操作?我明白它在做什么,但“为什么”让我无法理解。为什么不直接返回 0 或 1 开始呢?

我正在编写一些代码,其中 sub 使用“return sub”;这是一个非常截断的例子,例如

sub test1 {
  $a = shift @_;

  if ($a eq "cat") {
    return sub {
      print("cat test OK\n");
      return 0;
      }
  }
# default if "cat" wasn't the argument
  return sub {
    print("test for cat did not work\n");
    return 1;
    }
}

$c = test1("cat");
print ("received: $c\n");
print ("value is: ",&$c,"\n");

$c = test1("bat");
print ("received: $c\n");
print ("value is: ",&$c,"\n");

【问题讨论】:

  • 你问我们为什么我们一无所知的代码是这样写的。我们怎么可能回答这个问题?
  • 如果您来自 OO 背景,那么将匿名 sub 视为一种小型单对象方法可能是一种有用的心理练习。通过闭包绑定一些值很像用私有数据实例化一个对象。
  • Ikegami - 我不知道为什么会这样写 - 这就是我问这个问题的原因(我什至不知道原作者是否还在我们身边,所以我不能问他们。 ..).
  • 问题不是你问的;问题是您没有提供有关您要询问的代码的任何信息。您提供了与您的问题完全无关的代码。
  • 对不起,如果您认为这无关紧要 - 也许我问的问题很糟糕。原始代码有一堆 if else's,每个返回一个 sub(每个返回 0 或 1,当被调用时)。我将它编辑为只有一个测试,它返回一个子,默认值,它返回一个子。这怎么不相关?我不想争论,我只是想知道为什么我想这样做而不是从每个测试中返回一个标量。

标签: perl return subroutine


【解决方案1】:

在您的代码中没有理由返回一个子。但是,稍微调整一下

sub test1 {
    my $animal = shift @_;

    if ($animal eq "cat"  || $animal eq "dog") {
        return sub {
            print("$animal test OK\n");
            return 0;
        };
    }

    # default if "cat" or "dog" wasn't the argument
    return sub {
        print("test for cat or dog did not work\n");
        return 1;
    };
}

我们现在有一个围绕$animal 的闭包,这可以节省内存,因为猫和狗的测试共享相同的代码。请注意,这只适用于我的变量。另请注意,$a 和 $b 对 Perl 来说有点特殊,它们用于您可以传递给排序函数并绕过一些可见性检查的代码块中,因此除了排序之外最好避免使用它们。

【讨论】:

  • 在我解决这个问题时,请耐心等待。这部分回答了我的问题,但我没有看到返回一个 sub 的优势,如果我有一只猫,我必须调用它来获得我的“0”,而不是仅仅返回第一名。感谢您提供有关 $a 和 $b 的提示,这不是我会想到的事情(尽管通常我避免使用单字符变量名)。
  • Re "我没有看到返回一个我必须调用以获得我的 "0"" 的优势,你是否声称你的代码'正在询问是否返回一个无条件返回零的子?
  • “0”或“1”。没有别的了。
【解决方案2】:

您可能想搜索“perl 闭包”。

您想要返回代码引用的原因有很多,但这不是我可以在 StackOverflow 问题中简短回答的问题。 Mark Jason Dominus 的Higher Order Perl 是拓展思维的好方法,我们在Intermediate Perl 中介绍了其中的一些内容。

我写了File::Find::Closures 来证明这是类。该模块中的每个子例程都返回两个代码引用——一个用于回调File::Find,另一个用于访问结果。两者共享一个公共变量,其他任何人都无法访问。

请注意,在您的情况下,您不仅仅是调用子例程来“获得零”。它在做其他事情。即使在您的简单示例中,也有一些输出。然后某些行为会被延迟,直到您实际将结果用于某事。

话虽如此,但我们无法理解编写您的特定代码的程序员为什么会这样做。一个合理的猜测是该系统是为更复杂的情况而设置的,而您正在查看一个适合该情况的简单示例。另一个合理的猜测是,程序员刚刚学会了这个特性并爱上了它,然后在任何地方都使用了一年。总是有原因的,但这并不意味着总是有充分的理由。

【讨论】:

  • 好的,这实际上很有帮助(但我通过包含原始代码中不存在的“print”有点混淆了,所以真的 ,所有出来的都是 0 或 1,这取决于特定的 if...else... 路径通过代码。Mea culpa)。我的怀疑是(因为这种代码仅在约 12,000 行代码中的一个短子中)原始程序员当时只是认为这将是一个好主意......非常感谢这一点,并感谢 JGNI因为他们建议可能不需要它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-29
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
  • 2012-04-01
  • 2013-07-11
  • 2015-01-19
相关资源
最近更新 更多