Godot: Fatiamento de matriz para GDScript

Criado em 19 mai. 2016  ·  36Comentários  ·  Fonte: godotengine/godot

seria bom se pudéssemos usar o recurso de fatia pythonish como

array[2:4]
array[2:]
array[:-1]

ou ainda pode ser fatiado estendido com passo

array[::2]
array[::-1]
feature proposal pr welcome gdscript

Comentários muito úteis

sintaxe python imho com: é mais conveniente - menos caracteres e mais compacto

+1. E menos confuso. Nós somos parecidos com o python, então não vamos importar comportamentos de todas as outras linguagens do mundo ou o GDScript se tornará realmente inconsistente.

Todos 36 comentários

Observe que isso é feito facilmente com range e compreensões de #4716:

var result = array[from:to:step]
# Is the same as:
var result = (array[i] for i in range(from,to,step))

Além disso, para lançar a sintaxe CoffeeScript aqui também:

x = array[from...to]

Podemos adaptar isso para suportar o tamanho da etapa (já que eles não suportam):

x = array[from..step..to]
# or
x = array[from...to:step]

sintaxe python imho com: é mais conveniente - menos caracteres e mais compacto

sintaxe python imho com: é mais conveniente - menos caracteres e mais compacto

+1. E menos confuso. Nós somos parecidos com o python, então não vamos importar comportamentos de todas as outras linguagens do mundo ou o GDScript se tornará realmente inconsistente.

Sintaxe D ($ é o tamanho do array):

array[2..4]
array[2..$]
array[$-1..$]

Somente para referência. Concordo que o do Python se encaixa melhor com o GDScript: P

Estou disposto a trabalhar neste.

Como primeiro passo estou preparando um PR que adiciona indexação negativa. (Se permitirmos array[:-1] , devemos permitir array[-1] também.)

Que tal atribuir fatias de matriz? Existem casos de uso?

Estou confiante de que posso obter o código para suportá-lo, mas se não houver casos de uso, talvez não me incomode com isso.

Acho que uma restrição que temos que fazer é que os valores de substituição devem ter o mesmo tamanho (que o Python também impõe em estruturas semelhantes a matrizes com um tamanho fixo, como bytes)

Em outras palavras, o seguinte deve funcionar:

var a = range(10)
a[2:5] = [10, 11, 12]
print(a) #[0, 1, 10, 11, 12, 3, 4, 5, 6, 7, 8, 9]

O seguinte pode:

a = range(10)
a[1::2] = [10, 11, 12, 13, 14]
print(a) # [0, 10, 2, 11, 4, 12, 6, 13, 8, 14]

Mas isso provavelmente não vai:

a = range(10)
a[2:5] = [10]
print(a) # [0, 1, 10, 5, 6, 7, 8, 9]

Opiniões?

Só para constar, ainda estou trabalhando nisso. Eu posso ter um PR pronto na próxima semana, mas pode levar mais tempo.

@brakhane Ninguém está com muita pressa -- não se apresse :)

veja #5701 e #5765
Eu adicionei uma operação simples de fatia de 2 argumentos às associações DVector e ByteArray que, com algumas associações futuras, podem ser aplicadas a qualquer um dos tipos de matriz de baixo nível GDSript (IntArray, StringArray, etc). O código ainda não está lá para lidar com -1. Acabei de perceber que deixei essa conveniência de fora agora.

Eu acho que isso deve ser implementado para 3.0, atualmente temos apenas o método subarray(from, to) implementado para PoolByteArray, mas não para outros tipos internos, por isso é muito inconsistente. Se não implementarmos algo consistente para o 3.0, proponho reverter o #5879 (que ainda não foi lançado em uma versão estável) para evitar a introdução de uma API que possa ser substituída posteriormente.

Minha implementação está 98% concluída (funciona, mas há alguns vazamentos de memória e travamentos aleatórios que não tive tempo de depurar), mas devido a restrições de tempo real não poderei concluí-la.

Estou mais do que disposto a colocar meu WIP em um branch para que alguém possa (me ajude) terminá-lo. Posso ajudar com dúvidas sobre a implementação. Seria uma pena se meu esforço fosse desperdiçado (eu gasto provavelmente cerca de 40h até agora)

A implementação é bastante completa em termos de recursos (e estou muito orgulhoso de quão completo ficou), por exemplo, o fatiamento funciona como em Python para a maioria dos tipos de array, incluindo atribuição ( a[1:4] = [1,2,3] por exemplo funciona, o mesmo acontece a[1:3] = b[10:13:2] e vice-versa).

