Сравнение возможностей Python и Smalltalk - Metaprogramming

В последнее время я изучал Python и удивляюсь его превосходным возможностям метапрограммирования во время выполнения. Раньше я сталкивался с термином "метапрограммирование времени выполнения", когда я читал о Smalltalk, который, насколько мне известно, обладает лучшими возможностями метапрограммирования во время выполнения. Насколько хорошо Python складывается против Smalltalk w.r.t. метапрограммированием? Каковы заметные различия между подходами, взятыми на двух языках?

Ответ 1

Python на самом деле достаточно хорош здесь. Smalltalk обычно не делает явного различия между программой и метапрограммой, но Python является более явным - например, особый синтаксис для декораторов или соглашение об именах __foo__() для метапрограммирующих крючков. Это хорошая вещь.

С другой стороны, это немного сравнение яблок с апельсинами. Smalltalk - это меньший, более жесткий язык, чем Python, и поэтому есть меньше материалов для манипуляции с метапрограммами. Например, рассмотрим __getattr__(). Это крючок, который позволяет объектам Python предоставлять настраиваемую реализацию доступа к атрибутам. У Smalltalk нет ничего подобного. Но! Smalltalk обеспечивает более жесткую инкапсуляцию внутреннего состояния объекта, и нет эквивалента синтаксиса object.attribute, который используется в Python. Таким образом, чтение состояния объекта требует прохождения метода... что именно предоставляет __getattr__(). Поэтому для многих случаев, когда вы использовали бы __getattr__() в Python, вы просто напишете обычный метод в Smalltalk - не требуется метапрограммирование.

И это так повсюду: Python __getitem__() и друзья позволяют писать классы, имитирующие списки или словари. Smalltalk не нуждается в этом, потому что Array и Dictionary являются обычными классами Smalltalk и специального синтаксиса для их использования нет. Python __eq__() и т.д. Позволяют перегрузить оператор. У Smalltalk нет операторов, поэтому вы можете реализовать +, не делая ничего особенного. Python contextlib предоставляет отличные инструменты для реализации ваших собственных менеджеров контекста. У Smalltalk нет конструкции with, но у нее действительно легкий синтаксис для lambdas, который позволяет вам делать то же самое прямолинейно.

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

Возможности метапрограммирования Smalltalk являются мощными, но они не так аккуратно организованы, как Python, и не используются так часто.

Ответ 2

Отправлено как ответ на запрос участника.

Одна из больших идей Smalltalk - ортогональность. Честно говоря, Python страдает в этом отношении. Не все работает на все. Примеры:

  • inspect.getargspec() не работает со встроенными функциями или результатами вызовов functools.partial (в любом случае интерпретатором C).
  • eval работает только для строк выражений, а exec работает только для строк операторов.
  • Лямбда-выражения не могут быть маринованными.
  • myclass = type('x', (object,), {'__init__': partial(foo, value)}) создает класс, который не может быть создан, тогда как передача эквивалентного выражения lambda вместо partial отлично работает. (Хотя это может быть просто ошибкой, а не особенностью.)

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