Common Lisp vs Python
love5an — 22.12.2010 Или, "почему Python - говно".Любители Python часто ссылаются на Питера Норвига - он де посмотрел на Python, сравнил с лиспом, и оказалось - они почти не отличаются, так что, выходит, Python - вполне себе полноценная замена лиспу, а то даже и лучше него.
Да, такое имело место быть. Но если подумать - у Норвига вполне могли быть серьезные причины говорить подобное, и причины эти находились не то чтобы в стороне лиспа. То сравнение, вообще говоря, очень сильно отдает предвзятостью - там ведь сравниваются по большей части какие-то совершенно несущественные вещи, вроде синтаксиса доступа к хэш-табличкам.
Ну, так или иначе, я решил сравнить языки собственноручно, и в итоге получил вот такую таблицу:
Common Lisp | Python | |
Функциональное программирование | ||
Полноценные анонимные функции, замыкания; в стандартной библиотеке присутствует множество удобных функций высшего порядка. | Анонимные функции неполноценны. Функциональный стиль не поощряется. | |
Типы данных. | ||
Массивы | Множество типов массивов, в т.ч. многомерных, с разными типами элементов, включая массивы битов и массивы литер (в народе - "строки"). Присутствует возможность создания массивов с изменяемыми размерами и массивов с указателем заполнения. | Массивы - только одномерные, и зачем-то нескольких разных видов (один из которых почему-то называется "списки"). |
Числа | Множество числовых типов, включая дроби, комплексные числа, вещественные числа разных размеров, целые числа фиксированной(причем разной) и произвольной длины. Числовые типы образуют "numerical tower". | Числовых типов мало - int, long, float и complex. Причем int - строго фиксированной длины, и, что неудобно, не является подтипом long. |
ООП | ||
Динамичность | Крайне динамичная объектная система - возможность определения и переопределения классов и методов в рантайме. | reload/eval + см. ниже про MOP |
Диспетчеризация | Мультиметоды; диспетчеризация не только по классу, но и по значению; комбинаторы методов(перепрограммируемость механизма диспетчеризации). | Банальная одиночная диспетчеризация по классам. |
Метаобъектный протокол | Мощный метаобъектный протокол. | Метаобъектный протокол примитивен, утилизирует идею словарей. |
Обработка исключений | ||
Исключения не раскручивают стек вызовов (ср. Windows SEH/синхронные сигналы Unix); присутствует возможность "перезапусков", что позволяет обрабатывать исключения "изнутри", т.е. непосредственно в месте возможного возникновения ошибки. | Механизм обработки исключений примитивен и обычен("как в Java"). | |
Метапрограммирование | ||
Синтаксис и семантика идеальны для парсинга и кодогенерации. | Синтаксис затрудняет парсинг и кодогенерацию. | |
Макросы | Макросы; reader-макросы(перепрограммируемый синтаксис). | Макросы или какой-либо препроцессор отсутствуют. |
eval | eval работает с AST | eval работает со строками |
Многопоточность | ||
В большинстве реализаций используются kernel треды, т.е. возможно SMP. В некоторых реализациях(напр. SBCL) многие операции псевдоатомарны. | Многопоточное программирование затруднено, неудобно и тормозит - GIL(SMP невозможно). | |
Библиотеки | ||
Batteries, которые included | Стандартная библиотека, хотя и превосходит по размеру стандартные библиотеки многих других языков, все же достаточно минималистична. Впрочем, коммерческие реализации имеют достаточно количество "батареек". | В стандартной поставке куча "батареек" для простеньких задач, связанных с обработкой текста и др. |
Open-source библиотеки | Разнообразных open-source библиотек существует довольно немаленькое количество. Большинство из них очень переносимы и работают на большинстве платформ и реализаций. | Открытых библиотек больше, чем для лиспа, в силу большего размера сообщества. Однако, многие из них ориентированы на unix-like платформы, и заставить их не то, что даже работать, а даже собраться, на Windows часто очень сложно. |
Пакетные менеджеры и системы сборки | Де-факто стандарты для
сообщества CL: Quicklisp - простой и удобный пакетный менеджер. Крайне переносимый и написанный полностью на CL(не использует какие-либо внешние утилиты). ASDF - Мощная и многофункциональная, но, в то же время, простая в использовании система сборки, написанная, опять же, полностью на CL. |
Большинство пакетных менеджеров ориентированы на unix-like системы, и под Windows либо не работают вообще, либо глючат, либо требуют более-менее полноценного unix-like окружения, и нетривиальной его настройки. |
Взаимодействие с внешним миром | ||
FFI | Мощные и расширяемые FFI; интерфейсы к .NET и Java; интероперабельность с COM. | ctypes - лучше чем ничего. Имеются реализации Python для .NET и JVM. |
Встраиваемость | Встраиваемые реализации существуют, но в основной своей массе реализации лиспоцентричны. | Легко встраивается. |
Управление памятью | ||
Во всех основных реализациях присутствуют высококачественные отслеживающие сборщики мусора. | В основных реализациях крайне убогая система управления памятью - подсчет ссылок, что влечет дополнительные накладные расходы по памяти и по производительности. В последних версиях присутствует возможность задействовать отслеживающий сборщик, но он не заменяет подсчет ссылок, а только дополняет. | |
Производительность | ||
Трансляция | Основные реализации компилируют непосредственно в машинные коды. Имеются высококачественные оптимизирующие компиляторы, в т.ч. с открытым исходным кодом (например, SBCL). | Основные реализации - интерпретаторы текста или интерпретаторы байткода. Имеются JIT-компиляторы, но производительность полученного кода сильно отстает от такового, сгенерированного компиляторами лиспа. |
Compiler macros | В Common Lisp к каждой глобальной именованной функции можно добавить "макрос компилятора", раскрывающийся "вместо" функции там, где компилятор решает оптимизировать. | Отсутствуют. |
Опциональные декларации типов | Присутствуют | Отсутствуют, за исключением NumPy |
Создание объектов на стеке | Декларация dynamic-extent | Все объекты создаются в динамической памяти. |
Боксинг | Массивы и defstruct-структуры во многих реализациях способны хранить unboxed значения. Кроме того, тип fixnum предполагает реализацию в виде машинного слова с меткой типа, что, соответственно, позволяет эффективную целочисленную арифметику. | Все объекты - boxed. |
Inline-ассемблеры | В основных реализациях присутствуют встроенные ассемблеры. | Inline-ассемблеры отсутствуют по причине интерпретируемости. |
Средства разработки | ||
Emacs + SLIME - мощная
многофункциональная и открытая среда разработки. Де-факто стандарт
для разработчиков на CL. Кроме того, в коммерческих реализациях присутствуют свои навороченные IDE. |
Удобные и полноценные IDE в основном коммерческие(Komodo, PyCharm и др.). Большинство других средств разработки - разной степени удобства(в основном не очень большой) плагины ко всяким Eclipse и текстовым редакторам. | |
Разное | ||
Динамические переменные | В СL переменные могут иметь динамическую область видимости. | Отсутствуют |
Область имен | Отдельные области имен для типов, функций, переменных, goto-меток и т.п. | Область имен одна, что может создавать неудобства в крупных программах и библиотеках. |
Unicode | Полноценная поддержка Unicode в подавляющем большинстве реализаций. | Проблемы с юникодом в Python 2 довольно известны. |
Кривая обучения | В целом, язык довольно большой и сложный (хотя и не настолько, как, скажем, Haskell). Однако, благодаря продуманному дизайну и ортогональности фич, изучается довольно легко, и успешно и продуктивно применять его можно зная далеко не полностью. | Язык невероятно прост, если не сказать примитивен. Буквально, уровень Visual Basic. |
В табличку я старался вынести только те моменты, в которых СL и Python отличаются.
Возможно, в дальнейшем она будет пополняться.
|
</> |