5.2 Recursão Temporal🔗
Introdução🔗
Às vezes, nós queremos realizar algumas ações várias vezes repetidamente. Isso é geralmente o que fazemos quando criamos qualquer programa de computador, mas quando estamos em live coding, pode ser bastante complicado realizar ações repetidas e continuar codificando enquanto essas ações são realizadas. Uma solução útil para isso é a recursão temporal; criar uma função que se chama a si mesma no futuro. Vejamos um exemplo real de um problema que me foi apresentado recentemente e como a recursão temporal forneceu uma solução. Perguntaram-me por que o seguinte código FoxDot não funcionava:
for n in range(21):
if 0 > n > 4:
d1 >> play("x ")
elif 4 > n > 20:
d1 >> play("x-")
else:
d1.stop()
A razão é que o código não tem conceito de tempo – nem segundos nem batidas – e, portanto, todo o código é executado imediatamente, em menos de 0.1 segundos. Isso significa que, após 0.1 segundos, o código chama d1.stop() e, aparentemente, nada acontece. Se este fosse um programa Python normal, poderíamos dizer ao programa para "dormir" por um pequeno período de tempo em cada etapa do loop, assim:
import time
for n in range(21):
if 0 > n > 4:
d1 >> play("x ")
elif 4 > n > 20:
d1 >> play("x-")
else:
d1.stop()
time.sleep(1)
Isso funcionaria; nos primeiros 4 segundos do programa, ouviríamos o resultado de d1 >> play("x ") e, nos 16 segundos seguintes, ouviríamos d1 >> play("x-"), e então ele pararia. No entanto, não há como parar ou alterar esse código enquanto ele está em execução – algo que gostamos de fazer num live code. Uma abordagem alternativa é usar recursão temporal e definir uma função que se chama a si mesma no futuro, assim:
def update(n=0):
if 0 > n > 4:
d1 >> play("x ")
elif 4 > n > 20:
d1 >> play("x-")
else:
d1.stop()
return
Clock.future(1, update, args=(n + 1,))
# Inicie o processo chamando a função
update()
A função usa Clock.future para se programar no futuro com um novo valor de n até atingir o valor 21, quando então será interrompida. O interessante sobre a recursão temporal é que, se alterarmos o conteúdo da função de atualização, ela ainda será executada com o valor correto para n. Também podemos interromper a chamada repetida simplesmente removendo a chamada Clock.future do final da função.