Godot: Аннотации в GDScript

Созданный на 21 июл. 2018  ·  45Комментарии  ·  Источник: godotengine/godot

Около года назад был PR, добавляющий аннотации для GDScript (# 9469). Он был отклонен главным образом потому, что для него не было прямого использования (нет данных в дереве синтаксического анализа, его могли использовать только сторонние инструменты).

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

Для чего можно использовать аннотации?

  • export подсказки. Сейчас он использует собственный синтаксис для каждого типа. С помощью аннотаций он мог напрямую устанавливать использование и подсказку для PropertyInfo, улучшая использование новых дополнений к Inspector без необходимости взламывать новый синтаксис в парсере GDScript.
    Для ясности, я бы оставил ключевое слово export , просто подсказки переместились бы в аннотации. Тип можно определить с помощью подсказок типа.
  • Сюда входят и категории для export (# 4378, # 10303).
  • Замените ключевое слово onready аннотацией.
  • Отключение определенных предупреждений. # 19993 добавить предупреждения со специальным синтаксисом для их отключения, но вместо этого можно использовать аннотации.
  • setget (это странный синтаксис, когда вам нужен только геттер).
  • Ключевые слова RPC ( master , slave , sync , remote ).
  • Новые инструкции препроцессора, например, выполнение компиляции функции только в редакторе (с tool ) или только в режиме отладки (связано с # 12837).
  • Возможное обсуждение нового синтаксиса (например, сигнал, который будет выдаваться при изменении переменной: # 6491).
  • Возможно возможность добавления кастомных «декораторов».

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

С аннотациями будет меньше работы по добавлению определенного атрибута (например, export, setget, onready), вместо этого нужно будет только проверить, какие аннотации присутствуют.

Недостатки
Добавление поддержки аннотаций потребует больше изменений в синтаксический анализатор, чем одно ключевое слово. Это также может побудить людей предлагать новые функции как «просто аннотацию».

Синтаксис
У меня нет особых предпочтений к синтаксису, но я представляю себе что-то вроде декораторов Python. Однако это может сбивать с толку пользователей Python, поскольку аннотации - это не то же самое, что декораторы.

<strong i="41">@onready</strong>
var my_sprite = $Sprite

Для передачи аргументов он может работать как функции:

@export_hint(ENUM)
@export_hint_string("Attack,Defense")
export var my_enum : int = 0

Возможно без скобок:

<strong i="48">@export_hint</strong> ENUM
<strong i="49">@export_hint_string</strong> "Attack,Defense"
export var my_enum : int = 0

Или, возможно, используйте именованные параметры (и избегайте ключевого слова):

<strong i="53">@export</strong> type=String hint=MULTILINE
var my_text = ""

Или что-то другое.

Пользовательские аннотации
Неизвестные аннотации будут просто проигнорированы (возможно, с предупреждением). Таким образом, сторонние инструменты могут анализировать аннотации и предлагать другие возможности, например создание документации.

Также можно добавить API самоанализа: get_method_annotations() , get_property_annotations() или что-то в этом роде. Таким образом, плагины, которые, скажем, ожидают скриптов, могут использовать аннотации, чтобы решить, какой метод вызвать, вместо использования жестко заданного имени.

archived discussion feature proposal gdscript

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

почему синтаксис gdscript так сильно модифицируется? Изначально он был разработан, чтобы быть простым, легким в освоении и интуитивно понятным. Я боюсь, что со всеми этими новыми дополнениями (типизированные gds, аннотации) это запутает новых разработчиков.

Большинство (если не все) изменений синтаксиса GDScript совместимы со старым кодом. Основная цель - повысить продуктивность разработчиков с помощью GDScript, например:

  • Операторы match позволяют использовать операторы switch-case (которые были весьма востребованы) и даже улучшают это, позволяя людям легко сопоставлять массивы и словари.
  • onready переменные (которые были нововведением в 2.x) конкретизируют шаблон, который часто использовался, а именно инициализацию переменных в _ready .
  • Типизированный GDScript позволяет разработчикам наконец отдохнуть, зная, что ошибок неправильного типа не произойдет, и в то же время дает им возможность воспользоваться улучшенным автозаполнением. Это необязательно, поэтому новичкам не нужно изучать его для своей первой игры.

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

Это открытое сообщество. Разработчики игр могут прийти и высказать свое мнение, как и вы. В любом случае пройдет немало времени, прежде чем аннотации станут реальностью.

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

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

Кроме того, наличие трех строк для ключевого слова экспорта очень громоздко по сравнению с простым указанием всего в одной строке. например: onready var my_sprite = $ Sprite намного чище

Синтаксис еще не доработан. Вполне вероятно, что он не заменит сразу ключевые слова onready и export .

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

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

<strong i="6">@description</strong> "Adds two numbers and returns the result."
<strong i="7">@parameter</strong> name=num1 type=float description="The first number"
<strong i="8">@parameter</strong> name=num2 type=float description="The second number"
<strong i="9">@returns</strong> type=float description="num1 and num2 added together"
func add(num1, num2):
    return num1 + num2

И я мог бы вызвать функцию, скажем get_annotations("add") , которая вернет эти аннотации? Даже если эти аннотации не распознаются Годо как какое-то встроенное ключевое слово / аннотация?

@ LikeLakers2 да, в этом суть.

Мне это нравится, я не знаю, какова реализация, но в коде GDscript это выглядело бы намного чище, чем то, как оно выглядит сейчас. Специально для примера setget.

Это очень полезно, но для удобства чтения должно допускать использование однострочных операторов. Например,
<strong i="6">@onready</strong> var a = $A должно быть разрешено. В противном случае это добавит тонну новых строк и в этом случае приведет к потере полезного из уже готового.

Что-то вроде

<strong i="10">@onready</strong>
    var a = $A
    var b = $B
    var c = $C

Было бы полезно применить одну и ту же аннотацию к нескольким операторам.

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

Если аннотации можно анализировать с четким началом и концом, тогда нет необходимости в точках с запятой и при необходимости их можно поместить в ту же строку (если они используют '()', например, или не имеют аргументов)

Я не думаю, что vnen намеревался удалить старые короткие ключевые слова?

Также может помочь ручка с маркером.

Поздно к вечеринке, но вас очень интересует, как это может предоставить категории для переменных экспорта и создать разделы инструментов / сценариев отладки?

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

#### поступает непопулярное мнение:

почему синтаксис gdscript так сильно модифицируется? Изначально он был разработан, чтобы быть простым, легким в освоении и интуитивно понятным. Я боюсь, что со всеми этими новыми дополнениями (типизированные gds, аннотации) это запутает новых разработчиков. например, если бы новый человек в godot посмотрел учебник и увидел код из сообщения LikeLakers2, я бы предположил, что у него взорвется голова. во всяком случае, им придется задать кучу вопросов об этом / как это работает и т. д.

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

Кроме того, наличие трех строк для ключевого слова экспорта очень громоздко по сравнению с простым указанием всего в одной строке. например: onready var my_sprite = $Sprite намного чище (по крайней мере, для меня)

а что касается пункта №4, это можно сделать в редакторе AFAIK. Кроме того, imo, наличие аннотаций повсюду в коде для «отключения определенных предупреждений» может привести к очень грязному коду.

почему синтаксис gdscript так сильно модифицируется? Изначально он был разработан, чтобы быть простым, легким в освоении и интуитивно понятным. Я боюсь, что со всеми этими новыми дополнениями (типизированные gds, аннотации) это запутает новых разработчиков.

Большинство (если не все) изменений синтаксиса GDScript совместимы со старым кодом. Основная цель - повысить продуктивность разработчиков с помощью GDScript, например:

  • Операторы match позволяют использовать операторы switch-case (которые были весьма востребованы) и даже улучшают это, позволяя людям легко сопоставлять массивы и словари.
  • onready переменные (которые были нововведением в 2.x) конкретизируют шаблон, который часто использовался, а именно инициализацию переменных в _ready .
  • Типизированный GDScript позволяет разработчикам наконец отдохнуть, зная, что ошибок неправильного типа не произойдет, и в то же время дает им возможность воспользоваться улучшенным автозаполнением. Это необязательно, поэтому новичкам не нужно изучать его для своей первой игры.

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

Это открытое сообщество. Разработчики игр могут прийти и высказать свое мнение, как и вы. В любом случае пройдет немало времени, прежде чем аннотации станут реальностью.

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

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

Кроме того, наличие трех строк для ключевого слова экспорта очень громоздко по сравнению с простым указанием всего в одной строке. например: onready var my_sprite = $ Sprite намного чище

Синтаксис еще не доработан. Вполне вероятно, что он не заменит сразу ключевые слова onready и export .

Идея мне очень нравится, очень нравятся атрибуты в C #.

Также могут быть интересны аннотации классов и сигналов.

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

Каким может быть процесс определения пользовательских аннотаций? Я бы предпочел, чтобы они не определялись каждый раз в коде свободно, а создавались пользователем с однозначным определением, как классы.

Я думаю, что это требует большего внимания, я думаю, было бы здорово добавить к языку (в качестве необязательного синтаксиса и т. Д.), Чтобы не сбивать с толку новичков, пытающихся вмешаться.

Я думаю, что можно посмотреть на следующий синтаксис:

<strong i="7">@export</strong> type=String, hint=MULTILINE

добавление запятой между «параметрами», я думаю, сделало бы его немного более согласованным с текущим синтаксисом, например:

export (String, MULTILINE) var my_var

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

В будущем следует продолжить обсуждение синтаксиса. В целом идея мне нравится.

Аннотации - хороший способ внедрения конфигурации. Но разделение конфигурации и кода может быть более чистым подходом, ИМО. Может быть, добавление их в виде файлов заголовков будет более полезным.

Из комментария @ bojidar-bg ...

В любом случае пройдет немало времени, прежде чем аннотации станут реальностью.

Может кто-нибудь объяснить, в чем заключается проблема «блокировки», которая задерживает эту реализацию? Это просто знакомство с GDScript / персоналом, или есть определенные функции, которые необходимо реализовать заранее для поддержки аннотаций?

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

Основным препятствием для поддержки аннотаций будет согласие разработчиков ядра по синтаксису и семантике. После этого реализация должна быть относительно простой.

Нам нужно обсудить это с @reduz, поскольку он предпочитает, чтобы аннотации предназначались только для метаданных, они не должны влиять на поведение скрипта или редактора. Это сделало бы мое первоначальное предложение совершенно бессмысленным.

Я по-прежнему считаю, что аннотации достаточно ясны, особенно при замене отдельных ключевых слов ( onready , master , puppet и т. Д.). Но нам еще нужно прийти к консенсусу.

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

Его также можно использовать для элегантного решения этой проблемы 3-летней давности # 6204:

<strong i="8">@export</strong>
<strong i="9">@export_tooltip</strong> "The name used when displaying this item in the inventory and in shops."
var display_name := ""

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

Я согласен с @willnationsdev и хотел бы соединять сигналы по коду с использованием аннотаций, что-то вроде этого может действительно улучшить читаемость кода:

@connect("timeout")
func _on_Timer_timeout():
   ...

@rluders, возможно, при условии, что сценарий находится на узле Timer .

@Zylann, конечно. Простой пример. Он может поддерживать "целевые" параметры и опускать их для самостоятельного подключения. Например, если сценарий выполняется за пределами Timer :

@connect("timeout", $Timer)
func _on_Timer_timeout():
  ...

Я понятия не имею, как это можно реализовать, но мне бы очень хотелось увидеть аннотации в gds, особенно для ключевых слов. И для записи, я бы предпочел, чтобы вместо точки с запятой или новой строки для разделения аннотаций использовался '()'.

Было бы даже лучше, если бы мы могли создавать собственные аннотации + полноценные процессоры аннотаций.

@Zylann, конечно. Простой пример. Он может поддерживать "целевые" параметры и опускать их для самостоятельного подключения. Например, если сценарий выполняется за пределами Timer :

@connect("timeout", $Timer)
func _on_Timer_timeout():
  ...

Это может поддерживаться плагином каким-то образом, я бы не стал делать это основной функцией.
Плагины могут стать еще более мощными.

все, что я могу сказать, это то, что я рад, что изучил gdscript до того, как эти вещи были реализованы, потому что

@export_hint(ENUM)
@export_hint_string("Attack,Defense")
export var my_enum : int = 0

было бы очень сложно разобрать для меня, как новичка

@sleepcircle Мы постараемся сделать GDScript простым во всех случаях. Так что здесь не нужно быть саркастичным: код, который вы процитировали, был всего лишь предложением, а не синтаксисом будущего.

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

Просто хотел выложить свои 0,02 доллара в качестве инструктора по разработке игр. Предупреждение: излишне длинный комментарий, который мало что дает, просто мой 5-летний опыт преподавания программирования о том, как новые разработчики это воспримут.

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

Если @ использовалось исключительно для метаданных, то каждый раз, когда новый разработчик видит @ он распознает его как метаданные, не влияющие на логику их кода. Если это повлияет на логику, важно, чтобы мы не добавляли новые идиомы, которые иногда используются как x, а иногда как y .

Прямо сейчас для изменения переменной есть префиксы, суффиксы и альтернативы var. Я перечислю некоторые вещи, которые не обязательно являются «модификаторами переменных», но новые разработчики могут видеть их такими.

  • Префиксы: onready , export(...)

    • У каждого из них свой тип поведения. onready влияет на загрузку переменных времени выполнения, export - это своего рода подсказка / метаданные редактора. Когда их используют в одном месте, кажется, что их поведение должно быть каким-то образом связано, хотя на самом деле это не так.

  • Альтернативы: class_name , extends , signal , enum , const , func

    • Эти альтернативные форматы кажутся прекрасными, но различать "enum" и "const", скажем, от целых чисел или строк, кажется странным выбором.

  • Суффиксы: setget

    • Setget в отдельной категории - это нормально, но он похож на export в том смысле, что это скорее простое ключевое слово для разработчиков, а не логический сдвиг. Я вижу здесь людей, придерживающихся разных мнений, хотя

  • Где-то посередине: набираем var x : int = 5

    • Такая промежуточная типизация кажется странной, особенно когда "enum" и "const" являются ключевыми словами, альтернативными var, представляющими одно и то же. Определенно аргумент в пользу того, что const похож на setget в том, что он изменяет опыт разработчика больше, чем инструмент для самой игровой логики.

Итак, теперь давайте посмотрим на добавление аннотаций.

Аннотации были бы совершенно новой концепцией / идиомой, которую нужно было бы преподавать новым разработчикам. В идеале новые разработчики должны уметь быстро освоиться и делать вещи, зная как можно меньше идиом, чтобы они могли органично подбирать новые идиомы по мере того, как они становятся для них полезными. Думайте об этом как о дереве технологий.

  • (Уровень 1) Они могут создавать игру, зная только func, var и несколько базовых концепций программирования, таких как вызовы функций, условные выражения и циклы.
  • (Уровень 2) Затем они переходят к изучению полезного сахара / функциональности, например сигналов, const, enum.
  • (Уровень 3) Они изучают ярлыки, такие как setget, onready
  • (Уровень 3.1) Они изучают сахар только для разработчиков, который не изменит их игру, но изменит их процесс , с такими вещами, как экспорт, описания редакторов, инструменты и набор текста.
  • (Уровень 4) Чистая документация и структура проекта

Мне кажется, что уровень 3-4 - это основная цель для аннотаций. Я бы дал своим ученикам две высоты в лифте для двух разных реализаций:

  • Чисто метаданные: «Чтобы помочь с вашей документацией и совместной работой, узнайте об аннотациях, чтобы добавить некоторые метаданные в ваши сценарии. Они более эффективны, чем просто использование комментариев».
  • Сокращения разработчиков / сахар: «Если вы хотите сократить свой код или сделать его более читаемым, обратите внимание на аннотации. Они позволяют вам описывать переменные и функции, предоставляя при этом некоторые инструменты и ярлыки редактора».

Я обучал несколько разработчиков Годо, и я думаю, что делать аннотации по крайней мере вариант уровня 3 и максимум уровня 4. Я бы предпочел не показывать им символ @ пока они уже не будут создают целостные, достаточно сложные игры и стремятся улучшить их процесс .

Это означает, что я придерживаюсь мнения, что мы используем аннотации исключительно для сокращений разработчиков, которые не важны для функциональности игры / имеют альтернативные реализации или просто для документации, поскольку легко сказать людям «изучайте аннотации, когда вы создаете более крупные проекты, для которых нужна документация».

Конкретные моменты из ветки:

  • Они должны подходить для экспорта, поскольку экспорт не критичен для любой игры.
  • Onready - удобный ярлык на ранней стадии, но он не обязателен, поскольку новые разработчики могут начать с инициализации в _ready а перспектива вложенных аннотаций означает, что onready писать гораздо реже.
  • setget - уже такой странный синтаксис, и уже его собственная идиома в качестве единственного суффикса, что он полностью может быть там
  • Подключение: Как я уже сказал, он уже идеально подходит для идиомы вызова функции. Наличие нескольких способов подключения может объединить пространство учебника / образца кода. Возможно, лучше разрешить людям писать свои собственные аннотации, чем стандартизировать это, чтобы разработчики, работающие над закрытыми проектами, могли создать библиотеку аннотаций, которая не обязательно объединяет публичное пространство.
  • Типы: Типы сейчас находятся в странном месте, где некоторые модификаторы типа являются альтернативами, а некоторые модификаторы типа находятся между ними. Может быть, их использование в качестве аннотаций сработает: @type(const int) @type(enum) , что объединит их всех как сахар, ориентированный на разработчиков.

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

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

Я бы предпочел иметь больше ключевых слов

если людям не нравится множество ключевых слов, мы можем удалить некоторые из них

export MyClass : Node2D # export replaces class_name, : replaces extends 

signal mySignal #signal is kept

group(MyHeader, "res://icon.png" )
export var my_property : Array(int) setget _set_my_property, _get_my_property # : replaces export type

var test = 0 # no need for onready. variables declared outside of _ready automatically try to be onready vars

#others are kept

Я полностью согласен с первоначальным предложением.

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

@ Shadowblitz16 Многие из этих предложений сбивают людей с толку по следующим причинам ...

export MyClass : Node2D # export replaces class_name, : replaces extends

export , class_name , : и extends каждый настраивает 4 полностью отдельных точки данных и системы. Вы не можете просто переключить их, не повлияв на другие вещи безвозвратно.

  • export настраивает сгенерированный объект PropertyInfo, который отправляется инспектору для создания графического интерфейса редактора.
  • class_name регистрирует сценарий как глобальный класс в ScriptServer. Технически это не имеет ничего общего с системой типов. Это часть «статической типизации» GDScript только постольку, поскольку она просто создает глобальный экземпляр скрипта во время синтаксического анализа, а не во время выполнения.
  • : используется для дополнительных подсказок типа. Если вы не убедите людей постоянно делать GDScript статически типизированным и / или не предложите альтернативный синтаксис подсказки типа, нет никакого способа перепрофилировать токен двоеточия.
  • extends используется для унаследованного класса (как вы знаете). Это довольно распространенный синтаксис на других языках, и вся документация и руководства уже используют этот метод. Не будет сильного стимула отказаться от этого и создать больше работы по чисто косметическим причинам.
group(MyHeader, "res://icon.png")

Мне непонятно, что это вообще может сделать. Я имею в виду, похоже, что узел будет добавлен в группу «MyHeader» (что может иметь смысл), но для чего нужен значок? Группы не имеют связанных с ними значков.

export var my_property : Array(int) setget _set_my_property, _get_my_property # : replaces export type

Как было сказано ранее, все это влияет на разные системы, а не на одну и ту же систему. Кроме того, могут быть случаи, когда вы хотите, чтобы тип значения или его инициализация были гибкими. Например, в динамическом GDScript вы можете сделать что-то вроде этого:

onready export(NodePath) var the_node = get_node(the_node)
var test = 0 # no need for onready. variables declared outside of _ready automatically try to be onready vars

Инициализировать данные до уведомления о готовности не имеет смысла. Сценарии связаны с классом Object, а не с классом Node. Свойства скрипта инициализируются во время построения. Это не изменится, даже когда вы перейдете к конструктору класса Node. Уведомление _ready() происходит намного позже после создания экземпляра. Различие по умолчанию для инициализации переменных между объектами и узлами было бы чрезвычайно запутанным и привело бы к большому непредсказуемому поведению для тех, кто изучает и использует Godot.


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

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

Изменить: обратите внимание на C # как атрибуты, которые позволяют вам комбинировать их так ..
[Attribute1(), Attribute2()]
однако, хотя это может помочь уменьшить количество строк, это все еще немного уродливо

@ Shadowblitz16 Мы бы предпочли иметь только один очевидный способ делать что-то, когда это возможно. Наличие двух разных синтаксисов противоречило бы этой цели.

@Calinou Я думаю, что gdscript следует оставить как есть, если люди не могут пойти на компромисс.
1 - это без надобности нарушает обратную совместимость
2 - он создает файлы большего размера и менее читаемый код
3 - это заставляет людей переходить на новую систему, к которой они не привыкли.
4 - это заставляет людей использовать систему, которую они могут не захотеть

1 - это без надобности нарушает обратную совместимость
2 - он создает файлы большего размера и менее читаемый код
3 - это заставляет людей переходить на новую систему, к которой они не привыкли.
4 - это заставляет людей использовать систему, которую они могут не захотеть

Честно говоря, это довольно плохие аргументы. 3 из этих 4 пунктов присущи любым большим изменениям в API, и первое из них можно обойти, сохранив некоторое время совместимость со старой системой на основе ключевых слов (вероятно, с предупреждением об устаревании).

_Редактировать: мы могли бы также предоставить инструмент автоматического преобразования. _

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

@groud это использует аннотации для ненужных вещей
1 - почему нам нужно отказаться от того, что работает?
2 - его менее читабельно, если вам нужно прокрутить вниз на 5 строк, чтобы увидеть поле

  • экспорт - это в основном общедоступное ключевое слово для редактора
  • onready - это в основном объявление var перед запуском скрипта

оба не подходят для аннотаций

Определения членов - единственное, для чего я действительно вижу, что это хорошо, и они должны быть сворачиваемыми, в этом случае это не так.

@groud это использует аннотации для ненужных вещей

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

1 - почему нам нужно отказаться от того, что работает?

Для этого есть масса причин. Любая функция может нуждаться в развитии, чтобы обеспечить более чистый API, большую гибкость и т. Д. И как только новая версия будет широко использоваться, по возможности лучше удалить совместимость с предыдущей версией, так как это определенно требует затрат на обслуживание.

2 - его менее читабельно, если вам нужно прокрутить вниз на 5 строк, чтобы увидеть поле

Не нужно преувеличивать. Цель обсуждения такого предложения - позволить синтаксису, достаточно интеллектуальному, чтобы избежать таких проблем. IMHO, подсказки экспорта могут быть интегрированы в качестве аргументов в аннотации экспорта (при условии, что у нас может быть именованная система аргументов, я думаю). В таких ситуациях система могла занимать еще меньше места, чем раньше.

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

экспорт - это в основном общедоступное ключевое слово для редактора
onready - это в основном объявление var перед запуском скрипта
оба не подходят для аннотаций

Что ж, у вас, вероятно, есть предвзятые представления о том, для чего нужны аннотации. Я действительно думаю, что этот вариант использования идеально подходит для системы аннотаций (и похоже, что многие люди). Но на самом деле, я думаю, каждую ситуацию нужно обсуждать индивидуально.

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

<strong i="7">@onready</strong> var my_sprite = $Sprite
@onready; var my_sprite = $Sprite


@export_hint_string("Attack,Defense")
@export_hint(ENUM) export var my_enum : int = 0

@export_hint_string("Attack,Defense")
@export_hint(ENUM); export var my_enum : int = 0


<strong i="8">@export_hint_string</strong> "Attack,Defense";
<strong i="9">@export_hint</strong> ENUM export var my_enum : int = 0

<strong i="10">@export_hint_string</strong> "Attack,Defense"
<strong i="11">@export_hint</strong> ENUM; export var my_enum : int = 0


<strong i="12">@export</strong> type=String hint=MULTILINE; var my_text = ""

# more options

@export(type = String, hint = MULTILINE) var my_text = ""
@export(type = String, hint = MULTILINE); var my_text = ""

@export(String, hint = MULTILINE) var my_text = ""

# I personally prefer this one (positional and named args supported, default/optional args too)
@export(String, MULTILINE) var my_text = ""
@export(String, hint = MULTILINE) var my_text = ""
@export(type = String, hint = MULTILINE) var my_text = ""
@export(int, ENUM, "Attack,Defense") var my_enum:= 0

Изменить: О, я был слишком медленным, @groud уже обратился к аргументу строк. Ну, по крайней мере, эти несколько примеров кода добавили что-то в эту ветку.

это ваше мнение, ребята.
Я лично считаю @ некрасивым

РЕДАКТИРОВАТЬ:
так как же будет работать объявление члена?
это было бы ужасно

<strong i="10">@description</strong> "Adds two numbers and returns the result."
<strong i="11">@parameter</strong> name=num1 type=float description="The first number"
<strong i="12">@parameter</strong> name=num2 type=float description="The second number"
<strong i="13">@returns</strong> type=float description="num1 and num2 added together"
func add(num1, num2):
    return num1 + num2

если его не удалось свернуть с начала @description до начала func

Я считаю, что аннотации не предназначены для замены типов (как, похоже, ваш пример). Если вам не нужны аннотации документации, вам не придется их использовать:

func add(num1: float, num2: float) -> float: return num1 + num2

Эта путаница, вероятно, проистекает из неидеальной ситуации с подсказками экспорта, когда, насколько мне известно, вы не можете использовать реальные типы (и проблема отсутствия общих типов, которые неожиданно поддерживают экспорт подсказок для некоторых типов, таких как массив).

Я лично считаю @ некрасивым
так как же будет работать объявление члена?
это было бы ужасно

На других языках для этой цели обычно служат комментарии, а не аннотации, и они обычно являются такими же или более подробными, чем было предложено. В семействе языков C (наиболее популярных языках) @ довольно часто используется для аннотаций (например, Java, JavaScript, TypeScript, Scala, а также из того, что я читал на Python).

TypeScript (я считаю, что типы в документах не требуются, и инструменты могут использовать фактические типы):

/** Adds two numbers and returns the result.
 * <strong i="16">@param</strong> num1 {float} The first number
 * <strong i="17">@param</strong> num2 {float} The second number
 * <strong i="18">@return</strong> {float} num1 and num2 added together
  **/
const add = (num1: number, num2: number): number => num1 + num2;

Функциональный вкус:

@description("Adds two numbers and returns the result.")
@parameter(num1, "The first number", type=float)
@parameter(num2, "The second number", type=float)
@returns("num1 and num2 added together", type=float)
func add(num1: float, num2: float) -> float:
    return num1 + num2

без повторяющихся типов:

@description("Adds two numbers and returns the result.")
@parameter(num1, "The first number")
@parameter(num2, "The second number")
@returns("num1 and num2 added together")
func add(num1: float, num2: float) -> float:
    return num1 + num2

беспареновый аромат:

<strong i="28">@description</strong> "Adds two numbers and returns the result."
<strong i="29">@parameter</strong> num1 "The first number"
<strong i="30">@parameter</strong> num2 "The second number"
<strong i="31">@returns</strong> "num1 and num2 added together"
func add(num1: float, num2: float) -> float:
    return num1 + num2

Мне больше всего нравится этот синтаксис для комментариев к документам. Я все еще не уверен в использовании аннотаций для целей документации, поскольку для аннотаций, не относящихся к документации, я бы предпочел синтаксис, подобный func.

Я использовал имена аннотаций из предыдущего примера, @parameter может быть просто @param как и в других языках, @description может быть @desc , @descr или @func .

В GodoDoc я использую синтаксис, основанный на TypeScript (TypeDoc, который сам основан на JSDoc и Javadoc), и, на мой взгляд, он работает достаточно хорошо:

## Same as [[bool_]], but `on_false`/`on_true` are functions.
## Only selected function will be called and its return value will be returned from `bool_lazy`.
## <strong i="44">@typeparam</strong> T {any} Return type
## <strong i="45">@param</strong> cond {bool} Condition
## <strong i="46">@param</strong> on_false {FuncLike<T>} Function to call and return its result when `cond` is `false`
## <strong i="47">@param</strong> on_true {FuncLike<T>} Function to call and return its result when `cond` is `true`
## <strong i="48">@return</strong> {T}
func bool_lazy_(cond: bool, on_false, on_true): return GGI.bool_lazy_(cond, on_false, on_true)
var bool_lazy = funcref(self, "bool_lazy_")

если его не удалось свернуть с начала @description до начала func

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

Мне нравится возможность помещать аннотацию впереди или выше, для этого неплохо использовать @annotation(a, b) , с необязательными скобками, если не указаны параметры. Возможность вставки вперед обеспечивает ту же скорость записи, что и сегодняшнее ключевое слово, учитывая, что export и onready очень распространены для свойств.

Однако с точки зрения использования мне тоже не нравится документация. Я привык к аннотациям, влияющим на программу (даже если косвенно), в то время как документация часто утроила их количество для использования в виде комментариев, затем появлялась повсюду и выделялась так же, как функциональные аннотации ... она не подходит для чего-то что повсеместно. В принципе, мне нравится то же использование аннотаций, которое можно найти в C #, что приводит к тому, что гораздо меньше аннотаций нужно писать поверх членов (обычно они довольно редки, не каждый должен писать 5 строк, как показали некоторые примеры) . Если аргумент заключается в том, что у Годо нет API для указания документов сценария, то проблема в том, что ее нельзя решить исключительно с помощью аннотаций IMO. По крайней мере, я предполагаю, что это можно было бы использовать по желанию, но я бы не хотел, чтобы меня заставляли делать это таким образом, что я считаю неудобным для полномасштабной документации. (к тому же скрипты - это не только GDScript, и крайний случай использования _get_property_list делает это еще более неудобным)

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

# No parenthesis when there are no parameters
<strong i="6">@export</strong> var myvar
# With parenthesis for parameters
@export(ENUM, "Up,Down,Left,Right") var myvar2
# Being able to write the annoation on the line before
@export(ENUM, "Up,Down,Left,Right") 
var myvar2

Что касается части документации, я бы еще больше упростил синтаксис (на примере @mnn ):

<strong i="11">@description</strong> "Adds two numbers and returns the result."
<strong i="12">@parameter</strong> "The first number" # No need to name the args if they are ordered
<strong i="13">@parameter</strong> "The second number"
<strong i="14">@returns</strong> "num1 and num2 added together"
func add(num1: float, num2: float) -> float:
    return num1 + num2

Однако я согласен, что разработка другой системы является обязательной, чтобы документация могла быть написана в другом месте. Я бы сказал, что в json, XML или первом файле. Документация в коде подходит не для каждого проекта, и я согласен, что добавление большого количества аннотаций только для документации может раздражать и в некоторых случаях затруднять чтение кода.

Ссылка для релевантности: godotengine / godot-предложения # 177

Довольно поздно для вечеринки, но как разработчик, который сильно полагается на метаданные и отражение при разработке плагинов, мне бы очень хотелось, чтобы аннотации стали частью Godot.

Хотя я действительно думаю, что это делает некоторые вещи более красивыми (например, экспорт и готовые материалы), мой главный аргумент был бы в пользу настраиваемых плагинов, которые могут использовать аннотации в полной мере.

Относительно ключевого слова onready и его ограничений.

Я думаю, можно с уверенностью сказать, что большинство людей используют onready для ранней инициализации ссылок на узлы. За исключением того, что это может оказаться невозможным без проблем в долгосрочной перспективе, потому что, когда вы создаете экземпляры некоторых сцен, которые зависят от _ready , вы можете столкнуться с проблемой ссылки на null :

func explode():
    var bomb = preload("res://explosion.tscn").instance()
    # Oops, forgot to `add_child(bomb)` earlier
    bomb.fuse.wait_time = 5.0 # ERROR: fuse is `null`
    add_child(bomb)
    # ... because `fuse` is a $Timer node 
    # which is only initialized once added to the scene tree.

Конечно, вам нужно add_child() экземпляр сцены, прежде чем пытаться установить fuse , но что, если другие узлы / объекты должны знать точный предохранитель перед добавлением сцены в дерево сцены ?

Через некоторое время я нашел решение, описанное в https://github.com/godotengine/godot/issues/33620#issuecomment -559999681. Как вы можете заметить, onready - это всего лишь NOTIFICATION_READY , в то время как на самом деле мне нужно было NOTIFICATION_INSTANCED и инициализировать мои ссылки еще раньше. Единственная проблема в том, что нет ключевого слова oninstanced , и я думаю, вы можете понять, к чему я веду. 🙂

Итак, я думаю, было бы неплохо переделать ключевое слово onready в качестве аннотации, а также поддержать некоторые другие угловые случаи (например, мой, как всегда!) С функциональностью @oninstanced без раздувания языка сценариев , а также добавлена ​​поддержка других уведомлений, относящихся к инициализации ( _init , _enter_tree и т. д.).

Связанное предложение: godotengine / годот-предложения № 260.

Открыто предложение с более конкретной информацией: https://github.com/godotengine/godot-proposals/issues/828

Заменено вышеуказанным предложением.

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