Por que o return / redo avalia as funções de resultado no contexto de chamada, mas os resultados do bloco não são avaliados?
Ontem à noite eu aprendi sobre a opção / refazer para quando vocêreturn
de uma função. Deixa você voltaroutro função, que é então invocado no site de chamada e reinvoca o avaliador da mesma posição
>> foo: func [a] [(print a) (return/redo (func [b] [print b + 10]))]
>> foo "Hello" 10
Hello
20
Apesar defoo
é uma função que leva apenas um argumento, agoraage como uma função que levou dois argumentos. Algo assim exigiria que o chamador soubesse que você estava retornando uma função e que o chamador teria que usar manualmentedo
avaliador.
Assim semreturn/redo
você teria:
>> foo: func [a] [(print a) (return (func [b] [print b + 10]))]
>> foo "Hello" 10
Hello
== 10
foo
consumiu seu um parâmetro e retornou uma função por valor (que não foi chamado, assim o interpretador foi movido). Então a expressão avaliada como 10. Sereturn/redo
não existia você teria que escrever:
>> do foo "Hello" 10
Hello
20
Isso evita que o chamador tenha que saber (ou se importar) se você escolheu retornar uma função para executar. E é legal porque você pode fazer coisas como otimização de chamada de cauda ou escrever um wrapper para a própria funcionalidade de retorno. Aqui está uma variante dereturn
que imprime uma mensagem, mas ainda sai da função e fornece o resultado:
>> myreturn: func [] [(print "Leaving...") (return/redo :return)]
>> foo: func [num] [myreturn num + 10]
>> foo 10
Leaving...
== 20
Mas funções não são a única coisa que tem comportamento emdo
. Então, se este é um padrão geral para"removendo a necessidade de um DO no callsite"então porque isso não imprime nada?
>> test: func [] [return/redo [print "test"]]
>> test
== [print "test"]
Apenas retornou o bloco por valor, como um retorno normal teria. Não deveria ter impresso "teste"? Isso é o quedo
iria ... fazer isso:
>> do [print "test"]
test