Comments 28
Есть хоть одна разумная причина делать всё это?
Итого: у нас есть два высокоуровневых языка с динамической типизацией, сопоставимых по скорости выполнения программ. Язык, который получается после трансляции, более прост и визуально понятен, чем язык, который используется для трансляции.
Вывод: делать такую трансляцию — неразумно.
А вот «синтаксис питона проще» — чистая неправда
Что мешает генерировать эти классы при помощи python?
У меня просто была похожая задача и в целом я успешно решил ее через метаклассы + генерация кода.
Возможно, вашу задачу было можно так же решить?
Есть миксины. Есть магическая ф-ия type, которую можно использовать как фабрику классов.
Генерация python кода с помощью lisp может пригодиться… Никогда?
Нужно, для начала, рассмотреть вашу задачу. Почему я говорю, что вы что-то делаете не так: если речь идёт о генерации классов во время исполнения, то есть замечательная функция type(). Она позволяет создавать класс непосредственно в процессе выполнения кода. Т.е. вы пишете фабрики, которые, используя type, формируют классы с нужными методами. В input приходят аргументы, запускается генератор, возвращает вам класс и инстанс, с которым вы уже можете работать. Вот вам и DSL.
Однако, в большинстве случаев, создание такой фабрики не требуется, поскольку мы можем собрать любой сложный функционал, применив «Примеси» или Миксины. Миксины — это такие классы, которые применяются для множественного наследования. Каждый миксин может представлять собой реализацию одного-единственного метода, который будет использоваться в различных реализациях классов.
self.heavy.add_classes([Exorcist, Retributors, PenitentEngines])
self.troops.add_classes([BattleSisters])
self.transports.add_classes([ASRhino, Immolator])
self.hq.add_classes([Celestine, Canoness, Jacobus])
self.fast.add_classes([Dominions, Seraphims])
self.elite.add_classes([ArcoFlagellants, Assassins, Celestians, Dialogus, Hospitaller, Imagifier, Mistress, Priest, Repentia, PriestV2, Crusaders])
Вот это что за трёхколёсник? Не совсем понятно, что оно делает, но если бы мне нужно было собрать отряд, я бы начал вот с чего:
class PriestMixin(object):
def heal_one(target):
# do something
pass
def heal_many(targets):
for target in targets:
self.heal_one(target)
class WarriorMixin(object):
def kick_ass(target):
# kick ass
pass
class KnightMixin(object):
def protect(target):
# protect target
pass
class Patrol(object):
def __init__(self, id, name, containments):
self.id = id
self.name = name
self.unit_classes = [type(cont['name'], (*cont['mixins']), {}) for cont in containments]
self.containment = [unit_class() for unit_class in unit_classes]
Patrol('SuicideSquad', 'Suicide Squad', [
{'name': 'VasyaTheKnight', 'mixins': [PriestMixin, KnightMixin]},
{'name': 'YouraMotherFucker', 'mixins': [WarriorMixin]}
])
Во-вторых, я прекрасно знаю про миксины и пользуюсь ими. Собственно, модель множественного наследования в питоне приводит меня в полное восхищение и щенячий восторг своей удобностью.
В-третьих, речь не шла о динамической генерации классов во время выполнения. В данном случае речь идёт об автоматической генерации кода который будет выполняться когда-то потом. Наличие сгенерированного кода позволяет в дальнейшем его ручную правку, применение к нему инструментов контроля версий — ну и проще в отладке чем динамически сгенерированные типы. Во всяком случае, этим руководствовался я.
Спасибо за совет касающийся приведённого мной примера
Во втором случае, лучше обратить внимание на непосредственно компилируемые языки, на которых можно написать небольшое приложение, которое будет прекрасно исполняться в различных средах и дописывать вредоносный код.
Ну а лиспы в целом довольно часто в другой язык компилируются, в джакузи и Джаваскрипт например
Это так же глупо, как компилировать CSS в scss. Ладно, с компиляцией lisp в js лет пять назад можно было согласиться. Но лисп в Пайтон?! Лисп менее лаконичен и по скорости выполнения может уступать python. К тому же, он хуже читается.
О том, что Hy позволяет упростить часть синтаксиса пайтона, говорить нельзя: он полностью рассчитан на те же самые импорты, подключение библиотек python и их использование. Результирующий код будет выполняться python, и это серьёзно ограничивает возможности Hy.
Разумеется, можно использовать Hy для разработки DSL, рассчитанных на применение различными специалистами, которые не будут учить python. Только вот в чём проблема: Lisp в плане синтаксиса сложнее, чем python. Писать DSL для применения одним Lisp-гуру на всю компанию — экономически не выгодно. Создание же своего синтаксиса DSL проще реализовать на Python.
Да, посмотрел я в гитхабе репу этого Hylang:
Well. Python is awesome. So awesome, that we have so many tools to alter the language in a core way, but we never use them.
Why?
Well, I wrote Hy to help people realize one thing about Python:
It's really awesome.
Oh, and lisps are neat.
Иными словами, Lisp аккуратен, но Hylang был создан для того, чтобы показать, что пайтон лучше :-D Именно поэтому надо сперва читать README, а потом уже пилить обзоры.
Если бы эти языки имели разницу, смысл был бы. Например, если бы python генерировал c++. Это можно было использовать для увеличения производительности в отдельных вычислениях.
Либо, если нам нужно сгенерировать более сложный код с помощью более простого. Например, контроллер поддерживает golang. Но python — лаконичнее, и мы пишем код на python, который транслируется в go.
Но вот использовать устаревший тормознутый высокоуровневый язык, популярный в ИИ, чтобы генерировать код на современном и лаконичном тормознутом языке, популярном в ИИ — верх неблагоразумия.
Но блин Hy, с этой компиляцией в AST, это что-то совсем не то. Интероп есть. Но когда пытаешься что-то сделать, то понимаешь, что проще это сделать сразу на питоне. Может быть все дело в сырости и незрелости. Сами по себе скобочки особых преимуществ не дают. Мультиметоды, например, в Hy в каком-то пред-альфа состоянии.
Скорее, наверное, lumo с нодой быстрее допилят и доведут до пристойного вида.
Генерация кода на Python при помощи Hy