Pull to refresh

Comments 2

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

интересно будет подумать как сделать такое на C#

а что вам не нравится в partial классах на C#? я про ваш пример с Godot

  1. Да, функции тоже можно. Так работает кодоген по Swagger и т.п. Однако по моему опыту в F# на основе внешнего источника данных чаще генерируются структуры данных, а не функции. Для последних характерно использование рефлексии по существующим библиотекам, то есть источник данных скорее внутренний.

  2. Лет 6-7 назад в C# уже был рослин, которые позволял ворочить AST непосредственно в VS. Я практически не пробовал вытаскивать его наружу, но не думаю, что это вызовит серьёзные сложности. Кроме того в C# есть сорсгены, но они обычно подразумевают более общие задачи без серьёзной кастомизации.

  3. partial в неумелых руках может превратить проект в кашу, но в случае с Godot разрабы накидали своих фишек.

В Godot всё описывается через ноды, которые могут вкладываться друг в друга без ограничений, за счёт чего получаются очень раскидистые деревья. Это напоминает UI-фреймворки, но в качестве ноды может быть объект, который отвечает только за логику и вообще никак не взаимодействует с UI. У этих нод есть свойства и события, но они полностью не закрывают всех фич, часть из которых доступна только через переопределение методов. Проблема в том, что просто переопределить метод недостаточно, ещё важно сделать это в нужном месте проекта.

Для того, чтобы Godot узнал о override в типе, этот тип должен лежать в C#-проекте и быть partial. Если я просто закину анонимную ноду в глубине сцены:

{ new Node() with
    override this._Process delta =
        if Input.IsKeyPressed Key.Shift then
            GD.print "Shift pressed!!!"
}

То Godot никогда не вызовет метод _Process, потому что будет считать, что он не был изменён. Я пока не понял, почему они сделали именно так, но проблему приходится решать через создание прослойки вида:

public partial class InCSharp : InFSharp
{
    public override void _Process(double delta) => base._Process(delta);
}

На каждый тип вида:

type InFSharp () =
    override this._Process delta = 
        ()

Получается, что я:

  • Не могу избавиться от C#-проекта.

  • Вынужден дублировать все ключевые типы с переопределениями.

  • Вынужден создавать их через фабрики, так как вместо InFSharp() мне надо неявно вызвать InCSharp().

Кроме того есть проблемы с экспортируемыми свойстваи и сигналами, которые также надо протаскивать через C#.

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

Sign up to leave a comment.