Come funziona il valore? lavoro di funzione?
Domanda
Ho ridotto fino a un piccolo esempio un codice che ho, che test per se una variabile denominata class-name
ha un valore assegnato:
ask-params: function [
config-file [file!]
default-class-name
default-fields
] [
probe value? 'class-name
input
either (value? 'class-name) [
probe class-name
] [
;-- omit code in this branch for now
]
]
ret-block: ask-params %simple-class.params.txt "Person" "First Name, Last Name"
Il value? 'class-name
espressione restituisce falsa qui. D'altra parte, se io riempio nel ramo mancante con un incarico:
ask-params: function [
config-file [file!]
default-class-name
default-fields
] [
probe value? 'class-name
input
either (value? 'class-name) [
probe class-name
] [
class-name: default-class-name
]
]
ret-block: ask-params %simple-class.params.txt "Person" "First Name, Last Name"
Ciò restituirà vero per value? 'class-name
. Ma in questo secondo caso, class-name: default-class-name
non è nemmeno ancora eseguito.
Vorrei pensare che class-name non dovrebbe esistere in memoria, in modo da value? 'class-name
deve essere restituito false. Perché value?
tornando vero invece?
Soluzione
Si utilizza function
. Questo esegue la scansione del corpo della funzione e pre-crea le variabili locali per voi, inizializzati a NESSUNO. Ecco perché value? 'class-name
diventa vero (perché nessuno è un valore legale di una variabile, distinta dalla situazione di essere "unset").
Se si è utilizzato func
invece, poi entrambi avrebbero return false.
Altri suggerimenti
Non credo che si comporta in modo diverso rispetto function
func /local
. Guardate questi esempi:
>> f: func [/x] [value? 'x]
>> f
== true
I non ha dato alcun valore per x, ma dice che ha un valore. Lo stesso vale per / local
>> f: func [/local x] [value? 'x]
>> f
== true
Perché quando si effettua un locale (o un perfezionamento) variabile, allora vuol dire che già impostato un valore per esso (che non è) e che è quello che fa function
.
Qui vi mostro due esempi non si utilizza la funzione, ma per il resto equivalente al codice:
ask-params: func [config-file [file!] default-class-name default-fields] [
probe value? 'class-name
input
either (value? 'class-name) [
probe class-name
][
]
]
ask-params: func [
config-file [file!] default-class-name default-fields /local class-name
] [
probe value? 'class-name
input
either (value? 'class-name) [
probe class-name
][
]
]
Mentre la funzione value?
nel primo esempio rese #[false]
, nel secondo esempio produce #[true]
. Questo perché gli "argomenti restringimento" a seguito di un "perfezionamento inutilizzato" (un perfezionamento che non viene utilizzato nella chiamata attuale) vengono inizializzati a #[none!]
insieme con la variabile raffinatezza. Questo vale per le variabili /local
pure, poiché la raffinatezza /local
non differisce da altri filtri funzione (tranne per il fatto, che è una convenzione di usarlo per definire variabili locali).
Poiché il generatore function
utilizza il metodo /local
per implementare variabili locali "sotto il cofano", la descrizione di cui sopra si applica a tutte le funzioni che genera pure.
C'è un altro modo, che evita con il tasto FUNC / LOCAL e consente comunque l'uso della funzione.
Questo è di non usare un set-PAROLA! per l'assegnazione. Utilizzare invece la funzione SET su un LIT-parola!
ask-params: function [config-file [file!] default-class-name default-fields] [
probe value? 'class-name
input
either (value? 'class-name) [
probe class-name
] [
set 'class-name default-class-name
]
]
Si otterrà #[false]
per la funzione value?
. Tuttavia, la chiamata a SET sarà l'impostazione class-name
nel contesto globale ... non come un locale.