Perl 有一個未定義函式的概念。已宣告但未定義的函式。
sub foo;
foo(); # Undefined subroutine error
bar(); # Undefined subroutine error
該函式foo現在存在于符號表中,可用于決議方法呼叫。但是為什么這個“功能”甚至存在呢?在 C 中,這是因為函式是經過型別檢查的,有時您希望在定義之前進行呼叫(例如解決回圈依賴關系)。但是 Perl 沒有這樣的特性,所有函式符號都是在運行時而不是編譯時決議的。
如果是原型,那么如果沒有原型,為什么要存在未定義的函式?
如果它不是用于原型,那它為什么存在呢?
為什么在方法決議中使用未定義的子例程?為什么不完全忽略它們——你不能呼叫它們,就我所見(充其量)它們是內部實作細節?這就是為什么如果沒有定義函式,我們就不能繼續方法決議,就好像它不存在一樣(看起來它會不那么令人困惑)。
uj5u.com熱心網友回復:
它是關于原型的,函式的宣告(或不宣告)確實在編譯時產生影響。考慮
-
print foo 42;單獨來看,這相當于
print('foo' 42);—foo是一個“裸詞”。如果你strict 'subs'啟用了,它會給你一個編譯錯誤,說禁止使用裸詞。 -
sub foo; print foo 42;這相當于
print(foo(42)); 編譯器知道這foo是一個 sub 并且它沒有原型,所以它以“list op”方式消耗它之后的所有內容,并且它后面是 term42。 -
sub foo(); print foo 42;這相當于
print(foo() 42); 編譯器知道它foo有一個原型并且它不接受任何引數,因此不會尋找任何引數,foo并且42將是運算子的運算元。 -
sub foo($); print foo 42;與案例 2 一樣,這相當于
print(foo(42)). 我想可能有一個測驗我可以用來區分它們。
重點是,一個 sub 是否已知在編譯時確實會產生影響,Perl 為您提供了在定義 sub 的主體之前宣告該事實的選項,盡管它可能很少需要。
至于為什么它對方法決議順序有影響——很可能是副作用,但沒有錯。前向宣告 sub 應該意味著您打算在編譯完成之前提供定義。如果你不這樣做,那么當你嘗試呼叫它時你會得到一個運行時錯誤。對我來說似乎很公平,如果這樣的宣告在 MRO 的一個包中,那么這意味著“這里應該有一個方法,但我忘記了”,當 MRO 到達那個包時你會得到一個錯誤。
uj5u.com熱心網友回復:
我會說,這與其他型別相同;只是如何決議它的工件。
my $hr = { a => 1 }; # $hr name introduced at compile time, assigned or not
所以同樣如此
sub name { ... }; # "name" "declared" at compile time
并且說只是與說- 然后有一個沒有附加定義的符號sub name;大致相同。my $hr;
我不知道決議器是如何作業的,但我猜它必須先接受sub name并稍后“系結”定義,所以碰巧我們也可以說只是sub name;并擁有那個名字。
我的意思是說這就是“原因”,根據問題“但是為什么這個“特征”甚至存在? ”
但是,一旦編譯器提前知道有一個具有該名稱的子程式,那么該事實可能會有多種用途。
uj5u.com熱心網友回復:
這為我節省了很多除錯時間:
sub AUTOLOAD
{
my (undef,$filename,$lineno) = caller;
my ($fn) = basename($filename);
logmsg('E',"Undefined reference ($fn/$lineno): ref=$AUTOLOAD, refer=$ENV{HTTP_REFERER}");
}
uj5u.com熱心網友回復:
我能想到這些原因:
如果 sub 具有原型或屬性,則允許在呼叫它之后放置 sub 的定義。
值得注意的細節:
- 如果它們具有原型或屬性,則允許相互遞回的 subs 存在。
允許宣告 AUTOLOADed 和類似的 subs。
值得注意的細節:
- 允許檢查是否存在自動加載的潛艇。
- 允許匯出 AUTOLOADed 和類似的 subs。
可以用作抽象方法。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/422446.html
標籤:
