簡體   English   中英

為什么這個Perl產生“不是CODE參考?”

[英]Why does this Perl produce “Not a CODE reference?”

我需要在運行時從Perl符號表中刪除一個方法。 我嘗試使用undef &Square::area執行此操作,這會刪除該功能但會留下一些痕跡。 具體來說,當調用$square->area() ,Perl會抱怨它是“不是CODE引用”而不是“Undefined subroutine&Square :: area called”這是我所期望的。

你可能會問,“為什么這很重要?你刪除了這個功能,你為什么要打電話呢?” 答案是,我不是在呼喚它,Perl是。 Square繼承自Rectangle,我希望繼承鏈將$square->area傳遞給&Rectangle::area ,而不是跳過方法不存在的Square,然后進入Rectangle的area(),方法調用死於“不是CODE參考”。

奇怪的是,這似乎只發生在&square :: area由typeglob賦值定義時(例如*area = sub {...} )。 如果使用標准sub area {}方法定義函數,則代碼按預期工作。

同樣有趣的是,取消定義整個glob可以按預期工作。 只是不要取消定義子程序本身。

這是一個簡短的例子,說明了症狀,並與正確的行為形成對比:

#!/usr/bin/env perl
use strict;
use warnings;

# This generates "Not a CODE reference". Why?
sub howdy; *howdy = sub { "Howdy!\n" };
undef &howdy;
eval { howdy };
print $@;

# Undefined subroutine &main::hi called (as expected)
sub hi { "Hi!\n" }
undef &hi;
eval { hi };
print $@;

# Undefined subroutine &main::hello called (as expected)
sub hello; *hello = sub { "Hello!\n" };
undef *hello;
eval { hello };
print $@;

更新 :我已經使用Package :: Stash解決了這個問題(感謝@Ether),但我仍然感到困惑的是為什么它首先發生。 perldoc perlmod說:

package main;

sub Some_package::foo { ... } # &foo defined in Some_package

這只是編譯時typeglob賦值的簡寫:

BEGIN { *Some_package::foo = sub { ... } }

但它似乎不僅僅是速記,因為在取消定義函數后,這兩者會導致不同的行為。 如果有人能告訴我這是否是(1)不正確的文檔,(2)perl中的錯誤,或(3)PEBCAK,我會很感激。

操縱符號表引用自己必然會讓你陷入困境,因為有很多很難找到的小東西。 幸運的是,有一個模塊可以為你完成所有繁重的工作, Package :: Stash - 所以只需要根據需要調用它的方法add_package_symbolremove_package_symbol

您可能想要檢查的另一個好的方法安裝程序是Sub :: Install - 如果您想生成許多類似的函數,那就特別好。

至於為什么你的方法不正確,讓我們在刪除代碼引用后看一下符號表:

sub foo { "foo!\n"}
sub howdy; *howdy = sub { "Howdy!\n" };

undef &howdy;
eval { howdy };
print $@;

use Data::Dumper;
no strict 'refs';
print Dumper(\%{"main::"});

打印(刪節):

$VAR1 = {
              'howdy' => *::howdy,
              'foo' => *::foo,
    };

正如你所看到的那樣,'howdy'插槽仍然存在 - &howdy實際上沒有做足夠的 事情 你需要顯式刪除glob插槽, *howdy

它發生的原因正是因為你分配了一個typeglob。

當你刪除CODE符號時,其余的typeglob仍然是揮之不去的,所以當你嘗試執行howdy時它會指向非CODE的typeglob。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM