Dlaczego zwracanie / ponawianie oceny funkcji wynikowych w kontekście wywołującym, ale wyniki bloków nie są oceniane?
Ostatniej nocy dowiedziałem się o opcji / redo, kiedyreturn
z funkcji. Pozwala ci wrócićinne funkcja, która jest następnie wywoływana w miejscu wywołania i ponownie wywołuje ewaluatora z tej samej pozycji
>> foo: func [a] [(print a) (return/redo (func [b] [print b + 10]))]
>> foo "Hello" 10
Hello
20
Nawet jeślifoo
jest funkcją, która przyjmuje tylko jeden argument, terazdziała jak funkcja, która miała dwa argumenty. Coś takiego wymagałoby w przeciwnym razie, aby dzwoniący wiedział, że zwracasz funkcję, a ten rozmówca musiałby ręcznie użyćdo
ewaluator.
Tak więc bezreturn/redo
, dostaniesz:
>> foo: func [a] [(print a) (return (func [b] [print b + 10]))]
>> foo "Hello" 10
Hello
== 10
foo
zużyła swój jeden parametr i zwróciła funkcję według wartości (która nie została wywołana, dlatego interpreter przeniósł się dalej). Następnie wyrażenie ocenia się na 10. Jeślireturn/redo
nie istniałeś, musiałbyś napisać:
>> do foo "Hello" 10
Hello
20
Dzięki temu rozmówca nie musi znać (lub troszczyć się), czy wybrałeś zwrot funkcji do wykonania. I jest fajny, ponieważ możesz robić takie rzeczy, jak optymalizacja połączeń ogonowych lub pisanie opakowania dla samej funkcji powrotu. Oto wariantreturn
który drukuje wiadomość, ale nadal wychodzi z funkcji i zapewnia wynik:
>> myreturn: func [] [(print "Leaving...") (return/redo :return)]
>> foo: func [num] [myreturn num + 10]
>> foo 10
Leaving...
== 20
Ale funkcje nie są jedyną rzeczą, która zachowuje siędo
. Więc jeśli jest to ogólny wzór dla„usunięcie potrzeby DO w callsite”, więc dlaczego to nic nie drukuje?
>> test: func [] [return/redo [print "test"]]
>> test
== [print "test"]
Właśnie zwrócił blok po wartości, tak jakby miał normalny zwrot. Czy nie powinien był wydrukować „testu”? To codo
zrobiłbym ... z tym:
>> do [print "test"]
test