Сценарный язык

Материал из Википедии — свободной энциклопедии
(перенаправлено с «Скриптовый язык»)
Перейти к навигации Перейти к поиску

Сценарный язык (язык сценариев, жарг. скриптовый язык; англ. scripting language) — высокоуровневый язык сценариев (англ. script) — кратких описаний действий, выполняемых системой. Разница между программами и сценариями довольно размыта. Сценарий — это программа, имеющая дело с готовыми программными компонентами[1].

Согласно Джону Устерхауту, автору языка Tcl, высокоуровневые языки можно разделить на языки системного программирования (англ. system programming languages) и сценарные языки (англ. scripting languages). Последние он также назвал склеивающими языками (англ. glue languages) или языками системной интеграции (англ. system integration languages). Сценарии обычно интерпретируются, а не компилируются[2], хотя сценарные языки программирования один за другим обзаводятся JIT-компиляторами[3][4][5].

В более узком смысле под скриптовым языком может пониматься специализированный язык для расширения возможностей командной оболочки или текстового редактора и средств администрирования операционных систем[6].

Классификация[править | править код]

Языки программирования вообще и сценарные языки в частности могут быть классифицированы множеством различных способов.

В плане быстродействия скриптовые языки можно разделить на языки динамического разбора (sh, COMMAND.COM) и предварительно компилируемые (Perl). Языки динамического разбора считывают инструкции из файла программы минимально требующимися блоками, и исполняют эти блоки, не читая дальнейший код. Предкомпилируемые языки транслируют всю программу в байт-код и затем исполняют его. Некоторые скриптовые языки имеют возможность компиляции программы «на лету» в машинный код (т. н. JIT-компиляция).

По применению языки можно грубо разделить на три типа[7]:

  • командно-сценарные;
  • прикладные сценарные;
  • универсальные сценарные.

Командно-сценарные языки[править | править код]

Появились ещё в 1960-х годах для управления заданиями в операционных системах. Из языков того времени наиболее известен JCL для OS/360. В этот класс входят языки пакетной обработки (англ. batch language) и языки командных оболочек, например sh, csh для Unix. Эти языки чаще всего используются в пакетном режиме обработки[7].

Например, язык AppleScript операционной системы MacOS имеет редактор Script Editor, который позволяет записывать действия по мере их выполнения пользователем в системе в файл сценария (текстовый файл) и оформлять в виде исполняемой программы. Такой подход позволяет составлять простейшие сценарии непрограммирующим пользователем[8].

Встроенные (прикладные сценарные) языки[править | править код]

Сценарные языки этого типа начали появляться в 1980-е годы, когда на промышленных персональных компьютерах стало возможным интерактивное общение с ОС. В клиент-серверной архитектуре такие языки работали в клиентской части программного обеспечения[7].

Языки общего назначения[править | править код]

Этот тип сценарных языков наиболее известен (особенно в применении к веб-программированию). Языки этого типа стали возникать с 1990-х годов[7].

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

Критика[править | править код]

Создатель Java Джеймс Гослинг отвёл динамическим языкам программирования (упомянув PHP и Ruby) роль сценарных языков, генерирующих веб-страницы, но непригодных для применения в более широкой нише приложений из-за проблем с масштабируемостью и производительностью[9]. Приверженцы динамических языков не оставили критику без ответа по всем пунктам, в частности о его старании представить современные динамические языки всего лишь «сценарными»[10].

Плагины и скрипты[править | править код]

Основная статья: Плагин

Для написания пользовательских расширений могут использоваться как скрипты (в терминологии некоторых программ «макросы»), так и плагины (независимые модули, написанные на компилируемых языках; в некоторых программах они могут называться «утилитами», «экспортёрами», «драйверами»).

