Godot: Corte de matrices para GDScript

Creado en 19 may. 2016  ·  36Comentarios  ·  Fuente: godotengine/godot

Sería bueno si pudiéramos usar la función de división de Python como

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

o incluso puede extenderse rebanando con paso

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

Comentario más útil

sintaxis imho python con: es más conveniente - menos caracteres y más compacto

+1. Y menos confuso. Somos como Python, así que no importemos comportamientos de todos los demás idiomas del mundo o GDScript se volverá realmente inconsistente.

Todos 36 comentarios

Tenga en cuenta que esto se hace fácilmente con range y comprensiones de #4716:

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

Además, para agregar la sintaxis de CoffeeScript aquí también:

x = array[from...to]

Podríamos adaptar esto para admitir el tamaño del paso (ya que no lo hacen):

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

sintaxis imho python con: es más conveniente - menos caracteres y más compacto

sintaxis imho python con: es más conveniente - menos caracteres y más compacto

+1. Y menos confuso. Somos como Python, así que no importemos comportamientos de todos los demás idiomas del mundo o GDScript se volverá realmente inconsistente.

Sintaxis D ($ es el tamaño de la matriz):

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

Solo para referencia. Estoy de acuerdo en que Python encaja mejor con GDScript: P

Estoy dispuesto a trabajar en este.

Como primer paso estoy preparando un PR que agrega indexación negativa. (Si permitimos array[:-1] , también deberíamos permitir array[-1] ).

¿Qué pasa con la asignación a segmentos de matriz? ¿Hay casos de uso?

Estoy seguro de que puedo obtener el código que lo admita, pero si no hay casos de uso, es posible que no me moleste.

Creo que una restricción que debemos hacer es que los valores de reemplazo deben tener el mismo tamaño (que Python también aplica en estructuras similares a matrices con un tamaño fijo, como bytes)

En otras palabras, lo siguiente debería 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]

Lo siguiente podría:

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

Pero esto probablemente no lo hará:

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

¿Opiniones?

Solo para que conste, todavía estoy trabajando en ello. Es posible que tenga un PR listo la próxima semana, pero puede llevar más tiempo.

@brakhane Nadie tiene mucha prisa, tómese su tiempo :)

ver #5701 y #5765
Agregué una operación simple de división de 2 argumentos a los enlaces DVector y ByteArray que, con algunos enlaces futuros, se pueden aplicar a cualquiera de los tipos de arreglos de bajo nivel de GDSript (IntArray, StringArray, etc.). El código aún no está allí para manejar -1. Acabo de darme cuenta de que dejé esa conveniencia fuera en este momento.

Creo que esto debería implementarse para 3.0, actualmente solo tenemos el método subarray(from, to) implementado para PoolByteArray, pero no para otros tipos integrados, por lo que es muy inconsistente. Si no implementamos algo consistente para 3.0, propongo revertir el #5879 (que aún no se envió en una versión estable) para evitar la introducción de una API que podría reemplazarse más adelante.

Mi implementación está completa en un 98% (funciona, pero hay algunas fugas de memoria y bloqueos aleatorios que no tuve tiempo de depurar), pero debido a las limitaciones de tiempo de la vida real, no podré terminarlo.

Estoy más que dispuesto a poner mi WIP en una sucursal para que alguien pueda (ayudarme) a terminarlo. Puedo ayudar con preguntas sobre la implementación. Sería una pena si mi esfuerzo se desperdiciara (probablemente dedique alrededor de 40 horas hasta ahora)

La implementación es bastante completa (y en realidad estoy bastante orgulloso de lo completo que resultó), por ejemplo, el corte funciona como en Python para la mayoría de los tipos de matrices, incluida la asignación ( a[1:4] = [1,2,3] por ejemplo, funciona, también a[1:3] = b[10:13:2] y viceversa).

