Godot: Нарезка массива для GDScript

Созданный на 19 мая 2016  ·  36Комментарии  ·  Источник: godotengine/godot

было бы неплохо, если бы мы могли использовать функцию pythonish slice, например

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

или даже может быть расширена нарезка с шагом

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

Самый полезный комментарий

синтаксис imho python с : более удобен - меньше символов и более компактный

+1. И меньше путаницы. Мы похожи на Python, поэтому давайте не будем импортировать поведение из всех других языков мира, иначе GDScript станет действительно непоследовательным.

Все 36 Комментарий

Обратите внимание, что это легко сделать с помощью range и вкраплений из #4716:

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

Кроме того, здесь также можно добавить синтаксис CoffeeScript:

x = array[from...to]

Мы могли бы адаптировать это для поддержки размера шага (поскольку они этого не делают):

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

синтаксис imho python с : более удобен - меньше символов и более компактный

синтаксис imho python с : более удобен - меньше символов и более компактный

+1. И меньше путаницы. Мы похожи на Python, поэтому давайте не будем импортировать поведение из всех других языков мира, иначе GDScript станет действительно непоследовательным.

Синтаксис D ($ — размер массива):

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

Просто для справки. Я согласен, что Python лучше подходит для GDScript: P

Я готов работать над этим.

В качестве первого шага я готовлю PR, который добавляет отрицательную индексацию. (Если мы разрешим array[:-1] , мы также должны разрешить array[-1] .)

Как насчет назначения срезов массива? Есть ли варианты использования?

Я уверен, что смогу получить код для его поддержки, но если нет вариантов использования, я могу не беспокоиться об этом.

Я думаю, что одно ограничение, которое мы должны сделать, заключается в том, что замещающие значения должны иметь одинаковый размер (который Python также применяет к структурам, подобным массивам, с фиксированным размером, например байтами).

Другими словами, должно работать следующее:

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

Следующее может:

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

Но это, скорее всего, не будет:

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

Мнения?

Просто для протокола, я все еще работаю над этим. Я могу подготовить PR на следующей неделе, но это может занять больше времени.

@brakhane Никто не торопится - не торопитесь :)

см. № 5701 и № 5765.
Я добавил простую операцию среза с двумя аргументами для привязок DVector и ByteArray, которая с некоторыми будущими привязками может применяться к любому низкоуровневому массиву GDSript (IntArray, StringArray и т. д.). Кода еще нет для обработки -1. Только что понял, что упустил это удобство только сейчас.

Я думаю, что это должно быть реализовано для 3.0, в настоящее время у нас есть только метод subarray(from, to) , реализованный для PoolByteArray, но не для других встроенных типов, поэтому он очень противоречив. Если мы не реализуем что-то последовательное для версии 3.0, я бы предложил вернуть #5879 (который еще не был включен в стабильную версию), чтобы избежать введения API, который может быть заменен позже.

Моя реализация готова на 98% (она работает, но есть некоторые утечки памяти и случайные сбои, на отладку которых у меня не было времени), но из-за нехватки времени я не смогу ее закончить.

Я более чем готов поместить свой WIP в ветку, чтобы кто-нибудь мог (помочь мне) закончить его. Могу помочь с вопросами по реализации. Было бы обидно, если бы мои усилия пропали даром (на данный момент я трачу на это около 40 часов)

Реализация довольно полнофункциональная (и я на самом деле очень горжусь тем, насколько полной она оказалась), например, нарезка работает, как в Python, для большинства типов массивов, включая присваивание (например, a[1:4] = [1,2,3] работает, так что a[1:3] = b[10:13:2] и наоборот).

Однако есть несколько предостережений:

  • реализация довольно сложная, и вы должны иметь некоторое представление о Variant.cpp и variant_op, а также об интерпретаторе байт-кода, чтобы понять это.
  • Чтобы сохранить здравомыслие и помочь в отладке, мне пришлось заменить некоторые макросы в variant_op эквивалентными шаблонами, IMO они делают код более читабельным (и с включенными оптимизациями так же быстро, как и раньше), но поскольку код основан на 2.1, есть вероятно, потребуется некоторый рефакторинг для компиляции с 3.0; также, поскольку код WIP, у меня не было времени разбить его на отдельные коммиты, поэтому иногда макрос заменяется шаблоном, а заодно добавляется и вариантная логика; это немного усложняет (но не слишком) различение двух
  • Чтобы не сделать интерпретатор байт-кода несовместимым со старыми версиями, мне пришлось ввести новый тип данных slice , который необходимо отображать в редакторе. Эта работа сделана, но есть несколько шероховатостей.
  • Как уже было сказано, «единственная» оставшаяся проблема - это некоторое повреждение памяти, которое я не мог понять; тот, кто хочет отладить это, должен быть знаком с тем, как работает интерпретатор байт-кода Godot.

Дайте мне знать, если я должен разместить код где-нибудь. Я думаю, что кто-то, знакомый с внутренностями скрипта godot, исправит ошибки за 10 часов или меньше.

@brakhane , поскольку вы уже проделали работу, было бы здорово, если бы вы поместили код в свою вилку и открыли запрос на извлечение. Таким образом, другие люди могут просматривать и комментировать ваш код.

Как идут дела?
С нетерпением жду этого. :)

@bojidar-bg — наш новый разработчик gdscript, не хотите попробовать? :П

хорошо, буду давить на 3.1

Просто хотел отметить, что метод подмассива использует инклюзивные диапазоны, тогда как он (надеюсь) будет использовать диапазоны нарезки в стиле Python.

Я говорю с надеждой, потому что метод подмассива немного болезненный в использовании, требующий от вас написания специального регистра, чтобы убедиться, что вы никогда не попытаетесь создать срез нулевой ширины (например, если вы пытаетесь использовать часть буфера, разрезая его дважды, «оставшийся» слайс может быть нулевой длины) и добавлять -1 ко всем длинам при запросе слайса.

Редактировать: на самом деле, я не могу придумать ситуацию, в которой вам не нужно было бы добавлять -1 к конечному фрагменту, если только вы не нарезаете байты с постоянным числом и поэтому не можете сделать -1 при его написании.

Есть ли прогресс в этом?
Я только что узнал, что действительно могу использовать эту функцию в GDscript.

Переходим к следующему этапу, поскольку в версии 3.1 функция заморожена (а в версии 3.2 запланированы различные улучшения GDScript).

Привет, я только что наткнулся на этот предмет и хотел добавить свои пять копеек.

Если интеллектуальная нарезка каким-либо образом влияет на производительность индексации отдельных массивов, нам, вероятно, следует избегать ее. Итерация по объектам в GDScript слишком распространена, чтобы страдать от снижения производительности ради небольшого синтаксического сахара.

Хотя я полностью за синтаксический сахар, я думаю, что средний разработчик игр имеет разумные ожидания, связанные с атомарностью и скоростью, когда все, что связано со скобками, фигурными скобками, круглыми скобками и т. д., реализовано в GDScript. Если этот контракт нарушен, то вопрос о том, когда я должен отправить что-то в GDNative, становится гораздо более туманным. Я думаю, что хорошая функция «sub_array()» или «slice()» была бы лучшим способом, потому что тогда (я полагаю) вы могли бы сохранить существующий код индексации массива как есть.

Есть ли прогресс в этом? Я мог бы представить PR, который добавляет такие методы.

Все еще хотят, чтобы это было реализовано. Какие-нибудь Новости?

То же самое, я хочу получить подмножество из массива, и кажется, что и понимание списка, и функция для нарезки универсального массива не существуют. Один из них, вероятно, следует добавить, так как альтернатива немного многословна.

@bojidar-bg

Обратите внимание, что это легко сделать с помощью range и вкраплений из #4716:

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

В настоящее время это неверно, так как понимания еще не включены. Текущий синтаксис:

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

