Scheme

Поделись знанием:
Перейти к: навигация, поиск
Scheme
Семантика:

функциональный

Тип исполнения:

интерпретатор или компилятор

Появился в:

1975

Автор:

Гай Стил и Джеральд Сассмен

Расширение файлов:

.scm, .ss

Система типов:

строгая, динамическая

Основные реализации:

PLT Scheme, MIT Scheme, Scheme48, Guile, JScheme

Диалекты:

T (англ.)

Испытал влияние:

Lisp, ALGOL

Повлиял на:

Common Lisp, JavaScript, R, Ruby, Dylan, Lua, Hop (англ.), Racket

Scheme [skiːm] — это функциональный язык программирования, один из трёх наиболее популярных в наши дни диалектов языка Лисп (другие популярные диалекты — это Common Lisp и Clojure). Авторы языка Scheme — Гай Стил (англ. Guy L. Steele) и Джеральд Сассмен (англ. Gerald Jay Sussman) из Массачусетского технологического института — создали его в середине 1970-х годов.





Введение

При разработке Scheme упор был сделан на элегантность и простоту языка. Философия языка подчёркнуто минималистская. Его цель — не сваливать в кучу разные полезные конструкции и средства, а напротив — удалить слабости и ограничения, вызывающие необходимость добавления в язык новых возможностей. В результате, Scheme содержит минимум примитивных конструкций и позволяет выразить все, что угодно путём надстройки над ними. В качестве примера можно указать, что язык использует 2 механизма организации циклов:

  1. хвостовая рекурсия,
  2. итеративный подход (в котором используются временные переменные для сохранения промежуточного результата).

Scheme начинался с попытки понять модель акторов Карла Хьюитта, для чего Стил и Сассман написали «крошечный интерпретатор Лиспа», а затем «добавили механизм создания акторов и посылки сообщений». Scheme был первым диалектом Лиспа, применяющим исключительно статические (а не динамические) области видимости переменных, гарантирующим оптимизацию хвостовой рекурсии и поддерживающим данные булевского типа (#t и #f вместо традиционных T и NIL). Он также был одним из первых языков, непосредственно поддерживающих продолжения. Начиная со спецификации R^5RS, язык приобрел исключительно мощное и удобное средство для записи макросов на основе шаблонов синтаксического преобразования с «соблюдением гигиены» (англ. hygienic macro). В Scheme также реализована «сборка мусора», то есть автоматическое освобождение памяти от неиспользуемых более объектов.

В качестве базовых структур данных язык использует списки и одномерные массивы («векторы»). В соответствии с декларируемым минимализмом, (пока) нет стандартного синтаксиса для поддержки структур с именованными полями, а также средств ООП — все это может быть реализовано программистом по его предпочтению, хотя большинство реализаций языка предлагают готовые механизмы.

Как курьёз, можно отметить, что первоначальное название языка Schemer было изменено на настоящее из-за ограничения на длину имён файлов в ITS[en].

Примеры

Простые математические операции

(+ 2 (* 2 2))
> 6
(+ 1 2 3 4)
> 10

Вызов каждой операции (или функции) представляется списком, в котором символ операции (который, в сущности, является именем функции) всегда занимает начальную позицию.

Предикаты типа

(number? 5)
(number? "foo")
(string? "foo")

По соглашению, имена всех предикатов заканчиваются символом ?.

Проверки на равенство

(equal? "foo" "bar")
(eqv? 5 (+ 2 3))
(eq? 'a 'A)

Определение макросов для традиционных операций push/pop

(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)
      x
      (* (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)[1]. R5RS определяет два стандартных порта, доступные как current-input-port и current-output-port, отвечающие стандартным потокам ввода-вывода Unix. Большинство реализаций также предоставляют current-error-port. Перенаправление ввода-вывода поддерживается в стандарте с помощью процедур with-input-from-file и with-output-to-file. У реализаций также имеются строковые порты, с помощью которых многие операции ввода-вывода могут выполняться со строковым буфером вместо файла, используя процедуры из SRFI 6[2]. Стандарт 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?.

SRFI

Из-за минимализма Scheme, многие общие процедуры и синтаксические формы не определены в стандарте. Для того, чтобы сохранить ядро ​​языка малым и способствовать стандартизации расширений, в сообществе Scheme принят процесс "Scheme Request for Implementation" (запрос на реализацию), с помощью которого предлагаемые расширения проходят тщательное обсуждение. Это способствует переносимости кода. Многие SRFI поддерживаются всеми или большинством реализаций Scheme.

Достаточно широко поддерживаются реализациями следующие SRFI:[3]

  • 0: проверка наличия расширений с помощью cond-expand
  • 1: библиотека для списков
  • 4: гомогенные числовые векторы
  • 6: строковые порты
  • 8: receive: привязка к нескольким значениям
  • 9: record типы
  • 13: библиотека для строк
  • 14: библиотека наборов символов
  • 16: синтаксис для процедур переменной арности
  • 17: обобщенный set!
  • 18: поддержка многопоточности
  • 19: типы данных и процедуры работы со временем
  • 25: многомерные массивы
  • 26: нотация для фиксации аргументов процедуры без каррирования
  • 27: источники случайных битов
  • 28: базовое форматирование строк
  • 29: локализация
  • 30: вложенные многострочные комментарии
  • 31: специальная форма рекурсивного выполнения
  • 37: args-fold: процессор аргументов программы
  • 39: parameter objects
  • 41: потоки данных
  • 42: eager comprehensions
  • 43: библиотека векторов
  • 45: примитивы для выражения ленивых итерационных алгоритмов
  • 60: битовые операции
  • 61: более общий cond
  • 66: векторы октетов
  • 67: процедуры сравнения

Полный список принятых SRFI доступен на srfi.schemers.org/final-srfis.html

Основные реализации

  • [www.gnu.org/software/guile/ GNU Guile] «Официальный» язык расширений проекта GNU. Этот интерпретатор Scheme реализован как библиотека, позволяющая приложениям создавать внутренний интерпретатор Scheme.
  • [groups.csail.mit.edu/mac/projects/scheme/ MIT Scheme] Свободная (GPL-licensed) реализация для платформы x86 под GNU/Linux, FreeBSD, IBM OS/2, и Win32.
  • [www.call-cc.org/ Chicken Scheme] Интерпретатор Scheme, поддерживающий трансляцию в C.
  • [dynamo.iro.umontreal.ca/~gambit/wiki/index.php/Main_Page Gambit Scheme]
  • [www.racket-lang.org/ Racket] (ранее PLT Scheme)
  • JScheme

Проект Armpit Scheme реализует интерпретатор для микроконтроллеров на базе архитектуры ARM[4].

Напишите отзыв о статье "Scheme"

Литература. Учебники

  • [mitpress.mit.edu/sicp/ Structure and Interpretation of Computer Programs] (англ.)
  • [swiss.csail.mit.edu/classes/6.001/abelson-sussman-lectures/ Видео-лекции «Structure and Interpretation of Computer Programs»], Harold Abelson и Gerald Jay Sussman (англ.)
  • [www.scheme.com/tspl/ The Scheme Programming Language], R. Kent Dybvig (англ.)

См. также

Примечания

  1. Richard Kelsey (August 1998). «[www.schemers.org/Documents/Standards/R5RS/ Revised5 Report on the Algorithmic Language Scheme]». Higher-Order and Symbolic Computation 11 (1): 7–105. DOI:10.1023/A:1010051815785. Проверено 2012-08-09.
  2. William D Clinger. [srfi.schemers.org/srfi-6/srfi-6.html SRFI 6: Basic String Ports]. The SRFI Editors, schemers.org (1 июля 1999). Проверено 9 августа 2012.
  3. [srfi.schemers.org/srfi-implementers.html Scheme Systems Supporting SRFIs]. The SRFI Editors, schemers.org (30 августа 2009). Проверено 9 августа 2012.
  4. [armpit.sourceforge.net/ A Scheme Interpreter for ARM Microcontrollers]

Ссылки

На русском языке
  • [ru_scheme.livejournal.com/ ru_scheme] — сообщество в LiveJournal, посвящённое языку Scheme
На английском языке
  • [www.schemers.org/ A large collection of Scheme resources]. Большая коллекция ресурсов по Scheme.
  • [practical-scheme.net/gauche/ Gauche] Интерпретатор Scheme
  • [www.gnu.org/software/kawa/ Kawa] Программа для Scheme, написанная на Java, которая компилирует тексты Scheme программ в Java bytecode. Любая Java библиотека может быть легко использована в Kawa.
  • [community.schemewiki.org Сообщество schemewiki.org]

Отрывок, характеризующий Scheme

Ты, без которой счастье было бы для меня невозможно,
Нежная меланхолия, о, приди, меня утешить,
Приди, утиши муки моего мрачного уединения
И присоедини тайную сладость
К этим слезам, которых я чувствую течение.]
Жюли играла Борису нa арфе самые печальные ноктюрны. Борис читал ей вслух Бедную Лизу и не раз прерывал чтение от волнения, захватывающего его дыханье. Встречаясь в большом обществе, Жюли и Борис смотрели друг на друга как на единственных людей в мире равнодушных, понимавших один другого.
Анна Михайловна, часто ездившая к Карагиным, составляя партию матери, между тем наводила верные справки о том, что отдавалось за Жюли (отдавались оба пензенские именья и нижегородские леса). Анна Михайловна, с преданностью воле провидения и умилением, смотрела на утонченную печаль, которая связывала ее сына с богатой Жюли.
– Toujours charmante et melancolique, cette chere Julieie, [Она все так же прелестна и меланхолична, эта милая Жюли.] – говорила она дочери. – Борис говорит, что он отдыхает душой в вашем доме. Он так много понес разочарований и так чувствителен, – говорила она матери.
– Ах, мой друг, как я привязалась к Жюли последнее время, – говорила она сыну, – не могу тебе описать! Да и кто может не любить ее? Это такое неземное существо! Ах, Борис, Борис! – Она замолкала на минуту. – И как мне жалко ее maman, – продолжала она, – нынче она показывала мне отчеты и письма из Пензы (у них огромное имение) и она бедная всё сама одна: ее так обманывают!
Борис чуть заметно улыбался, слушая мать. Он кротко смеялся над ее простодушной хитростью, но выслушивал и иногда выспрашивал ее внимательно о пензенских и нижегородских имениях.
Жюли уже давно ожидала предложенья от своего меланхолического обожателя и готова была принять его; но какое то тайное чувство отвращения к ней, к ее страстному желанию выйти замуж, к ее ненатуральности, и чувство ужаса перед отречением от возможности настоящей любви еще останавливало Бориса. Срок его отпуска уже кончался. Целые дни и каждый божий день он проводил у Карагиных, и каждый день, рассуждая сам с собою, Борис говорил себе, что он завтра сделает предложение. Но в присутствии Жюли, глядя на ее красное лицо и подбородок, почти всегда осыпанный пудрой, на ее влажные глаза и на выражение лица, изъявлявшего всегдашнюю готовность из меланхолии тотчас же перейти к неестественному восторгу супружеского счастия, Борис не мог произнести решительного слова: несмотря на то, что он уже давно в воображении своем считал себя обладателем пензенских и нижегородских имений и распределял употребление с них доходов. Жюли видела нерешительность Бориса и иногда ей приходила мысль, что она противна ему; но тотчас же женское самообольщение представляло ей утешение, и она говорила себе, что он застенчив только от любви. Меланхолия ее однако начинала переходить в раздражительность, и не задолго перед отъездом Бориса, она предприняла решительный план. В то самое время как кончался срок отпуска Бориса, в Москве и, само собой разумеется, в гостиной Карагиных, появился Анатоль Курагин, и Жюли, неожиданно оставив меланхолию, стала очень весела и внимательна к Курагину.
– Mon cher, – сказала Анна Михайловна сыну, – je sais de bonne source que le Prince Basile envoie son fils a Moscou pour lui faire epouser Julieie. [Мой милый, я знаю из верных источников, что князь Василий присылает своего сына в Москву, для того чтобы женить его на Жюли.] Я так люблю Жюли, что мне жалко бы было ее. Как ты думаешь, мой друг? – сказала Анна Михайловна.
Мысль остаться в дураках и даром потерять весь этот месяц тяжелой меланхолической службы при Жюли и видеть все расписанные уже и употребленные как следует в его воображении доходы с пензенских имений в руках другого – в особенности в руках глупого Анатоля, оскорбляла Бориса. Он поехал к Карагиным с твердым намерением сделать предложение. Жюли встретила его с веселым и беззаботным видом, небрежно рассказывала о том, как ей весело было на вчерашнем бале, и спрашивала, когда он едет. Несмотря на то, что Борис приехал с намерением говорить о своей любви и потому намеревался быть нежным, он раздражительно начал говорить о женском непостоянстве: о том, как женщины легко могут переходить от грусти к радости и что у них расположение духа зависит только от того, кто за ними ухаживает. Жюли оскорбилась и сказала, что это правда, что для женщины нужно разнообразие, что всё одно и то же надоест каждому.
– Для этого я бы советовал вам… – начал было Борис, желая сказать ей колкость; но в ту же минуту ему пришла оскорбительная мысль, что он может уехать из Москвы, не достигнув своей цели и даром потеряв свои труды (чего с ним никогда ни в чем не бывало). Он остановился в середине речи, опустил глаза, чтоб не видать ее неприятно раздраженного и нерешительного лица и сказал: – Я совсем не с тем, чтобы ссориться с вами приехал сюда. Напротив… – Он взглянул на нее, чтобы увериться, можно ли продолжать. Всё раздражение ее вдруг исчезло, и беспокойные, просящие глаза были с жадным ожиданием устремлены на него. «Я всегда могу устроиться так, чтобы редко видеть ее», подумал Борис. «А дело начато и должно быть сделано!» Он вспыхнул румянцем, поднял на нее глаза и сказал ей: – «Вы знаете мои чувства к вам!» Говорить больше не нужно было: лицо Жюли сияло торжеством и самодовольством; но она заставила Бориса сказать ей всё, что говорится в таких случаях, сказать, что он любит ее, и никогда ни одну женщину не любил более ее. Она знала, что за пензенские имения и нижегородские леса она могла требовать этого и она получила то, что требовала.
Жених с невестой, не поминая более о деревьях, обсыпающих их мраком и меланхолией, делали планы о будущем устройстве блестящего дома в Петербурге, делали визиты и приготавливали всё для блестящей свадьбы.


Граф Илья Андреич в конце января с Наташей и Соней приехал в Москву. Графиня всё была нездорова, и не могла ехать, – а нельзя было ждать ее выздоровления: князя Андрея ждали в Москву каждый день; кроме того нужно было закупать приданое, нужно было продавать подмосковную и нужно было воспользоваться присутствием старого князя в Москве, чтобы представить ему его будущую невестку. Дом Ростовых в Москве был не топлен; кроме того они приехали на короткое время, графини не было с ними, а потому Илья Андреич решился остановиться в Москве у Марьи Дмитриевны Ахросимовой, давно предлагавшей графу свое гостеприимство.
Поздно вечером четыре возка Ростовых въехали во двор Марьи Дмитриевны в старой Конюшенной. Марья Дмитриевна жила одна. Дочь свою она уже выдала замуж. Сыновья ее все были на службе.
Она держалась всё так же прямо, говорила также прямо, громко и решительно всем свое мнение, и всем своим существом как будто упрекала других людей за всякие слабости, страсти и увлечения, которых возможности она не признавала. С раннего утра в куцавейке, она занималась домашним хозяйством, потом ездила: по праздникам к обедни и от обедни в остроги и тюрьмы, где у нее бывали дела, о которых она никому не говорила, а по будням, одевшись, дома принимала просителей разных сословий, которые каждый день приходили к ней, и потом обедала; за обедом сытным и вкусным всегда бывало человека три четыре гостей, после обеда делала партию в бостон; на ночь заставляла себе читать газеты и новые книги, а сама вязала. Редко она делала исключения для выездов, и ежели выезжала, то ездила только к самым важным лицам в городе.
Она еще не ложилась, когда приехали Ростовы, и в передней завизжала дверь на блоке, пропуская входивших с холода Ростовых и их прислугу. Марья Дмитриевна, с очками спущенными на нос, закинув назад голову, стояла в дверях залы и с строгим, сердитым видом смотрела на входящих. Можно бы было подумать, что она озлоблена против приезжих и сейчас выгонит их, ежели бы она не отдавала в это время заботливых приказаний людям о том, как разместить гостей и их вещи.
– Графские? – сюда неси, говорила она, указывая на чемоданы и ни с кем не здороваясь. – Барышни, сюда налево. Ну, вы что лебезите! – крикнула она на девок. – Самовар чтобы согреть! – Пополнела, похорошела, – проговорила она, притянув к себе за капор разрумянившуюся с мороза Наташу. – Фу, холодная! Да раздевайся же скорее, – крикнула она на графа, хотевшего подойти к ее руке. – Замерз, небось. Рому к чаю подать! Сонюшка, bonjour, – сказала она Соне, этим французским приветствием оттеняя свое слегка презрительное и ласковое отношение к Соне.
Когда все, раздевшись и оправившись с дороги, пришли к чаю, Марья Дмитриевна по порядку перецеловала всех.
– Душой рада, что приехали и что у меня остановились, – говорила она. – Давно пора, – сказала она, значительно взглянув на Наташу… – старик здесь и сына ждут со дня на день. Надо, надо с ним познакомиться. Ну да об этом после поговорим, – прибавила она, оглянув Соню взглядом, показывавшим, что она при ней не желает говорить об этом. – Теперь слушай, – обратилась она к графу, – завтра что же тебе надо? За кем пошлешь? Шиншина? – она загнула один палец; – плаксу Анну Михайловну? – два. Она здесь с сыном. Женится сын то! Потом Безухова чтоль? И он здесь с женой. Он от нее убежал, а она за ним прискакала. Он обедал у меня в середу. Ну, а их – она указала на барышень – завтра свожу к Иверской, а потом и к Обер Шельме заедем. Ведь, небось, всё новое делать будете? С меня не берите, нынче рукава, вот что! Намедни княжна Ирина Васильевна молодая ко мне приехала: страх глядеть, точно два боченка на руки надела. Ведь нынче, что день – новая мода. Да у тебя то у самого какие дела? – обратилась она строго к графу.
– Всё вдруг подошло, – отвечал граф. – Тряпки покупать, а тут еще покупатель на подмосковную и на дом. Уж ежели милость ваша будет, я времечко выберу, съезжу в Маринское на денек, вам девчат моих прикину.
– Хорошо, хорошо, у меня целы будут. У меня как в Опекунском совете. Я их и вывезу куда надо, и побраню, и поласкаю, – сказала Марья Дмитриевна, дотрогиваясь большой рукой до щеки любимицы и крестницы своей Наташи.