Porém, existem algumas ressalvas:

  • a implementação é meio complexa, e você deve ter algum conhecimento sobre Variant.cpp e variant_op, bem como o interpretador de bytecode para entender isso.
  • Para manter minha sanidade e ajudar na depuração, tive que substituir algumas das macros em variant_op por templates equivalentes, IMO eles tornam o código mais legível (e com otimizações habilitadas tão rápido quanto antes), mas como o código é baseado em 2.1, há provavelmente precisa ser alguma refatoração para compilar com 3.0; Além disso, como o código é WIP, não tive tempo de dividi-lo em commits separados, então às vezes uma macro é substituída por um modelo enquanto, ao mesmo tempo, a lógica variante é adicionada; torna um pouco mais difícil (mas não muito difícil) distinguir os dois
  • Para evitar tornar o interpretador de código de bytes incompatível com versões antigas, tive que introduzir um novo tipo de dados slice , que precisa ser exposto no editor. Este trabalho está feito, mas há algumas arestas.
  • Como já foi dito, o "único" problema que resta é alguma corrupção de memória que não consegui descobrir; quem quiser depurar isso deve estar familiarizado com o funcionamento do interpretador de bytecode Godot

Deixe-me saber se eu deveria colocar o código em algum lugar. Eu acho que alguém familiarizado com os componentes internos do script godot resolverá os problemas em 10 horas ou menos.

@brakhane já que você já tem trabalho feito, seria ótimo se você colocasse o código em seu fork e abrisse um Pull Request. Dessa forma, outras pessoas podem revisar e comentar seu código.

Como tá indo?
Ansioso isso. :)

@bojidar-bg é nosso novo desenvolvedor gdscript, gostaria de tentar? :P

bem, vai empurrar para 3.1

Só queria observar que o método subarray usa intervalos inclusivos, enquanto isso (espero) usará intervalos de fatiamento no estilo python.

Digo esperançosamente porque o método subarray é um pouco doloroso de usar, exigindo que você escreva uma caixa especial para garantir que nunca tente criar uma fatia de largura zero (por exemplo, se você estiver tentando consumir parte de um buffer cortando-o duas vezes, a fatia 'restante' pode ter comprimento zero) e adicionar -1 a todos os comprimentos ao solicitar uma fatia.

Edit: na verdade, não consigo pensar em uma situação em que você não precisaria adicionar um -1 à fatia final, a menos que você esteja fatiando bytes de número constante e, portanto, possa fazer o -1 ao escrevê-lo.

Algum progresso com isso?
Acabei de descobrir que realmente poderia usar essa funcionalidade no GDscript

Movendo-se para o próximo marco, pois o 3.1 agora está congelado (e o 3.2 tem várias melhorias GDScript planejadas).

Oi, acabei de encontrar este item e queria jogar meus dois centavos.

Se o fatiamento inteligente afetar de alguma forma o desempenho da indexação de array individual, provavelmente devemos evitá-lo. Iterar sobre objetos no GDScript é um caso de uso muito comum para sofrer penalidades de desempenho por causa de um pouco de açúcar sintático.

Embora eu seja a favor do açúcar sintático, acho que o desenvolvedor médio de jogos tem expectativas razoáveis ​​relacionadas à atomicidade e velocidade quando qualquer coisa relacionada a colchetes, chaves, parênteses etc. é implementada em GDScript. Se esse contrato for quebrado, a questão de quando devo enviar algo para a GDNative se torna muito mais nebulosa. Eu acho que uma boa função "sub_array()" ou "slice()" seria o melhor caminho a seguir, porque então (eu suponho) você poderia manter o código de indexação de array existente como está.

Há algum progresso nisso? Eu poderia enviar um PR que adiciona esses métodos.

Ainda quero que isso seja implementado. Qualquer notícia?

Mesmo, eu quero pegar um subconjunto de uma matriz, e parece que tanto as compreensões de lista quanto uma função para fatiar uma matriz genérica não existem. Um deles provavelmente deve ser adicionado, pois a alternativa é um pouco detalhada.

@bojidar-bg

Observe que isso é feito facilmente com range e compreensões de #4716:

var result = array[from:to:step]
# Is the same as:
var result = (array[i] for i in range(from,to,step))

Isso não está correto no momento, pois as compreensões ainda não foram incluídas. A sintaxe atual é:

var result = []
for i in range(from, to, step):
    result.append(array[i])

Estranhamente, os desenvolvedores rejeitaram um PR para esse recurso (#15222) por motivos de legibilidade.

Discutimos isso no IRC com muitos desenvolvedores principais, e a sensação geral é que a sintaxe de compreensão de lista torna o código bastante difícil de ler e vai contra os princípios de design do GDScript para ter uma sintaxe direta e fácil de ler.

Pessoalmente, acho uma linha não mais difícil de ler do que as três. Alguém mais acha que essa conversa deveria ser reaberta?

@SnailBones Acho que ter um método Array.slice() embutido faz mais sentido aqui. Linguagens como JavaScript têm uma função semelhante e parece funcionar bem lá :slightly_smiling_face:

Eu acho que as compreensões de lista seriam boas, mas ter um Array.slice() separado seria útil independentemente.

Estou trabalhando em um método Array.slice agora

Seria mais preferível criar um novo tipo de fatia Variant, como o python faz onde esse objeto de fatia é alimentado na matriz como um operador ou que a chamada para a função slice na matriz seja codificada no compilador? Eu tenho o método slice pronto e estou procurando adicionar a sintaxe start:end:delta à indexação do gdscript.

O objeto slice seria mais "Pythonic" ;) mas o método embutido em código
quase certamente seria mais rápido. De qualquer forma, usando o
sintaxe start:end :delta
seria muito útil.

No sábado, 20 de julho de 2019 às 18h05 Cameron Reikes [email protected]
escrevi:

Seria mais preferível criar um novo tipo de fatia Variant como
python faz isso onde esse objeto de fatia é alimentado na matriz como um
operador, ou para que a chamada para a função slice na matriz seja
codificado no analisador? Eu tenho o método slice feito e estou procurando
para adicionar a sintaxe start:end :delta à indexação do gdscript.


Você está recebendo isso porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/godotengine/godot/issues/4715?email_source=notifications&email_token=ACJUE6P4A4CDQWUS4PSQQH3QAOK2JA5CNFSM4CEI4JPKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2NXQ4Qissue#WW2ZLOORPWSZGOD2NXQ4Qissue
ou silenciar o thread
https://github.com/notifications/unsubscribe-auth/ACJUE6LOTSF243FOYXXR2SDQAOK2JANCNFSM4CEI4JPA
.

Eu só penso em usar um novo tipo de variante de fatia porque assim o fatiamento poderia ser um operador no analisador e funcionaria melhor, porém não sou super experiente nessa área, então seria ótimo ter um dos gdscript devs pesam.

Você está certo sobre isso. Também seria muito mais fácil reutilizar a sintaxe
estrutura para outras coisas mais tarde. Parece-me a melhor opção.

No sábado, 20 de julho de 2019 às 23h28, Cameron Reikes [email protected]
escrevi:

Eu só penso em usar um novo tipo de variante de fatia porque então o fatiamento
poderia ser um operador no analisador e funcionaria melhor


Você está recebendo isso porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/godotengine/godot/issues/4715?email_source=notifications&email_token=ACJUE6IMHLNTYTVL7DITY2TQAPQX3A5CNFSM4CEI4JPKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2N3D4Q#issuecomment
ou silenciar o thread
https://github.com/notifications/unsubscribe-auth/ACJUE6P5Q55EXAWD6IB4ARDQAPQX3ANCNFSM4CEI4JPA
.

Vou ver se consigo encontrar minha implementação antiga que ainda está por aí em algum lugar. Foi 90% finalizado e funcionou mais ou menos como o Python, pois há um objeto slice que você pode usar para indexar em arrays. Você pode até fazer coisas como arr[2:4] = [1,2,3].

Parei de trabalhar nele por causa de restrições de tempo

@brakhane Isso seria muito útil. No momento, estou no processo de adicionar um novo tipo de variante de objeto de fatia para que o ato de fatiar possa ser considerado uma operação, tornando a modificação do analisador muito mais fácil.

@creikey Isso soa bem parecido com a minha abordagem. Eu deletei meu repositório do GitHub, mas posso ter o código ainda em outro lugar. vou postar uma atualização

@creikey Encontrei um WIP não completamente recente (pode haver alguns recursos ausentes nesta versão). Você pode encontrá-lo aqui: https://github.com/brakhane/godot/compare/4c4ab14..8a258c0

Ainda existem alguns bugs, por exemplo, acabei de notar aqui https://github.com/brakhane/godot/compare/4c4ab14..8a258c0#diff -7d521a4f767fb1ae3c908a20616084a4R1446 deve dizer ".end" em vez de ".start"

Se você tiver dúvidas, ficarei feliz em respondê-las. Também vou tentar encontrar uma versão mais recente.

Agora, sou da opinião de que adicionar fatiamento de matriz pythonic em vez de apenas uma função com um limite superior inclusivo está adicionando complexidade desnecessária, pois implicaria a criação de uma nova variante, com pouco benefício em comparação com apenas adicionar um método.

Esta página foi útil?
0 / 5 - 0 avaliações