Как ни странно, разработчики отклонили PR для этой функции (#15222) по причинам удобочитаемости.

Мы обсуждали это в IRC со многими основными разработчиками, и общее мнение состоит в том, что синтаксис спискового понимания делает код довольно трудным для чтения и противоречит принципам разработки GDScript, заключающимся в простом и легком для чтения синтаксисе.

Лично я нахожу одну строчку не труднее читать, чем три. Кто-нибудь еще считает, что этот разговор следует возобновить?

@SnailBones Я думаю, что встроенный метод Array.slice() здесь имеет смысл. Такие языки, как JavaScript, имеют аналогичную функцию , и, кажется, там она хорошо работает :slightly_smiling_face:

Я думаю, что понимание списка было бы неплохо, но наличие отдельного Array.slice() было бы полезно в любом случае.

Я сейчас работаю над методом Array.slice

Было бы предпочтительнее создать новый тип слайса Variant, например, как это делает python, когда этот объект слайса передается в массив в качестве оператора, или чтобы вызов функции среза в массиве был жестко закодирован в компиляторе? У меня есть метод slice , и я собираюсь добавить синтаксис start:end:delta в индексирование gdscript.

Объект среза был бы более "Pythonic";), но жестко закодированный метод
почти наверняка будет быстрее. Так или иначе, используя
начало: конец : дельта-синтаксис
было бы очень полезно.

В субботу, 20 июля 2019 г., в 18:05 Кэмерон Рейкес уведомления[email protected]
написал:

Было бы предпочтительнее создать новый тип фрагмента Variant, например, как
python делает это, когда этот объект среза подается в массив как
оператора, либо для вызова функции среза в массиве
жестко запрограммировано в парсере? У меня есть метод среза, и я смотрю
в добавление синтаксиса start:end :delta к индексации gdscript.


Вы получаете это, потому что вы прокомментировали.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/godotengine/godot/issues/4715?email_source=notifications&email_token=ACJUE6P4A4CDQWUS4PSQQH3QAOK2JA5CNFSM4CEI4JPKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD24NXQ4,#59iss5com,59iss5com
или заглушить тему
https://github.com/notifications/unsubscribe-auth/ACJUE6LOTSF243FOYXXR2SDQAOK2JANCNFSM4CEI4JPA
.

Я только думаю использовать новый вариант типа среза, потому что тогда нарезка может быть оператором в синтаксическом анализаторе, и это будет работать лучше, однако я не очень опытен в этой области, поэтому было бы здорово иметь один из gdscript разработчики взвешиваются.

Вы правы. Также было бы намного проще повторно использовать синтаксис
структура для других вещей позже. По мне так лучший вариант.

В субботу, 20 июля 2019 г., в 23:28 Кэмерон Рейкс уведомления[email protected]
написал:

Я думаю только об использовании нового варианта нарезки, потому что тогда нарезка
можно было бы оператором в парсере и было бы лучше


Вы получаете это, потому что вы прокомментировали.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/godotengine/godot/issues/4715?email_source=notifications&email_token=ACJUE6IMHLNTYTVL7DITY2TQAPQX3A5CNFSM4CEI4JPKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWS0ZGOD2N3D41,43-51#issue
или заглушить тему
https://github.com/notifications/unsubscribe-auth/ACJUE6P5Q55EXAWD6IB4ARDQAPQX3ANCNFSM4CEI4JPA
.

Я посмотрю, смогу ли я найти свою старую реализацию, которая все еще где-то валяется. Он был готов на 90% и работал примерно так же, как Python, в том смысле, что есть объект среза, который вы можете использовать для индексации в массивы. Вы даже можете делать такие вещи, как arr[2:4] = [1,2,3].

Я прекратил работу над ним из-за нехватки времени

@brakhane Это было бы очень полезно. Прямо сейчас я нахожусь в процессе добавления нового типа варианта объекта среза, чтобы акт нарезки можно было рассматривать как операцию, что значительно упростило изменение синтаксического анализатора.

@creikey Звучит очень похоже на мой подход. Я удалил свой репозиторий godot на GitHub, но, возможно, код все еще лежит где-то в другом месте. я опубликую обновление

@creikey Я нашел не совсем свежий WIP (в этой версии могут отсутствовать некоторые функции). Вы можете найти его здесь: https://github.com/brakhane/godot/compare/4c4ab14..8a258c0

Есть еще некоторые баги, например я тут только что заметил https://github.com/brakhane/godot/compare/4c4ab14..8a258c0#diff -7d521a4f767fb1ae3c908a20616084a4R1446 должно быть написано ".end" вместо ".start"

Если у вас есть вопросы, я с удовольствием на них отвечу. Я также постараюсь найти более свежую версию.

Теперь я придерживаюсь мнения, что добавление нарезки массива pythonic, а не просто функции с включенной верхней границей, добавляет ненужной сложности, поскольку это повлечет за собой создание нового варианта с небольшой выгодой по сравнению с простым добавлением метода.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги