¿Por qué return / redo evalúa las funciones de resultados en el contexto de llamada, pero los resultados de bloque no se evalúan?
Anoche aprendí sobre la opción / rehacer para cuandoreturn
de una función. Te deja volverotro función, que luego se invoca en el sitio que llama y reinvoca al evaluador desde la misma posición
>> foo: func [a] [(print a) (return/redo (func [b] [print b + 10]))]
>> foo "Hello" 10
Hello
20
Aunquefoo
Es una función que solo toma un argumento, ahoraActúa como una función que tomó dos argumentos.. Algo así requeriría que la persona que llama sepa que estaba devolviendo una función, y esa persona tendría que usar manualmentedo
evaluador en ello.
Asi sinreturn/redo
obtendrías
>> foo: func [a] [(print a) (return (func [b] [print b + 10]))]
>> foo "Hello" 10
Hello
== 10
foo
consumió su único parámetro y devolvió una función por valor (que no se invocó, por lo que el intérprete siguió adelante). Entonces la expresión se evaluó a 10. Sireturn/redo
no existía, habrías tenido que escribir:
>> do foo "Hello" 10
Hello
20
Esto evita que la persona que llama tenga que saber (o preocuparse) si ha elegido devolver una función para ejecutar. Y es genial porque puedes hacer cosas como la optimización de llamadas de cola o escribir un contenedor para la funcionalidad de devolución. Aquí hay una variante dereturn
que imprime un mensaje pero aún sale de la función y proporciona el resultado:
>> myreturn: func [] [(print "Leaving...") (return/redo :return)]
>> foo: func [num] [myreturn num + 10]
>> foo 10
Leaving...
== 20
Pero las funciones no son lo único que tiene un comportamiento endo
. Así que si este es un patrón general para"Eliminar la necesidad de un DO en el sitio de la llamada", entonces ¿por qué esto no imprime nada?
>> test: func [] [return/redo [print "test"]]
>> test
== [print "test"]
Acaba de devolver el bloque por valor, como lo haría un retorno normal. ¿No debería haber impreso "prueba"? Eso es lo quedo
Haría ... uh, hacer con esto:
>> do [print "test"]
test