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?

Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top