Comment la valeur? travail de la fonction?
Question
J'ai réduit à un petit exemple un code que j'ai, qui teste si une variable appelée class-name
a une valeur qui lui est assignée:
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"
Le value? 'class-name
d'expression renvoie false ici. D'autre part, si je remplirai dans la branche manquante avec une mission:
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"
Ceci renvoie vrai pour value? 'class-name
. Mais dans ce second cas, class-name: default-class-name
est même pas encore exécuté.
Je pense que le nom de classe ne devrait pas exister dans la mémoire, donc value? 'class-name
devrait être de retour faux. Pourquoi est-value?
vrai retour à la place?
La solution
Vous utilisez function
. Ce scanne le corps de la fonction et pré-crée les variables locales pour vous, initialisées à NONE. C'est pourquoi value? 'class-name
devient vrai (car aucun est une valeur juridique d'une variable, distincte de la situation d'être « hors service »).
Si vous avez utilisé à la place func
, alors les deux reviendraient faux.
Autres conseils
Je ne pense pas que se comporte différemment de function
func /local
. Regardez ces exemples:
>> f: func [/x] [value? 'x]
>> f
== true
Je ne donne aucune valeur à x, mais il dit qu'il a une valeur. Idem pour / local
>> f: func [/local x] [value? 'x]
>> f
== true
Parce que quand vous faites une variable locale (ou un raffinement), cela signifie que vous avez déjà défini une valeur pour (ce qui est pas) et qui est ce function
fait.
Ici je vous montre deux exemples non utilisation de la fonction, mais sinon équivalent à votre code:
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
][
]
]
Alors que la fonction value?
dans les premiers rendements par exemple #[false]
, dans le second exemple, il donne #[true]
. En effet, les « arguments » raffinement suite d'un « raffinement utilisé » (un raffinement qui ne sert pas dans l'appel réel) sont initialisés à #[none!]
en même temps que la variable de raffinement. Cela vaut pour les variables /local
aussi bien, puisque le raffinement de /local
ne diffère pas d'autres améliorations de la fonction (à l'exception du fait qu'il est une convention à l'utiliser pour définir des variables locales).
Depuis le générateur de function
utilise la méthode /local
pour mettre en œuvre des variables locales « sous le capot », la description ci-dessus applique à toutes les fonctions qu'elle génère ainsi.
Il y a une autre façon, ce qui évite l'utilisation FUNC / LOCAL et permet toujours l'utilisation de la fonction.
C'est de ne pas utiliser un SET-PAROLE! pour l'affectation. Au lieu d'utiliser la fonction SET sur un MOT LIT.!
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
]
]
Vous obtiendrez #[false]
pour la fonction value?
. Cependant, l'appel à SET sera mise en class-name
dans l'environnement global ... non pas comme un local.