2012-03-16 6 views
5

ho una domanda circa il passaggio di parametri in Tcl riguardo al seguente codice:In TCL, possiamo passare i parametri in questo modo?

set name "Ronaldo" 

proc GET_PLAYER_INFO {player_id {player_name "$name"}} { 
    global name 
    puts $player_name 
} 

riguardo al codice di cui sopra, abbiamo una variabile globale "nome", e nella lista dei parametri di proc GET_PLAYER_INFO, il default il valore del parametro player_name è impostato su "$ name"? se il valore del nome è "ronaldo", è già una citazione doppia, dobbiamo inserire una virgola nella lista dei parametri come questa: player_name "$ name"? e prima di eseguire il comando "nome globale", il valore predefinito di player_name è "Ronaldo"? è così, perché abbiamo bisogno di avere il comando "nome globale" nel nostro proc?

risposta

7

Che non funzionerà così com'è; il $name non verrà valutato affatto, quindi il valore predefinito sarà di cinque caratteri letterali.

Se stai vincolante il valore predefinito al momento della creazione della procedura, lo faresti in questo modo:

proc GET_PLAYER_INFO [list player_id [list player_name $name]] { 
    ... 
} 

Vale a dire, gli argomenti a proc sono cose normali solo è possibile costruire con Comandi e sostituzioni Tcl. Questa è una delle grandi cose di Tcl.

Tuttavia, se hai intenzione di valutare che $name al momento della procedura si chiama, hai avuto modo di farlo in modo diverso. Se hai qualche tipo di valore che non potrà mai essere utilizzato per il nome del giocatore (per esempio, la stringa vuota), allora è abbastanza facile:

proc GET_PLAYER_INFO {player_id {player_name ""}} { 
    if {$player_name eq ""} { 
     set player_name $::name 
    } 
    ... 
} 

Nota che ho usato il nome della variabile pienamente qualificato lì . Ci sono altri modi per ottenere quel nome troppo (ad esempio, con global, con upvar, con variable, ...)

Il luogo in cui le cose si fanno difficili è quando hai non ha un valore sentinella adatto a tutti. A quel punto, bisogna vedere quanti argomenti erano in realtà forniti:

proc GET_PLAYER_INFO {player_id {player_name ""}} { 
    if {[llength [info level 0]] == 2} { 
     set player_name $::name 
    } 
    ... 
} 

Il comando info level 0 restituisce la lista completa di parole argomento della chiamata di procedura in corso. Ciò include lo stesso GET_PLAYER_INFO e sarebbe un elenco di lunghezza 2 o 3 in una chiamata valida alla definizione precedente. Una volta che l'elenco è disponibile, controllarne la lunghezza è un esercizio banale in llength e un confronto numerico. (Utilizzando un valore sentinella è più facile, però, e lavora a 99,99% dei casi.)

L'ultima opzione è quella di utilizzare lo speciale args parametro formale e fare il parsing manualmente:

proc GET_PLAYER_INFO args { 
    if {[llength $args] < 1 || [llength $args] > 2} { 
     return -code error "wrong # args: should be \"GET_PLAYER_INFO player_id ?player_name?\"" 
    } 
    set player_id [lindex $args 0] 
    if {[llength $args] > 1} { 
     set player_name [lindex $args 1] 
    } else { 
     set player_name $::name 
    } 
    ... 
} 

Come si può vedere , questo è piuttosto prolisso ...