Para criar funções geradoras, precisamos que yield(value) seja implementado. Isso agiria como yield(), mas 'value' seria passado de volta e retornado da chamada resume().
Isso permitiria que range() fosse transformado em um iterador, em vez de criar um array potencialmente enorme.
Isso também seria um passo em direção a recursos interessantes como compreensão de lista/dit.
Solução desagradável:
func xrange(count, dict):
var i = 0
while i < count:
dict.next = i
yield()
i += 1
func do_stuff():
var curr = {}
var it = xrange(5, curr)
while curr.value != null:
print(curr.value)
it.resume()
Acabei de começar a trabalhar com Godot (gostei até agora), mas concordo que parece que yield() deve ser capaz de retornar mais do que o estado da função. Yield é como retornar com a capacidade de resume(), então a função deve ser capaz de "retornar" um valor rendendo.
Uma abordagem possível que tenho pensado é aumentar o [GDScript]FunctionState
( https://docs.godotengine.org/en/3.1/classes/class_gdscriptfunctionstate.html )
ter um método value() que retorne o argumento para yield().
func co1():
yield(5)
s = co1()
print(s.value()) # prints 5
O GDscript já possui um yield que recebe dois valores e aguarda um sinal. No entanto, esta versão de um argumento apenas retornaria seu argumento no FunctionState. Com apenas essa alteração, um gerador pode ser escrito como:
func xrange(count):
var i = 0
while i < count:
yield(i)
func do_stuff():
var it = xrange(5)
while it:
print(it.result())
it = it.resume()
Isso funciona muito bem, mas há uma sutileza que vale a pena considerar. Quando a função corrotina retorna (em vez de render), um valor é retornado, não um FunctionState. No exemplo acima, null é retornado (porque a função é void) que testamos para parar o loop em do_stuff(). Se a função corrotina retornar um valor [ex. imagine return false
no final de xrange()] então esse teste seria interrompido.
Acho que vou dar uma olhada no código.
IMO, yield(value) seria, erm, valioso.
EDIT: Olhando para o código, há complicações com a versão do sinal do yield, então a seção que escrevi abaixo sobre isso foi removida por enquanto. Pode detalhar mais tarde.
Há alguns problemas em como yield
funciona, então ele será substituído por await
que é mais direto. Ainda não tenho certeza se faremos geradores reais.
Se você ainda estiver interessado na ideia de adicionar geradores, abra uma nova proposta no rastreador GIP seguindo o modelo de problema fornecido (depois de verificar se já não existe). Você pode fazer referência a esse problema e resumir as ideias da proposta. Desde já, obrigado!
Comentários muito úteis
Acabei de começar a trabalhar com Godot (gostei até agora), mas concordo que parece que yield() deve ser capaz de retornar mais do que o estado da função. Yield é como retornar com a capacidade de resume(), então a função deve ser capaz de "retornar" um valor rendendo.
Uma abordagem possível que tenho pensado é aumentar o [GDScript]FunctionState
( https://docs.godotengine.org/en/3.1/classes/class_gdscriptfunctionstate.html )
ter um método value() que retorne o argumento para yield().
O GDscript já possui um yield que recebe dois valores e aguarda um sinal. No entanto, esta versão de um argumento apenas retornaria seu argumento no FunctionState. Com apenas essa alteração, um gerador pode ser escrito como:
Isso funciona muito bem, mas há uma sutileza que vale a pena considerar. Quando a função corrotina retorna (em vez de render), um valor é retornado, não um FunctionState. No exemplo acima, null é retornado (porque a função é void) que testamos para parar o loop em do_stuff(). Se a função corrotina retornar um valor [ex. imagine
return false
no final de xrange()] então esse teste seria interrompido.Acho que vou dar uma olhada no código.
IMO, yield(value) seria, erm, valioso.
EDIT: Olhando para o código, há complicações com a versão do sinal do yield, então a seção que escrevi abaixo sobre isso foi removida por enquanto. Pode detalhar mais tarde.