【问题标题】:Which Perl built-ins cannot be overridden in CORE::GLOBAL?在 CORE::GLOBAL 中哪些 Perl 内置函数不能被覆盖?
【发布时间】:2011-02-23 06:28:09
【问题描述】:

perlsub 文档的Overriding Built-in Functions 部分提供

当您希望在任何地方覆盖内置函数时,有时可以使用第二种方法,而无需考虑命名空间边界。这是通过将 sub 导入特殊命名空间 CORE::GLOBAL:: 来实现的。

然后举几个例子。然而,最后是

最后,一些内置函数(例如 existsgrep)不能被覆盖。

完整列表是什么?

【问题讨论】:

  • 我很高兴你问这个问题,因为我正要问自己,因为我必须为一本书写这个。 :)
  • @brian d foy 我会把账单寄给你。
  • 我会用可在一些 Perl 活动中兑换的啤酒优惠券付款。 :) 我打算通过蛮力尝试做到这一点,然后看看 Perl 抱怨的地方。我仍然可能会这样做。

标签: perl


【解决方案1】:

toke.c 中的任何负值都可以被覆盖;所有其他人可能不会。可以看源码here

例如,让我们看看第 10,396 行的waitpid

    case 'w':
      if (name[1] == 'a' &&
          name[2] == 'i' &&
          name[3] == 't' &&
          name[4] == 'p' &&
          name[5] == 'i' &&
          name[6] == 'd')
      {                                       /* waitpid    */
        return -KEY_waitpid;
      }

由于waitpid 是负数,它可能会被覆盖。 grep呢?

        case 'r':
          if (name[2] == 'e' &&
              name[3] == 'p')
          {                                   /* grep       */
            return KEY_grep;
          }

它是正数,因此不能被覆盖。这意味着以下关键字不能被覆盖:

chop, defined, delete, do, dump, each, else, elsif, eval, exists, for, foreach, format, glob, goto, grep, if, keys, last, local, m, map, my, next, no, package, pop, pos, print, printf, prototype, push, q, qq, qw, qx, redo, return, s, scalar, shift, sort, splice, split, study, sub, tie, tied, tr, undef, unless, unshift, untie, until, use, while, y

【讨论】:

  • OP中的链接包含一个模拟glob的具体例子。
  • 该示例通过将glob 符号导出到调用包来实现,而不是替换CORE::GLOBAL:: 中的符号
  • 必须有一些额外的魔法:chopsplice 可以被模拟。我认为shiftunshiftpushpop 也可以。
  • @friedo:比这更奇怪。据我所知,您可以设置*CORE::GLOBAL::glob,然后CORE::glob 也会调用模拟函数。
【解决方案2】:

prototype 函数会告诉您是否可以覆盖 CORE:: 函数。

这是一个无需输入即可获得所有功能的共同尝试:

#!/usr/bin/perl

use strict;
use warnings;

open my $fh, "-|", "perldoc", "-u", "perlfunc" or die $!;
my %seen;
while (<$fh>) {
    next unless my ($func) = /=item ([a-z]\w+)/;
    next if $seen{$func}++;

    my $prototype = prototype "CORE::$func";

    print "$func is ", defined $prototype ? "overiddable with $prototype " :
        "not overiddable", "\n";
}

【讨论】:

  • 还有额外的魔法允许dorequireglob 被覆盖。请参阅perlsub 了解内容(如果不是如何以及为什么)。
【解决方案3】:

之前有一个关于SO的问题,感叹mocking the filetest operators的难度(-f-d-x,...)

【讨论】:

    【解决方案4】:

    readline(HANDLE) 函数(和等效的 &lt;HANDLE&gt; I/O 运算符)可以被模拟,但它在使用时自动分配给 $_ 的行为类似于

    while (<HANDLE>) { ...    # equivalent to   while (defined($_=readline(HANDLE)))
    

    不可能。请参阅How can I still get automatic assignment to '$_' with a mocked 'readline' function? 的 hobbs 评论。这意味着像

    这样的代码
    while (<>) {       # implicitly sets $_
        do_something_with($_);
    }
    

    如果您重新定义readline,可能会中断。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-17
      • 2013-04-08
      • 2019-12-04
      • 2015-10-06
      • 1970-01-01
      • 2012-06-28
      相关资源
      最近更新 更多