Scheme | |
---|---|
| |
Семантика | функциональный |
Класс языка | язык программирования, мультипарадигмальный язык программирования, язык функционального программирования, процедурный язык программирования[d], metaprogramming language[d] и off-side rule language[d] |
Тип исполнения | интерпретатор или компилятор |
Появился в | 1975 |
Автор | Гай Стил и Джеральд Сассмен |
Расширение файлов |
.scm, .ss |
Выпуск |
|
Система типов | строгая, динамическая |
Основные реализации: | PLT Scheme, MIT Scheme, Scheme48, Guile, JScheme |
Диалекты | T |
Испытал влияние | Lisp, ALGOL |
Повлиял на | Common Lisp, JavaScript, R, Ruby, Dylan, Lua, Hop, Racket |
Сайт | scheme-reports.org |
Scheme [skiːm] — это функциональный язык программирования, один из двух[1] наиболее популярных в наши дни диалектов языка Лисп (наряду с Common Lisp ). Авторы языка Scheme — Гай Стил (англ. Guy L. Steele) и Джеральд Сассмен (англ. Gerald Jay Sussman) из Массачусетского технологического института — создали его в середине 1970-х годов.
При разработке Scheme упор был сделан на элегантность и простоту языка. Философия языка подчёркнуто минималистская. Его цель — не сваливать в кучу разные полезные конструкции и средства, а напротив — удалить слабости и ограничения, вызывающие необходимость добавления в язык новых возможностей. В результате, Scheme содержит минимум примитивных конструкций и позволяет выразить все, что угодно путём надстройки над ними. В качестве примера можно указать, что язык использует 2 механизма организации циклов:
Scheme начинался с попытки понять модель акторов Карла Хьюитта, для чего Стил и Сассман написали «крошечный интерпретатор Лиспа», а затем «добавили механизм создания акторов и посылки сообщений». Scheme был первым диалектом Лиспа, применяющим исключительно статические (а не динамические) области видимости переменных, гарантирующим оптимизацию хвостовой рекурсии и поддерживающим данные булевского типа (#t и #f вместо традиционных T и NIL). Он также был одним из первых языков, непосредственно поддерживающих продолжения. Начиная со спецификации R⁵RS, язык приобрел исключительно мощное и удобное средство для записи макросов на основе шаблонов синтаксического преобразования с «соблюдением гигиены» (англ. hygienic macro). В Scheme также реализована «сборка мусора», то есть автоматическое освобождение памяти от неиспользуемых более объектов.
В качестве базовых структур данных язык использует списки и одномерные массивы («векторы»). В соответствии с декларируемым минимализмом, (пока) нет стандартного синтаксиса для поддержки структур с именованными полями, а также средств ООП — все это может быть реализовано программистом по его предпочтению, хотя большинство реализаций языка предлагают готовые механизмы.
Как курьёз, можно отметить, что первоначальное название языка Schemer было изменено на настоящее из-за ограничения на длину имён файлов в ITS[en].
0 (+ 2 (* 2 2))
1 > 6
2 (+ 1 2 3 4)
3 > 10
Вызов каждой операции (или функции) представляется списком, в котором символ операции (который, в сущности, является именем функции) всегда занимает начальную позицию.
(number? 5)
(number? "foo")
(string? "foo")
По соглашению, имена всех предикатов заканчиваются символом ?
.
(equal? "foo" "bar")
(eqv? 5 (+ 2 3))
(eq? 'a 'A)
(define-syntax push!
(syntax-rules ()
((push! x l)
(set! l (cons x l)))))
(define-syntax pop!
(syntax-rules ()
((pop! l)
(let ((x (car l)))
(set! l (cdr l))
x))))
;; факториал в (неэффективном) рекурсивном стиле
(define (fact x)
(if (< x 2)
1
(* (fact (- x 1)) x)))
;; функция Фибоначчи — требует параллельной рекурсии
(define (fib n)
(cond ((= n 0) 0)
((= n 1) 1)
(else (+ (fib (- n 1))
(fib (- n 2))))))
;; сумма элементов списка в характерном для Scheme стиле
;; (вспомогательная функция loop выражает цикл с помощью
;; хвостовой рекурсии и переменной-аккумулятора)
(define (sum-list x)
(let loop ((x x) (n 0))
(if (null? x)
n
(loop (cdr x) (+ (car x) n)))))
(fact 14)
(fib 10)
(sum-list '(6 8 100))
(sum-list (map fib '(1 2 3 4)))
Определение функции должно соответствовать следующему прототипу:
(define имя-функции (lambda (аргументы) (реализация-функции)))
хотя на практике чаще используют сокращённую форму:
(define (имя-функции аргументы) (реализация-функции))
Для ввода и вывода в Scheme используется тип порт (R5RS sec 6.6)[2]. R5RS определяет два стандартных порта, доступные как current-input-port
и current-output-port
, отвечающие стандартным потокам ввода-вывода Unix. Большинство реализаций также предоставляют current-error-port
. Перенаправление ввода-вывода поддерживается в стандарте с помощью процедур with-input-from-file
и with-output-to-file
. У реализаций также имеются строковые порты, с помощью которых многие операции ввода-вывода могут выполняться со строковым буфером вместо файла, используя процедуры из SRFI 6[3]. Стандарт R6RS определяет более сложные процедуры для работы с портами и много новых типов портов.
Следующие примеры написаны на R5RS Scheme.
(write (+ (read) (read)))
Вывод в порт по умолчанию (current-output-port):
(let ((hello0 (lambda() (display "Hello world") (newline))))
(hello0))
Передача порта в качестве аргумента:
(let ((hello1 (lambda (p) (display "Hello world" p) (newline p))))
(hello1 (current-output-port)))
Перенаправление вывода в файл:
(let ((hello0 (lambda () (display "Hello world") (newline))))
(with-output-to-file "outputfile" hello0))
Явное открытие файла и закрытие порта:
(let ((hello1 (lambda (p) (display "Hello world" p) (newline p)))
(output-port (open-output-file "outputfile")))
(hello1 output-port)
(close-output-port output-port)
)
call-with-output-file:
(let ((hello1 (lambda (p) (display "Hello world" p) (newline p))))
(call-with-output-file "outputfile" hello1))
Подобные процедуры есть и для ввода. R5RS Scheme предоставляет предикаты input-port?
и output-port?
. Для символьного ввода и вывода существуют write-char
, read-char
, peek-char
и char-ready?
. Для чтения и записи выражений Scheme используются процедуры read
и write
. Если порт достиг конца файла при операции чтения, возвращается eof-объект, который может быть распознан предикатом eof-object?
.
Из-за минимализма Scheme, многие общие процедуры и синтаксические формы не определены в стандарте. Для того, чтобы сохранить ядро языка малым и способствовать стандартизации расширений, в сообществе Scheme принят процесс "Scheme Request for Implementation" (запрос на реализацию), с помощью которого предлагаемые расширения проходят тщательное обсуждение. Это способствует переносимости кода. Многие SRFI поддерживаются всеми или большинством реализаций Scheme.
Достаточно широко поддерживаются реализациями следующие SRFI:[4]
cond-expand
receive
: привязка к нескольким значениямset!
args-fold
: процессор аргументов программыcond
Полный список принятых SRFI доступен на http://srfi.schemers.org/final-srfis.html
Список примеров в этом разделе не основывается на авторитетных источниках, посвящённых непосредственно предмету статьи или её раздела. |
Проект Armpit Scheme реализует интерпретатор для микроконтроллеров на базе архитектуры ARM[5].
Для улучшения этой статьи по информационным технологиям желательно: |
Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".
Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.
Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .