¿Cómo funciona el VALOR? trabajo de la función?
Pregunta
I han reducido a un pequeño ejemplo un código que tengo, que las pruebas de si una variable llamada class-name
tiene un valor asignado a él:
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"
El value? 'class-name
expresión devuelve falsa aquí. Por otro lado, si completo en la rama que falta con una misión:
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"
Esto devolverá cierto para value? 'class-name
. Sin embargo, en este segundo caso, se class-name: default-class-name
ni siquiera ejecutado todavía.
Me gustaría pensar que la clase-nombre no debe existir en la memoria, por lo value? 'class-name
debe devolver false. ¿Por qué está volviendo value?
cierto lugar?
Solución
Está utilizando function
. Este escanea el cuerpo de la función y pre-crea las variables locales para que, inicializados a NINGUNO. Es por eso que value? 'class-name
llega a ser verdad (porque ninguno es un valor legal de una variable, distinta de la situación de estar "preparada").
Si ha utilizado func
lugar, a continuación, ambos se devuelve falso.
Otros consejos
No creo que se comporta de manera diferente que function
func /local
. Vistazo a estos ejemplos:
>> f: func [/x] [value? 'x]
>> f
== true
que no le dan ningún valor a x, pero dice que tiene un valor. Lo mismo para / local
>> f: func [/local x] [value? 'x]
>> f
== true
Debido al realizar una variable local (o un refinamiento), entonces significa que ya ha configurado un valor para ella (que no es) y que es lo que hace function
.
Aquí os muestro dos ejemplos no usar la función, pero por lo demás equivalentes a su código:
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
][
]
]
Mientras que la función value?
en el primer ejemplo rendimientos #[false]
, en el segundo ejemplo se produce #[true]
. Esto es debido a que los "argumentos de refinamiento" después de un "refinamiento sin usar" (un refinamiento que no se utiliza en la llamada real) se inicializan a #[none!]
junto con la variable de refinamiento. Esto se aplica a las variables /local
también, puesto que el refinamiento /local
no difiere de otros refinamientos de función (excepto por el hecho, que es una convención para utilizarlo para definir variables locales).
Desde el generador function
utiliza el método /local
para implementar las variables locales "bajo el capó", la descripción anterior se aplica a todas las funciones que genera también.
Hay otra manera, lo que evita el uso de FUNC / LOCAL y todavía permite el uso de FUNCTION.
Eso es no utilizar un conjunto-PALABRA! para la asignación. En lugar de utilizar la función SET en un LIT-PALABRA!
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
]
]
obtendrá #[false]
para la función value?
. Sin embargo, la llamada al conjunto será el establecimiento de class-name
en el entorno global ... no como un local.