Sin embargo, hay algunas advertencias:

  • la implementación es un poco compleja, y debe tener algún conocimiento sobre Variant.cpp y variant_op, así como el intérprete de bytecode para que tenga sentido.
  • Para mantener mi cordura y ayudar con la depuración, tuve que reemplazar algunas de las macros en variant_op con plantillas equivalentes, en mi opinión, hacen que el código sea más legible (y con optimizaciones habilitadas tan rápido como antes), pero dado que el código se basa en 2.1, no probablemente necesite una refactorización para compilar con 3.0; Además, dado que el código es WIP, no tuve tiempo de dividirlo en confirmaciones separadas, por lo que a veces se reemplaza una macro con una plantilla y, al mismo tiempo, también se agrega la lógica de la variante; hace que sea un poco más difícil (pero no demasiado) distinguir los dos
  • Para evitar que el intérprete de código de bytes sea incompatible con versiones anteriores, tuve que introducir un nuevo tipo de datos slice , que debe exponerse en el editor. Este trabajo está hecho, pero hay algunas asperezas.
  • Como ya se dijo, el "único" problema que queda es una corrupción de memoria que no pude resolver; quien quiera depurar esto debe estar familiarizado con el funcionamiento del intérprete de código de bytes de Godot

Avíseme si debo poner el código en alguna parte. Creo que alguien familiarizado con las partes internas del guión de Godot resolverá los problemas en 10 horas o menos.

@brakhane dado que ya tiene trabajo hecho, sería genial si pusiera el código en su bifurcación y abriera una solicitud de extracción. De esta manera, otras personas pueden revisar y comentar su código.

¿Cómo te va?
Esperando esto. :)

@bojidar-bg es nuestro nuevo desarrollador de gdscript, ¿quieres probarlo? :PAGS

bueno, presionaré por 3.1

Solo quería señalar que el método de subarreglo usa rangos inclusivos, mientras que esto (con suerte) usará rangos de corte al estilo de Python.

Digo con suerte porque el método de subarreglo es un poco doloroso de usar, lo que requiere que escriba una carcasa especial para asegurarse de que nunca intente crear un segmento de ancho cero (por ejemplo, si está tratando de consumir parte de un búfer dividiéndolo dos veces, el segmento 'restante' puede tener una longitud cero), y agregar -1 a todas las longitudes al solicitar un segmento.

Editar: de hecho, no puedo pensar en una situación en la parte superior de mi cabeza en la que no necesite agregar un -1 al segmento final, a menos que esté cortando bytes de números constantes y así pueda hacer el -1 al escribirlo.

¿Algún progreso con esto?
Acabo de descubrir que realmente podría usar esta funcionalidad en GDscript

Pasar al siguiente hito ya que 3.1 ahora tiene características congeladas (y 3.2 tiene planeadas varias mejoras de GDScript).

Hola, acabo de encontrar este artículo y quería aportar mis dos centavos.

Si el corte inteligente afecta de alguna manera el rendimiento de la indexación de matrices individuales, entonces probablemente deberíamos evitarlo. Iterar sobre objetos en GDScript es un caso de uso demasiado común como para sufrir penalizaciones de rendimiento por el bien de un poco de azúcar sintáctico.

Si bien estoy a favor del azúcar sintáctico, creo que el desarrollador de juegos promedio tiene expectativas razonables relacionadas con la atomicidad y la velocidad cuando se implementa en GDScript cualquier cosa relacionada con corchetes, llaves, paréntesis, etc. Si ese contrato se rompe, la cuestión de cuándo debo enviar algo a GDNative se vuelve mucho más confusa. Creo que una buena función "sub_array ()" o "slice ()" sería la mejor manera de hacerlo porque entonces (supongo) podría mantener el código de indexación de matriz existente tal como está.

¿Hay algún progreso en esto? Podría enviar un PR que agregue tales métodos.

Todavía quiero que esto se implemente. ¿Hay noticias?

Lo mismo, quiero tomar un subconjunto de una matriz, y parece que no existen las listas de comprensión y una función para dividir una matriz genérica. Probablemente se debería agregar uno de estos, ya que la alternativa es un poco detallada.

@bojidar-bg

Tenga en cuenta que esto se hace fácilmente con range y comprensiones de #4716:

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

Eso no es correcto actualmente, ya que aún no se han incluido las comprensiones. La sintaxis actual es:

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

