constant - Perl pragma 用於宣告常數
use constant PI => 4 * atan2(1, 1);
use constant DEBUG => 0;
print "Pi equals ", PI, "...\n" if DEBUG;
use constant {
SEC => 0,
MIN => 1,
HOUR => 2,
MDAY => 3,
MON => 4,
YEAR => 5,
WDAY => 6,
YDAY => 7,
ISDST => 8,
};
use constant WEEKDAYS => qw(
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
);
print "Today is ", (WEEKDAYS)[ (localtime)[WDAY] ], ".\n";
此 pragma 允許您在編譯時宣告常數。
當您使用上述方法宣告常數(例如 PI
)時,執行腳本的每部電腦都能使用其所能使用的最大精確度位數。此外,您的程式會更容易閱讀、更容易維護(並正確維護),而且不太可能因為沒有人注意到您在其中一個等式中寫入 3.14195
而將太空探測器送往錯誤的星球。
當常數用於表達式時,Perl 會在編譯時將其替換為其值,然後可能進一步最佳化表達式。特別是,如果常數為 false,則 if (CONSTANT)
程式區塊中的任何程式碼都將被最佳化移除。
與所有 use
指令一樣,定義常數會在編譯時期發生。因此,將常數宣告放入條件式陳述中(例如 if ($foo) { use constant ... }
)可能不正確。
使用此模組定義的常數無法像變數一樣插入字串中。不過,串接運作正常
print "Pi equals PI...\n"; # WRONG: does not expand "PI"
print "Pi equals ".PI."...\n"; # right
即使參考可能宣告為常數,參考仍可能指向可以變更的資料,如下列程式碼所示。
use constant ARRAY => [ 1,2,3,4 ];
print ARRAY->[1];
ARRAY->[1] = " be changed";
print ARRAY->[1];
常數屬於定義它們的套件。若要參考在其他套件中定義的常數,請指定完整的套件名稱,例如 Some::Package::CONSTANT
。常數可以由模組匯出,也可以作為類別或執行個體方法呼叫,亦即,作為 Some::Package->CONSTANT
或作為 $obj->CONSTANT
,其中 $obj
是 Some::Package
的執行個體。子類別可以定義自己的常數來覆寫其基底類別中的常數。
從此模組的 1.32 版開始,常數可以定義在呼叫者以外的套件中,方法是在常數名稱中包含套件名稱
use constant "OtherPackage::FWIBBLE" => 7865;
constant->import("Other::FWOBBLE",$value); # dynamically at run time
使用全大寫作為常數名稱只是一個慣例,不過建議這樣做,以使常數顯著,並有助於避免與其他裸字、關鍵字和子常式名稱發生衝突。常數名稱必須以字母或底線開頭。以雙底線開頭的名稱是保留的。如果在編譯時期啟用警告,一些不佳的名稱選擇會產生警告。
常數可以是多個(或少於一個)值的清單。沒有值的常數在純量內容中會評估為 undef
。請注意,具有多個值的常數並不會在純量內容中傳回它們的最後一個值,就像人們預期的那樣。它們目前傳回值的數量,但這可能會在未來改變。請勿在純量內容中使用具有多個值的常數。
注意:這表示定義常數值的表達式是在清單內容中評估的。這可能會產生驚喜
use constant TIMESTAMP => localtime; # WRONG!
use constant TIMESTAMP => scalar localtime; # right
上面的第一行將 TIMESTAMP
定義為 9 個元素的清單,就像 localtime()
在清單內容中傳回的。若要將其設定為 localtime()
在標量內容中傳回的字串,則需要明確的 scalar
關鍵字。
清單常數是清單,不是陣列。若要索引或切片它們,必須將它們放在括號中。
my @workdays = WEEKDAYS[1 .. 5]; # WRONG!
my @workdays = (WEEKDAYS)[1 .. 5]; # right
您不必撰寫多個 use constant
陳述式,而是可以在單一陳述式中定義多個常數,方法是提供一個雜湊的參考,其中金鑰是所定義常數的名稱,而不是常數名稱。顯然地,使用此方法定義的所有常數都必須具有單一值。
use constant {
FOO => "A single value",
BAR => "This", "won't", "work!", # Error!
};
這是 Perl 中雜湊建構方式的基本限制。當發生這種情況時產生的錯誤訊息通常會相當難懂,最糟糕的情況是可能完全沒有,而您只能在稍後發現某些東西損壞了。
在定義多個常數時,您不能使用在同一個宣告中定義的其他常數的值。這是因為呼叫套件在 use
陳述式完成之後才知道該群組中的任何常數。
use constant {
BITMASK => 0xAFBAEBA8,
NEGMASK => ~BITMASK, # Error!
};
神奇值和參考可以在編譯時轉換為常數,允許執行像這樣很酷的事情。(這些錯誤號碼並非完全可移植,唉。)
use constant E2BIG => ($! = 7);
print E2BIG, "\n"; # something like "Arg list too long"
print 0+E2BIG, "\n"; # "7"
您不能透過提供繫結標量作為值來產生繫結常數。然而,繫結變數的參考可以用作常數,而不會有任何問題。
在目前的實作中,標量常數實際上是可內嵌的子常式。從 Perl 的 5.004 版開始,適當的標量常數會直接插入某些子常式呼叫的所在位置,從而節省子常式呼叫的開銷。有關如何以及何時發生這種情況的詳細資訊,請參閱 "perlsub 中的常數函式"。
在極少數情況下,您需要在執行時找出是否已透過此模組宣告特定常數,您可以使用此函式來檢查雜湊 %constant::declared
。如果給定的常數名稱不包含套件名稱,則使用目前的套件。
sub declared ($) {
use constant 1.01; # don't omit this!
my $name = shift;
$name =~ s/^::/main::/;
my $pkg = caller;
my $full_name = $name =~ /::/ ? $name : "${pkg}::$name";
$constant::declared{$full_name};
}
除非您使用 Perl v5.20 或更高版本,否則清單常數不會內嵌。在 v5.20 或更高版本中,它們仍然不是唯讀的,但這可能會在未來的版本中改變。
不可能在同一個套件中有一個子常式或關鍵字與常數同名。這可能是一件好事。
由於技術原因,名稱在清單 STDIN STDOUT STDERR ARGV ARGVOUT ENV INC SIG
中的常數只允許在套件 main::
中使用。
與某些語言中的常數不同,這些常數不能在命令列或透過環境變數覆寫。
如果您在會自動引用裸字的內容中使用常數,您可能會遇到問題(對任何子常式呼叫都是如此)。例如,您不能說 $hash{CONSTANT}
,因為 CONSTANT
會被解釋為字串。使用 $hash{CONSTANT()}
或 $hash{+CONSTANT}
來防止裸字引用機制啟動。類似地,由於 =>
算子會引用其左邊的裸字,因此您必須說 CONSTANT() => 'value'
(或僅在箭頭符號的位置使用逗號)而不是 CONSTANT => 'value'
。
Readonly - 建立唯讀標量、陣列、雜湊的工具。
Attribute::Constant - 透過屬性建立唯讀變數
Scalar::Readonly - Perl 擴充,用於 SvREADONLY
標量旗標
Hash::Util - 一系列通用雜湊子常式(主要用於鎖定/解鎖鍵和值)
請透過 perlbug(1) 工具回報任何錯誤或功能要求。
Tom Phoenix, <rootbeer@redcat.com>,並得到許多其他人的協助。
一次加入多個常數宣告由 Casey West, <casey@geeknest.com> 加入。
文件大部分由 Ilmari Karonen, <perl@itz.pp.sci.fi> 重新撰寫。
此程式由 Perl 5 Porters 維護。CPAN 發行版由 Sébastien Aperghis-Tramoni <sebastien@aperghis.net> 維護。
Copyright (C) 1997, 1999 Tom Phoenix
此模組為自由軟體;您可以在與 Perl 相同的條款下重新發布或修改它。