Скриптовый язык удобен в следующих случаях:

  • Если нужно обеспечить программируемость без риска дестабилизировать систему. Так как, в отличие от плагинов, скрипты интерпретируются, а не компилируются, неправильно написанный скрипт выведет диагностическое сообщение, а не приведёт к системному краху. Контрпримером могут служить, например, JVM и CLR, причём если первая была разработана из соображений переносимости кода (безопасность — побочный эффект), то вторая — именно из соображений безопасности.
  • Если важен выразительный код.
    • Во-первых, чем сложнее система, тем больше кода приходится писать «потому, что это нужно». Впрочем, написание кода «потому, что это нужно» считается крайне плохой практикой (начиная с процедурного программирования), оправданной лишь при построчной оплате труда.
    • Во-вторых, в скриптовом языке может быть совсем другая концепция программирования, чем в основной программе — например, игра может быть монолитным однопоточным приложением, в то время как управляющие персонажами скрипты выполняются параллельно или как сопрограммы. Такой подход хорош с точки зрения масштабируемости системы (сценарии не зависят от реализации процедур, пишутся гораздо быстрее и легче отлаживаются), но не очень хорош с точки зрения качества кода, поскольку неизбежно приводит к его дублированию.
      • Гораздо более рациональным подходом является создание файлов ресурсов (как вариант, xml-файлов, структур, баз данных), описывающих поведение "по существу" (в декларативном стиле), как это делается с другими свойствами внутриигровых объектов (текстуры, модели, эффекты, звуки).
    • В-третьих, скриптовый язык имеет собственный проблемно-ориентированный набор команд, и одна строка скрипта может делать то же, что несколько десятков строк на традиционном языке. Однако стоит заметить, что бо́льшая выразительность кода на сценарных языках является следствием их ограниченности и/или новизны и сравнивать C (1970-е) и PHP (1990-е) и/или Fortran (1950-е) и Python (1990-е) неуместно.
  • Скрипты известны низким порогом вхождения, на скриптовом языке может писать даже низкоквалифицированный программист. Это одновременно и плюс, и минус. С одной стороны, это позволяет нанимать дешёвую рабочую силу (освобождать специалистов от рутинной работы и повышать скорость разработки экстенсивно), а с другой критически снижает производительность и надёжность (из-за ориентированности обучения таким языкам на решение конкретных задач, а не на понимание сущности производимых действий).
    • Проблема высокого порога вхождения возникает, в основном, в языках с избыточным синтаксисом (C++, C#) и может быть полностью решена лишь отказом от них в пользу более удачных (что, разумеется, далеко не всегда возможно). В этом случае скрипты выполняют роль паллиатива. Собственно, они и возникли когда масштабируемость Си-подобных языков стала недостаточной для повседневной работы и порог вхождения новичков в отрасль резко возрос.
    • Проблема большого количества рутины, вообще говоря, неразрешима, но в большинстве случаев может быть сглажена более надёжными дополнительными средствами, например, автоматической кодогенерацией.
  • Если требуется кроссплатформенность. Например, JavaScript — его исполняют браузеры под самыми разными ОС.
    • Проблема с кроссплатформенностью напрямую вытекает из стандарта языка: стандарт Си, например, указывает "sizeOf (short) <= sizeOf (int) <= sizeOf (long)", но не указывает какую именно разрядность они должны иметь (эту проблему решают прикладные библиотеки, например, Glib). Современные не-сценарные языки (Java, C#, Haskell) этой проблемы полностью лишены именно по причине хорошей стандартизации.
  • Скриптовые языки применяются для написания программ, не требующих оптимальности и быстроты исполнения. Из-за простоты на них часто пишутся небольшие одноразовые («проблемные») программы.
    • Многие скриптовые языки общего назначения работают достаточно медленно, поэтому их часто используют только в сочетании со сторонними библиотеками (например, NumPy в сочетании с Python).
      • Это не очень хороший пример, поскольку NumPy основывается на старой фортрановской библиотеке MATHLAB, код которой, хоть и проверен временем, начинает неизбежно "гнить" — писался он под крайне примитивные однопоточные компьютеры с другими узкими местами (и хотя это компенсируется оптимизирующими компиляторами и распараллеливанием на уровне ОС, производительность постепенно снижается).
    • Более правильный пример: язык Lua является классическим встраиваемым языком сценариев общего назначения, для его работы достаточно минимальной реализации Си (везде, где есть Си, может работать и Lua).
    • Также скриптовые языки хороши для визуализации данных: создания сложных графиков и презентаций, а также простых программ (например, Python используется в графических оболочках Gnome и Cinnamon для создания апплетов и небольших настроечных утилит).

У плагинов также есть важные преимущества.

  • Готовые программы, оттранслированные в машинный код, выполняются значительно быстрее скриптов, которые интерпретируются из исходного кода динамически при каждом исполнении. Большинство программ переносимы на уровне исходного кода и могут быть выполнены интерпретатором соответствующего языка подобно скриптам. Использование же байт-кода (Java, C#, LLVM) позволяет хранить, переносить и исполнять программы более эффективным образом, нежели скрипты.
    • JIT-компиляция также позволяет оптимизировать общий код под конкретную платформу (в перспективе, под конкретное семейство процессоров и имеющееся оборудование).
  • Полный доступ к любому аппаратному обеспечению или ресурсу ОС (в скриптовом языке для этого должен существовать специальный API, написанный на компилируемом языке). Плагины, работающие с аппаратным обеспечением, традиционно называют драйверами.
  • Если предполагается интенсивный обмен данными между основной программой и пользовательским расширением, для плагина его обеспечить проще.
  • Если языки программирования созданы в разное время и для разных целей, их сравнение по выразительной силе некорректно. Совершенно естественно, что, например, алголоподобные языки (создавались в 60-х и 70-х) будут менее выразительны, чем современные скриптовые языки общего назначения. В сравнении же с "ровесниками" скрипты выглядят уже гораздо менее выгодно.
  • Для компилируемых языков программирования характерно использование сильной статической системы типов, которая позволяет эффективно отлавливать ошибки и лучше оптимизировать код. Использование же в современных скриптах динамической типизации обусловлено скорее техническими особенностями реализации и историческими причинами. Также у статически типизированных языков есть потенциал для роста, а именно, переход с традиционной мономорфной типизации на полиморфную. Расширения мономорфизма в современных Си-подобных языках (перегрузка, ad-hoc-полиморфизм) и полиморфизм подтипов, а также параметрический полиморфизм и классы типов в экспериментальных языках (например, Haskell) сценарным языкам недоступен (статическая типизация во время исполнения скрипта приведёт к существенной потере производительности).

Примечания[править | править код]

Литература[править | править код]

Ссылки[править | править код]