Extrañamente, los desarrolladores rechazaron una PR para esta característica (#15222) por razones de legibilidad.

Hemos discutido esto en IRC con muchos desarrolladores principales, y la sensación general es que la sintaxis de la comprensión de listas hace que el código sea bastante difícil de leer y va en contra de los principios de diseño de GDScript para tener una sintaxis directa y fácil de leer.

Personalmente, encuentro que una línea no es más difícil de leer que las tres. ¿Alguien más piensa que esta conversación debería reabrirse?

@SnailBones Creo que tener un método Array.slice() incorporado tiene más sentido aquí. Los lenguajes como JavaScript tienen una función similar , y parece funcionar bien ahí :slightly_smiling_face:

Creo que las listas de comprensión estarían bien, pero tener un Array.slice() separado sería útil de todos modos.

Estoy trabajando en un método Array.slice ahora mismo

¿Sería más preferible crear un nuevo tipo de segmento Variant como lo hace Python donde ese objeto de segmento se introduce en la matriz como un operador, o que la llamada a la función de división en la matriz esté codificada en el compilador? Tengo el método slice listo y estoy buscando agregar la sintaxis start:end:delta a la indexación de gdscript.

El objeto de corte sería más "Pythonic";) pero el método codificado
Sería casi seguro que sería más rápido. De cualquier manera, usando el
inicio: fin : sintaxis delta
sería muy útil

El sábado 20 de julio de 2019 a las 18:05 Cameron Reikes [email protected]
escribió:

¿Sería más preferible crear un nuevo tipo de división Variant como
python lo hace donde ese objeto de segmento se introduce en la matriz como un
operador, o para que la llamada a la función de corte en la matriz sea
codificado en el analizador? Tengo el método de corte hecho y estoy buscando
en agregar la sintaxis start:end :delta a la indexación de gdscript.


Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/godotengine/godot/issues/4715?email_source=notifications&email_token=ACJUE6P4A4CDQWUS4PSQQH3QAOK2JA5CNFSM4CEI4JPKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2NXQ459Q,30comment-34,505
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/ACJUE6LOTSF243FOYXXR2SDQAOK2JANCNFSM4CEI4JPA
.

Solo pienso en usar un nuevo tipo de variante de corte porque entonces el corte podría ser un operador en el analizador y funcionaría mejor, sin embargo, no tengo mucha experiencia en esa área, por lo que sería genial tener uno de los gdscript. los desarrolladores opinan.

Tienes razón sobre eso. También sería mucho más fácil reutilizar la sintaxis
estructura para otras cosas más adelante. Me parece la mejor opción.

El sábado 20 de julio de 2019 a las 23:28 Cameron Reikes [email protected]
escribió:

Solo pienso en usar un nuevo tipo de variante de corte porque entonces el corte
podría ser un operador en el analizador y funcionaría mejor


Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/godotengine/godot/issues/4715?email_source=notifications&email_token=ACJUE6IMHLNTYTVL7DITY2TQAPQX3A5CNFSM4CEI4JPKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2N3D4Q3#issue20comment-514,50comment-514
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/ACJUE6P5Q55EXAWD6IB4ARDQAPQX3ANCNFSM4CEI4JPA
.

Veré si puedo encontrar mi implementación anterior que todavía está por ahí. Estaba terminado en un 90% y funcionaba como lo hace Python, en el sentido de que hay un objeto de segmento que puede usar para indexar en matrices. Incluso podrías hacer cosas como arr[2:4] = [1,2,3].

Dejé de trabajar en él por falta de tiempo.

@brakhane Eso sería muy útil. En este momento, estoy en el proceso de agregar un nuevo tipo de variante de objeto de división para que el acto de dividir se pueda considerar una operación, lo que facilita mucho la modificación del analizador.

@creikey Eso suena bastante similar a mi enfoque. Eliminé mi repositorio de GitHub de Godot, pero es posible que aún tenga el código en otro lugar. Publicaré una actualización

@creikey He encontrado un WIP no completamente reciente (puede que falten algunas características en esta versión). Puede encontrarlo aquí: https://github.com/brakhane/godot/compare/4c4ab14..8a258c0

Todavía hay algunos errores, por ejemplo, acabo de notar aquí https://github.com/brakhane/godot/compare/4c4ab14..8a258c0#diff -7d521a4f767fb1ae3c908a20616084a4R1446 debería decir ".end" en lugar de ".start"

Si tiene preguntas, estoy feliz de responderlas. También intentaré encontrar una versión más reciente.

Ahora soy de la opinión de que agregar el corte de matriz pythonic en lugar de solo una función con un límite superior inclusivo agrega una complejidad innecesaria, ya que implicaría crear una nueva variante, con pocos beneficios en comparación con solo agregar un método.

¿Fue útil esta página
0 / 5 - 0 calificaciones