Введение
Диалект Lisp
Racket — это универсальный, многопарадигменный язык программирования. Язык Racket является современным диалектом Lisp и происходит от Scheme. Он разработан как платформа для проектирования и реализации языков программирования. Помимо основного языка Racket, термин Racket также используется для обозначения семейства языков программирования и набора инструментов, поддерживающих разработку на Racket и с использованием Racket. Racket также применяется для написания скриптов, обучения информатике и проведения исследований. Платформа Racket предоставляет реализацию языка Racket (включая систему времени выполнения).
Основной язык Racket известен своей мощной макросистемой, которая позволяет создавать встроенные и предметно-ориентированные языки, языковые конструкции, такие как классы или модули, и отдельные диалекты Racket с различной семантикой. Распространение платформы представляет собой бесплатное программное обеспечение с открытым исходным кодом, распространяемое под лицензиями Apache 2.0 и MIT. Расширения и пакеты, разработанные сообществом, могут быть загружены в каталог пакетов Racket.
Разработка
Маттиас Феллейзен основал PLT Inc. в середине 1990-х годов, сначала как исследовательскую группу, а вскоре как проект, посвященный созданию педагогических материалов для начинающих программистов (лекции, упражнения/проекты, программное обеспечение). В январе 1995 года группа решила разработать педагогическую среду программирования на основе Scheme. Мэтью Флатт собрал MrEd, оригинальную виртуальную машину для Racket, из libscheme, wxWidgets и нескольких других бесплатных систем. В последующие годы команда, включавшая Флатта, Робби Финдлера, Шрирама Кришнамурти, Кормака Фланагана и многих других, создала DrScheme, среду программирования для начинающих программистов Scheme и исследовательскую среду для работы с мягкой типизацией. Основной язык разработки, поддерживаемый DrScheme, назывался PLT Scheme. Параллельно команда начала проводить семинары для учителей средних школ, обучая их проектированию программ и функциональному программированию. Полевые испытания с этими учителями и их учениками предоставили важные сведения для направления разработки. В течение следующих лет PLT добавила в DrScheme учебные языки, алгебраический степпер, прозрачный цикл "чтение-вычисление-печать", принтер на основе конструкторов и множество других инноваций, создав среду разработки педагогических программ прикладного качества. К 2001 году основная команда (Феллейзен, Финдлер, Флатт, Кришнамурти) также написала и опубликовала свой первый учебник "Как разрабатывать программы", основанный на их философии обучения. Манифест Racket. Система классов приобретала новые возможности (например, интерфейсы в стиле Java), а также лишалась некоторых (например, множественное наследование) в этих версиях. В отличие от модулей, эти модули не являются объектами первого класса. Версия 300 представила поддержку Unicode, поддержку внешних библиотек и усовершенствования системы классов. 7 июня 2010 года PLT Scheme была переименована в Racket. Переименование совпало с выпуском версии 5.0. Впоследствии графический пользовательский интерфейс (GUI) был переписан на Racket с C++ в версии 5.1 с использованием нативных UI-инструментов на всех платформах. Версия 5.3 включала новую функцию подмодулей для опционально загружаемых модулей, новые инструменты оптимизации, библиотеку JSON и другие возможности. Версия 5.3.1 внесла существенные улучшения в DrRacket: проверка синтаксиса в фоновом режиме включена по умолчанию и был добавлен новый инструмент предварительного просмотра документации. В версии 6.0 Racket выпустила систему управления пакетами второго поколения. В рамках этой разработки основной репозиторий DrRacket и Racket был реорганизован и разбит на множество небольших пакетов, что позволило установить минимальный Racket и устанавливать только необходимые пакеты. Версия 7 Racket была выпущена с новым расширителем макросов, написанным на Racket, в рамках подготовки к переходу на среду выполнения Chez Scheme и поддержке нескольких сред выполнения. 19 ноября 2019 года был выпущен Racket 7.5. Лицензия Racket 7.5 стала менее ограничительной. Теперь используется либо лицензия Apache 2.0, либо лицензия MIT. 13 февраля 2021 года был выпущен Racket 8.0. Racket 8.0 знаменует первый релиз, в котором Racket с системой времени выполнения Chez Scheme, известной как Racket CS, является реализацией по умолчанию. Racket CS быстрее, проще в обслуживании и разработке, обратно совместим с существующими программами Racket и обладает улучшенной параллельной сборкой мусора.
Особенности
Ядро языка Racket включает в себя макросы, модули, лексические замыкания, хвостовые вызовы, ограниченные продолжения, зелёные потоки и потоки ОС, и многое другое. Язык также поставляется с примитивами, такими как пространства событий и распорядители, которые управляют ресурсами и позволяют языку функционировать как операционная система для загрузки и управления другими программами. Большинство языковых конструкций в Racket реализованы как макросы в базовом языке, включая систему классов миксинов. Система контрактов Racket вдохновлена принципами проектирования по контракту, разработанными для Eiffel, и расширяет их для работы со значениями высшего порядка, такими как функции первого класса, объекты, ячейки памяти и так далее. Например, объект, проверяемый контрактом, гарантированно будет выполнять проверки контрактов при вызове его методов. Racket включает в себя как байт-код, так и JIT (Just-In-Time) компиляторы. Байт-код компилятор генерирует внутренний формат байт-кода, исполняемый виртуальной машиной Racket, а JIT компилятор транслирует байт-код в машинный код во время выполнения. С 2004 года язык поставляется с PLaneT – менеджером пакетов, интегрированным в модульную систему, что позволяет прозрачно импортировать и использовать сторонние библиотеки. PLaneT также имеет встроенную политику версионирования для предотвращения конфликтов зависимостей. В конце 2014 года большая часть кода Racket была перенесена в новую систему упаковки, отделённую от основной кодовой базы. Эту новую систему пакетов обслуживает клиентская программа raco. Новая система пакетов предоставляет меньше возможностей, чем PLaneT; в блоге на сайте Racket Джей Маккарти объясняет причины этого изменения и способы воссоздания старой системы.
Racket's contract system is inspired by the Design by Contract work for Eiffel and extends it to work for higher order values such as first class functions, objects, reference cells, and so on. For example, an object that is checked by a contract can be ensured to make contract checks when its methods are eventually invoked. Racket includes both bytecode and JIT (JIT) compilers. The bytecode compiler produces an internal bytecode format run by the Racket virtual machine, and the JIT compiler translates bytecode to machine code at runtime. Since 2004, the language has also shipped with PLaneT, a package manager that is integrated into the module system so that third party libraries can be transparently imported and used. Also, PLaneT has a built in versioning policy to prevent dependency hell. At the end of 2014, much of Racket's code was moved into a new packaging system separate from the main code base. This new packaging system is serviced by a client program named raco. The new package system provides fewer features than PLaneT; a blog post by Jay McCarthy on the Racket blog explains the rationale for the change and how to duplicate the older system.
Интегрированная расширяемость языка и макросы
Особенности, которые наиболее отчетливо отличают Racket от других языков семейства Lisp, – это встроенные средства расширяемости языка, поддерживающие создание новых языков, ориентированных на конкретные задачи и общего назначения. Средства расширяемости Racket интегрированы в модульную систему, обеспечивая контекстно-зависимый и уровневый контроль над синтаксисом, в отличие от гигиенических макросов синтаксиса Scheme 84 или синтаксических правил R5RS. Фактически, справедливо сказать, что макросистема представляет собой тщательно настроенный интерфейс прикладного программирования (API) для расширений компилятора. Используя этот API компилятора, программисты могут добавлять новые возможности и целые языки, специфичные для определенной области, таким образом, чтобы они были полностью неотличимы от встроенных языковых конструкций. Макросистема в Racket использовалась для создания целых языковых диалектов, включая Typed Racket – постепенно типизируемый диалект Racket, облегчающий переход от нетипизированного к типизированному коду, Lazy Racket – диалект с ленивыми вычислениями, и Hackett, сочетающий Haskell и Racket. Педагогический язык программирования Pyret изначально был реализован на Racket. Среди других диалектов можно выделить FrTime (функциональное реактивное программирование), Scribble (язык документации), Slideshow (язык для создания презентаций) и несколько языков для обучения. Базовая поставка Racket предоставляет библиотеки, помогающие в разработке языков программирования. Примером такого языка может служить Racket logic programming.
Применение и практическое применение
Помимо теоретической базы в области теории языков программирования, Racket был разработан как язык общего назначения для создания рабочих систем. Поэтому в состав дистрибутива Racket входит обширная библиотека, охватывающая системное и сетевое программирование, веб-разработку, унифицированный интерфейс к базовой операционной системе, динамический интерфейс для работы с функциями на других языках, различные реализации регулярных выражений, генераторы лексических анализаторов и парсеров.
Racket используется в программе Bootstrap для обучения студентов алгебре посредством разработки игр.