2013-06-20 178 views
7

我想知道我怎麼能在Perl做什麼,我通常做口齒不清:動態變量

(defvar *verbose-level* 0) 
(defun my-function (... &key ((:verbose-level *verbose-level*) *verbose-level*) ...) ...) 

這意味着my-function在冗長的當前級別運行,但我可以通過它不同的水平,這將影響其所有呼叫過於:

(defun f1 (&key ((:verbose-level *verbose-level*) *verbose-level*)) 
    (format t "~S: ~S=~S~%" 'f1 '*verbose-level* *verbose-level*) 
    (f2 :verbose-level 1) 
    (format t "~S: ~S=~S~%" 'f1 '*verbose-level* *verbose-level*) 
    (f2 :verbose-level (1+ *verbose-level*)) 
    (format t "~S: ~S=~S~%" 'f1 '*verbose-level* *verbose-level*)) 
(defun f2 (&key ((:verbose-level *verbose-level*) *verbose-level*)) 
    (format t "~S: ~S=~S~%" 'f2 '*verbose-level* *verbose-level*)) 
[17]> (f1) 
F1: *VERBOSE-LEVEL*=0 
F2: *VERBOSE-LEVEL*=1 
F1: *VERBOSE-LEVEL*=0 
F2: *VERBOSE-LEVEL*=1 
F1: *VERBOSE-LEVEL*=0 
NIL 
[18]> (f1 :verbose-level 4) 
F1: *VERBOSE-LEVEL*=4 
F2: *VERBOSE-LEVEL*=1 
F1: *VERBOSE-LEVEL*=4 
F2: *VERBOSE-LEVEL*=5 
F1: *VERBOSE-LEVEL*=4 

(注意變量綁定恢復在退出 - 即使是不正常的 - 從功能)。

我該如何在Perl中做類似的事情?

例如,在misc.pm,我有our $verbose=0;。 如何編寫一個將$verbose綁定到其參數值並在返回時恢復其值的函數?

回答

10

Perl的全局變量的概念與CL中的特殊變量非常相似。

你可以在「影子」的全局變量與local值:

our $var = 1; 

func("before"); 

{ 
    # a block creates a new scope 
    local $var = 2; 
    func("inside"); 
} 

func("after"); 

sub func { say "@_: $var" } 

輸出:

before: 1 
inside: 2 
after: 1 

如果local值,新的值是在整個動態範圍可見即在所有被調用的函數中。一旦詞法作用域被任何方式遺漏(錯誤,回報等),舊值就會恢復。尾調用不會擴展動態範圍,但可以算作範圍退出。

請注意,全局變量具有完全限定的名稱。從不同的包,你會做這樣的事情

local $Other::Package::var = 3; 
Other::Package::func("from a package far, far away"); 

這通常用來爲功能性(非面向對象)接口軟件包提供的配置。重要的例子是 CarpData::Dumper

+1

看到Perl和CL之間的相似之處有趣。從編譯模型開始(爲什麼*不應該在代碼執行過程中執行代碼?)在特殊語法和詞法變量之間進行獨立的命名空間(CL:變量,函數,標籤,流......; Perl:標量,數組,哈希, subs,IO,...)。哦,和CLOS /駝鹿顯然有關係 – amon

3

如果我理解正確,您需要在函數內部局部重寫一個全局變量。

package my_package; 
our $verbose = 0; 

sub function { 
    my ($arg1, $arg2) = @_; # getting function arguments. 
    local $verbose = $arg1; 
} 

它會恢復舊狀態$verbose

+0

謝謝。如果沒有參數調用'function'會怎麼樣?即,'$ arg1'沒有綁定。我是否需要訴諸'local $ verbose = defined $ arg1? $ arg1:$ verbose'還是有更漂亮的方法? – sds

+0

如果定義了$ arg1;',您可以編寫'local $ verbose = $ arg1'。 –

+0

這沒有意義。如果'$ arg1'沒有被定義,那麼'$ verbose'將是未定義的。你可以做的是'local $ verbose = shift;如果未定義,$ verbose =「default」$ verbose;'(或者使用定義的或賦值運算符:$ verbose // =「default」')。 – TLP