stringtranslate.com

Схема (язык программирования)

Schemeдиалект семейства языков программирования Lisp . Scheme был создан в 1970-х годах в Лаборатории компьютерных наук и искусственного интеллекта Массачусетского технологического института (MIT CSAIL) и выпущен его разработчиками Гаем Л. Стилом и Джеральдом Джеем Сассманом в виде серии меморандумов, ныне известных как Lambda Papers . Это был первый диалект Lisp, выбравший лексическую область видимости и первый, потребовавший от реализаций выполнения оптимизации хвостового вызова , что обеспечило более сильную поддержку функционального программирования и связанных с ним методов, таких как рекурсивные алгоритмы. Он также был одним из первых языков программирования, поддерживающих первоклассные продолжения . Он оказал значительное влияние на усилия, которые привели к разработке Common Lisp . [2]

Язык Scheme стандартизирован в официальном стандарте Института инженеров по электротехнике и электронике (IEEE) [3] и стандарте де-факто , который называется Revised n Report on the Algorithmic Language Scheme (R n RS). Широко применяемым стандартом является R5RS (1998). [4] Самым последним ратифицированным стандартом Scheme является «R7RS-small» (2013). [5] Более обширный и модульный R6RS был ратифицирован в 2007 году. [6] Оба ведут свое происхождение от R5RS; временная шкала ниже отражает хронологический порядок ратификации.

История

Происхождение

Scheme появился в 1970-х годах как попытка понять модель акторов Карла Хьюитта , для чего Стил и Сассман написали «крошечный интерпретатор Lisp» с использованием Maclisp , а затем «добавили механизмы для создания акторов и отправки сообщений». [7] Первоначально Scheme назывался «Schemer», в традициях других языков, производных от Lisp, таких как Planner или Conniver . Нынешнее название возникло в результате использования авторами операционной системы ITS , которая ограничивала имена файлов двумя компонентами по шесть символов каждый. В настоящее время «Schemer» обычно используется для обозначения программиста Scheme.

Р6РС

На семинаре Scheme 2003 года начался новый процесс стандартизации языка с целью разработки стандарта R6RS в 2006 году. Этот процесс порвал с более ранним подходом R n RS, предполагавшим единогласие.

R6RS представляет собой стандартную модульную систему, позволяющую разделить основной язык и библиотеки . Было выпущено несколько проектов спецификации R6RS, финальная версия — R5.97RS. Успешное голосование привело к ратификации нового стандарта, объявленного 28 августа 2007 года. [6]

В настоящее время новейшие выпуски различных реализаций Scheme [8] поддерживают стандарт R6RS. Существует переносимая эталонная реализация предлагаемых неявно фазированных библиотек для R6RS, называемая psyntax, которая загружает и самозагружается должным образом на различных старых реализациях Scheme. [9]

Особенностью R6RS является дескриптор типа записи (RTD). Когда RTD создается и используется, представление типа записи может отображать структуру памяти. Он также вычисляет битовую маску поля объекта и битовые маски изменяемых полей объекта Scheme, а также помогает сборщику мусора узнать, что делать с полями, не проходя по всему списку полей, сохраненных в RTD. RTD позволяет пользователям расширять базовый RTD для создания новой системы записей. [10]

R6RS вносит многочисленные существенные изменения в язык. [11] Исходный код теперь указан в Unicode , и большое подмножество символов Unicode теперь может появляться в символах и идентификаторах Scheme , а также есть другие незначительные изменения в лексических правилах. Символьные данные теперь также указаны в Unicode. Многие стандартные процедуры были перемещены в новые стандартные библиотеки, которые сами по себе образуют большое расширение стандарта, содержащее процедуры и синтаксические формы, которые ранее не были частью стандарта. Была введена новая модульная система, и системы обработки исключений теперь стандартизированы. Syntax-rules был заменен более выразительным средством синтаксической абстракции (syntax-case), которое позволяет использовать всю Scheme во время расширения макроса. Теперь для поддержки полной числовой башни Scheme требуются совместимые реализации , а семантика чисел была расширена, в основном в направлении поддержки стандарта IEEE 754 для числового представления с плавающей точкой.

Р7РС

Стандарт R6RS вызвал споры, поскольку некоторые считают его отходом от минималистской философии. [12] [13] В августе 2009 года Руководящий комитет Scheme, который курирует процесс стандартизации, объявил о своем намерении рекомендовать разделение Scheme на два языка: большой современный язык программирования для программистов; и малую версию, подмножество большой версии, сохраняющее минимализм, восхваляемый преподавателями и случайными разработчиками. [14] Для работы над этими двумя новыми версиями Scheme были созданы две рабочие группы. На сайте Scheme Reports Process есть ссылки на уставы рабочих групп, публичные обсуждения и систему отслеживания проблем.

Девятый проект R7RS (малый язык) был представлен 15 апреля 2013 года. [15] Голосование по ратификации этого проекта завершилось 20 мая 2013 года, [16] а окончательный отчет был доступен с 6 августа 2013 года, описывая «малый» язык этой попытки: поэтому его нельзя рассматривать изолированно как преемника R6RS». [5]

Отличительные черты

Scheme — это в первую очередь функциональный язык программирования . Он разделяет многие характеристики с другими членами семейства языков программирования Lisp. Очень простой синтаксис Scheme основан на s-выражениях , списках в скобках, в которых за префиксным оператором следуют его аргументы. Таким образом, программы Scheme состоят из последовательностей вложенных списков. Списки также являются основной структурой данных в Scheme, что приводит к близкой эквивалентности между исходным кодом и форматами данных ( гомоиконичность ). Программы Scheme могут легко динамически создавать и оценивать фрагменты кода Scheme.

Зависимость от списков как структур данных свойственна всем диалектам Lisp. Scheme наследует богатый набор примитивов обработки списков, таких как cons, carиcdr от своих предшественников Lisp. Scheme использует строго, но динамически типизированные переменные и поддерживает процедуры первого класса . Таким образом, процедуры могут быть назначены как значения переменным или переданы как аргументы процедурам.

В этом разделе основное внимание уделяется инновационным возможностям языка, включая те, которые отличают Scheme от других Lisp. Если не указано иное, описания возможностей относятся к стандарту R5RS. В примерах, приведенных в этом разделе, обозначение "===> result" используется для указания результата вычисления выражения в непосредственно предшествующей строке. Это то же соглашение, которое используется в R5RS.

Минимализм

Scheme — очень простой язык, гораздо более простой в реализации, чем многие другие языки сопоставимой выразительной мощности . [17] Эта простота объясняется использованием лямбда-исчисления для выведения большей части синтаксиса языка из более примитивных форм. Например, из 23 синтаксических конструкций на основе s-выражений, определенных в стандарте R5RS Scheme, 14 классифицируются как производные или библиотечные формы, которые могут быть записаны как макросы, включающие более фундаментальные формы, в основном лямбда. Как говорится в R5RS (§3.1): «Самой фундаментальной из конструкций связывания переменных является лямбда-выражение, потому что все другие конструкции связывания переменных можно объяснить в терминах лямбда-выражений». [4]

Основные формы : определение, лямбда, кавычки, если, определение-синтаксис, let-синтаксис, letrec-синтаксис, синтаксические правила, набор!
Производные формы : do, let, let*, letrec, cond, case, and, or, begin, named let, delay, unquote, unquote-splicing, quadracquote

Пример: макрос для реализации letв виде выражения, используемого lambdaдля выполнения привязки переменных.

( define-syntax let ( syntax-rules () (( let (( var expr ) ... ) body ... ) (( lambda ( var ... ) body ... ) expr ... ))))                

Таким образом, использование letреализации Scheme, как определено выше, перепишет " (let ((a 1)(b 2)) (+ b a))" как " ((lambda (a b) (+ b a)) 1 2)", что сводит задачу реализации к кодированию инстанцирований процедур.

В 1998 году Сассман и Стил отметили, что минимализм Scheme не был сознательной целью дизайна, а скорее непреднамеренным результатом процесса дизайна. «Мы на самом деле пытались построить что-то сложное и обнаружили, по счастливой случайности, что мы случайно спроектировали что-то, что отвечало всем нашим целям, но было намного проще, чем мы предполагали... мы поняли, что лямбда-исчисление — небольшой, простой формализм — может служить ядром мощного и выразительного языка программирования». [7]

Лексический объем

Как и большинство современных языков программирования и в отличие от более ранних Lisp, таких как Maclisp , Scheme имеет лексическую область действия: все возможные привязки переменных в программном модуле могут быть проанализированы путем чтения текста программного модуля без учета контекстов, в которых он может быть вызван. Это контрастирует с динамической областью действия, которая была характерна для ранних диалектов Lisp, из-за затрат на обработку, связанных с примитивными методами текстовой подстановки, используемыми для реализации алгоритмов лексической области действия в компиляторах и интерпретаторах того времени. В тех Lisp вполне возможно было, чтобы ссылка на свободную переменную внутри процедуры ссылалась на совершенно разные привязки, внешние по отношению к процедуре, в зависимости от контекста вызова.

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

Ключевые идеи о том, как ввести лексическую область видимости в диалект Lisp, были популяризированы в статье Сассмана и Стила 1975 года «Схема: интерпретатор для расширенного лямбда-исчисления» [18] , где они приняли концепцию лексического замыкания (на странице 21), которая была описана в AI Memo в 1970 году Джоэлом Мозесом , который приписал эту идею Питеру Дж. Ландину . [19]

Лямбда-исчисление

Математическая нотация Алонзо Чёрча , лямбда-исчисление, вдохновила Lisp на использование «лямбда» в качестве ключевого слова для введения процедуры, а также повлияла на развитие методов функционального программирования, включающих использование функций высшего порядка в Lisp. Но ранние Lisp не были подходящими выражениями лямбда-исчисления из-за их обработки свободных переменных . [7]

Формальная лямбда-система имеет аксиомы и полное правило вычисления. Она полезна для анализа с использованием математической логики и инструментов. В этой системе вычисление можно рассматривать как направленную дедукцию. Синтаксис лямбда-исчисления следует рекурсивным выражениям из x, y, z, ..., скобок, пробелов, точки и символа λ. [20] Функция лямбда-исчисления включает: Во-первых, служить отправной точкой мощной математической логики. Во-вторых, оно может снизить потребность программистов в рассмотрении деталей реализации, поскольку его можно использовать для имитации машинной оценки. Наконец, лямбда-исчисление создало существенную метатеорию. [21]

Введение лексической области видимости решило проблему, установив эквивалентность между некоторыми формами лямбда-нотации и их практическим выражением в рабочем языке программирования. Сассман и Стил показали, что новый язык может быть использован для элегантного вывода всей императивной и декларативной семантики других языков программирования, включая ALGOL и Fortran , а также динамической области видимости других Lisp, используя лямбда-выражения не как простые инстанциации процедур, а как «управляющие структуры и модификаторы окружения». [22] Они ввели стиль продолжения-передачи вместе со своим первым описанием Scheme в первой из Lambda Papers, а в последующих статьях они продолжили демонстрировать чистую мощь этого практического использования лямбда-исчисления.

Блочная структура

Scheme наследует свою блочную структуру от более ранних блочно-структурированных языков, в частности ALGOL . В Scheme блоки реализуются тремя конструкциями связывания : let, let*и letrec. Например, следующая конструкция создает блок , в котором вызываемый символ varсвязан с числом 10:

( define var "goose" ) ;; Любая ссылка на var здесь будет привязана к "goose" ( let (( var 10 )) ;; Здесь идут операторы. Любая ссылка на var здесь будет привязана к 10. ) ;; Любая ссылка на var здесь будет привязана к "goose"      

Блоки могут быть вложены для создания произвольно сложных структур блоков в соответствии с потребностями программиста. Использование структурирования блоков для создания локальных привязок снижает риск коллизии пространств имен , которая в противном случае могла бы возникнуть.

Один из вариантов let, let*, позволяет привязкам ссылаться на переменные, определенные ранее в той же конструкции, таким образом:

( let* (( var1 10 ) ( var2 ( + var1 12 ))) ;; Но определение var1 не может ссылаться на var2 )        

Другой вариант, letrec, предназначен для того, чтобы позволить взаимно рекурсивным процедурам быть связанными друг с другом.

;; Расчет мужских и женских последовательностей Хофштадтера в виде списка пар( define ( hofstadter-male-female n ) ( letrec (( female ( lambda ( n ) ( if ( = n 0 ) 1 ( - n ( male ( female ( - n 1 ))))))) ( male ( lambda ( n ) ( if ( = n 0 ) 0 ( - n ( female ( male ( - n 1 )))))))) ( let loop (( i 0 )) ( if ( > i n ) ' () ( cons ( cons ( female i ) ( male i )) ( loop ( + i 1 )))))))                                                   ( hofstadter-мужчина-женщина 8 ) ===> (( 1 . 0 ) ( 1 . 0 ) ( 2 . 1 ) ( 2 . 2 ) ( 3 . 2 ) ( 3 . 3 ) ( 4 . 4 ) ( 5 . 4 ) ( 5 . 5 ) )                           

( Определения, используемые в этом примере, см. в последовательности мужчин и женщин Хофштадтера .)

Все процедуры, связанные в одну, letrecмогут ссылаться друг на друга по имени, а также на значения переменных, определенных ранее в той же процедуре letrec, но они не могут ссылаться на значения, определенные позднее в той же процедуре letrec.

Вариант letформы "named let" имеет идентификатор после letключевого слова. Это связывает переменные let с аргументом процедуры, имя которой — заданный идентификатор, а тело — тело формы let. Тело может быть повторено по желанию путем вызова процедуры. Именованный let широко используется для реализации итерации.

Пример: простой счетчик

( пусть цикл (( n 1 )) ( если ( > n 10 ) ' () ( cons n ( цикл ( + n 1 )))))              ===> ( 1 2 3 4 5 6 7 8 9 10 )          

Как и любая процедура в Scheme, процедура, созданная в именованном let, является объектом первого класса.

Правильная хвостовая рекурсия

В Scheme есть конструкция итерации, doно в Scheme более идиоматично использовать хвостовую рекурсию для выражения итерации . Соответствующие стандарту реализации Scheme должны оптимизировать хвостовые вызовы, чтобы поддерживать неограниченное количество активных хвостовых вызовов (R5RS sec. 3.5) [4] — свойство, которое отчет Scheme описывает как правильную хвостовую рекурсию — что позволяет программистам Scheme безопасно писать итерационные алгоритмы с использованием рекурсивных структур, которые иногда более интуитивны. Хвостовые рекурсивные процедуры и именованнаяlet форма обеспечивают поддержку итерации с использованием хвостовой рекурсии.

;; Создание списка квадратов от 0 до 9: ;; Примечание: loop — это просто произвольный символ, используемый в качестве метки. Подойдет любой символ.( определить ( список-квадратов n ) ( пусть цикл (( i n ) ( рез ' ())) ( если ( < i 0 ) рез ( цикл ( - i 1 ) ( cons ( * i i ) рез )))))                      ( список-квадратов 9 ) ===> ( 0 1 4 9 16 25 36 49 64 81 )           

Первоклассные продолжения

Продолжения в Scheme являются объектами первого класса . Scheme предоставляет процедуру call-with-current-continuation(также известную как call/cc) для захвата текущего продолжения путем упаковки его в качестве процедуры выхода, связанной с формальным аргументом в процедуре, предоставленной программистом. (R5RS раздел 6.4) [4] Продолжения первого класса позволяют программисту создавать нелокальные управляющие конструкции, такие как итераторы , сопрограммы и возвраты .

Продолжения могут использоваться для эмуляции поведения операторов return в императивных языках программирования. Следующая функция find-first, заданная function funcи list lst, возвращает первый элемент xв lstтаком виде, что (func x)возвращает true.

( define ( find-first func lst ) ( call-with-current-continuation ( lambda ( return-immediately ) ( for-each ( lambda ( x ) ( if ( func x ) ( return-immediately x ))) lst ) #f )))                ( найти первое целое число? ' ( 1/2 3/4 5.6 7 8/9 10 11 )) ===> 7 ( найти первый ноль? ' ( 1 2 3 4 )) ===> #f               

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

( пусть* (( инь (( лямбда ( cc ) ( отобразить "@" ) cc ) ( вызов-с-текущим-продолжением ( лямбда ( c ) c )))) ( ян (( лямбда ( cc ) ( отобразить "*" ) cc ) ( вызов-с-текущим-продолжением ( лямбда ( c ) c ))))) ( инь янь ))                      

При выполнении этого кода отображается последовательность подсчета:@*@**@***@****@*****@******@*******@********...

Общее пространство имен для процедур и переменных

В отличие от Common Lisp, все данные и процедуры в Scheme имеют общее пространство имен, тогда как в Common Lisp функции и данные имеют отдельные пространства имен, что позволяет функции и переменной иметь одно и то же имя и требует специальной нотации для ссылки на функцию как на значение. Это иногда известно как различие " Lisp-1 против Lisp-2 ", ссылаясь на единое пространство имен Scheme и отдельные пространства имен Common Lisp. [23]

defunВ Scheme те же примитивы, которые используются для манипулирования и связывания данных, могут использоваться для связывания процедур. Эквивалент Common Lisp и примитивов отсутствует #'.

;; Переменная, связанная с числом: ( define f 10 ) f ===> 10 ;; Мутация (изменение связанного значения) ( set! f ( + f f 6 )) f ===> 26 ;; Назначение процедуры той же переменной: ( set! f ( lambda ( n ) ( + n 12 ))) ( f 6 ) ===> 18 ;; Назначение результата выражения той же переменной: ( set! f ( f 1 )) f ===> 13 ;; функциональное программирование: ( apply + ' ( 1 2 3 4 5 6 )) ===> 21 ( set! f ( lambda ( n ) ( + n 100 ))) ( map f ' ( 1 2 3 )) ===> ( 101 102 103 )                                          

Стандарты внедрения

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

Числовая башня

Scheme определяет сравнительно полный набор числовых типов данных, включая комплексные и рациональные типы, который в Scheme известен как числовая башня (R5RS sec. 6.2 [4] ). Стандарт рассматривает их как абстракции и не обязывает разработчика к каким-либо конкретным внутренним представлениям.

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

Стандарт R5RS определяет процедуры exact->inexactи , inexact->exactкоторые могут использоваться для изменения точности числа. inexact->exactпроизводит «точное число, которое численно ближе всего к аргументу». exact->inexactпроизводит «неточное число, которое численно ближе всего к аргументу». Стандарт R6RS исключает эти процедуры из основного отчета, но определяет их как процедуры совместимости с R5RS в стандартной библиотеке (rnrs r5rs (6)).

В стандарте R5RS реализации Scheme не обязаны реализовывать всю числовую башню, но они должны реализовывать «согласованное подмножество, соответствующее как целям реализации, так и духу языка Scheme» (R5RS, раздел 6.2.3). [4] Новый стандарт R6RS требует реализации всей башни и «точных целочисленных объектов и точных рациональных объектов практически неограниченного размера и точности, а также реализации определенных процедур... чтобы они всегда возвращали точные результаты при задании точных аргументов» (R6RS, раздел 3.4, раздел 11.7.1). [6]

Пример 1: точная арифметика в реализации, поддерживающей точные рациональные комплексные числа.

;; Сумма трех рациональных действительных чисел и двух рациональных комплексных чисел ( define x ( + 1/3 1/4 -1/5 -1/3i 405/50+2/3i )) x ===> 509/60+1/3i ;; Проверка на точность. ( exact? x ) ===> #t          

Пример 2: Та же арифметика в реализации, которая не поддерживает ни точные рациональные числа, ни комплексные числа, но принимает действительные числа в рациональной нотации.

;; Сумма четырех рациональных действительных чисел ( define xr ( + 1/3 1/4 -1/5 405/50 )) ;; Сумма двух рациональных действительных чисел ( define xi ( + -1/3 2/3 )) xr ===> 8,48333333333333 xi ===> 0,333333333333333 ;; Проверка на точность. ( exact? xr ) ===> #f ( exact? xi ) ===> #f                

Обе реализации соответствуют стандарту R5RS, но вторая не соответствует R6RS, поскольку не реализует полную числовую башню.

Отсроченная оценка

Схема поддерживает отложенную оценку посредством delayформы и процедуры force.

( определить a 10 ) ( определить eval-aplus2 ( задержка ( + a 2 ))) ( установить! a 20 ) ( заставить eval-aplus2 ) ===> 22 ( определить eval-aplus50 ( задержка ( + a 50 ))) ( пусть (( a 8 )) ( заставить eval-aplus50 )) ===> 70 ( установить! a 100 ) ( заставить eval-aplus2 ) ===> 22                         

Лексический контекст исходного определения обещания сохраняется, и его значение также сохраняется после первого использования force. Обещание оценивается только один раз.

Эти примитивы, которые создают или обрабатывают значения, известные как обещания , могут использоваться для реализации расширенных конструкций ленивой оценки, таких как потоки . [24]

В стандарте R6RS они больше не являются примитивами, а вместо этого предоставляются как часть библиотеки совместимости R5RS (rnrs r5rs (6)).

В R5RS предлагается реализация delayand force, реализующая обещание как процедуру без аргументов ( thunk ) и использующая мемоизацию для обеспечения того, чтобы оно было оценено только один раз, независимо от того, сколько раз forceоно вызывается (R5RS, раздел 6.4). [4]

SRFI 41 позволяет выражать как конечные, так и бесконечные последовательности с необычайной экономией. Например, это определение последовательности Фибоначчи с использованием функций, определенных в SRFI 41: [24]

;; Определить последовательность Фибоначчи: ( define fibs ( stream-cons 0 ( stream-cons 1 ( stream-map + fibs ( stream-cdr fibs ))))) ;; Вычислить сотое число в последовательности: ( stream-ref fibs 99 ) ===> 218922995834555169026             

Порядок оценки процессуальных аргументов

Большинство Lisp-ов определяют порядок оценки аргументов процедуры. Scheme этого не делает. Порядок оценки — включая порядок, в котором оценивается выражение в позиции оператора — может быть выбран реализацией на основе вызова-за-вызовом, и единственным ограничением является то, что «эффект любой одновременной оценки выражений оператора и операнда ограничен, чтобы соответствовать некоторому последовательному порядку оценки». (R5RS sec. 4.1.3) [4]

( let (( ev ( lambda ( n ) ( display "Вычисляется " ) ( display ( if ( procedure? n ) "procedure" n )) ( newline ) n ))) (( ev + ) ( ev 1 ) ( ev 2 ))) ===> 3                   
Оценка 1 Оценка 2 Процедура оценки

ev — это процедура, которая описывает переданный ей аргумент, а затем возвращает значение аргумента. В отличие от других Lisp, появление выражения в позиции оператора (первый элемент) выражения Scheme вполне допустимо, пока результатом выражения в позиции оператора является процедура.

При вызове процедуры " + " для сложения 1 и 2 выражения (ev +), (ev 1) и (ev 2) могут быть оценены в любом порядке, пока эффект не будет таким, как если бы они были оценены параллельно. Таким образом, следующие три строки могут быть отображены в любом порядке стандартной схемой при выполнении приведенного выше примера кода, хотя текст одной строки не может быть перемежен с другим, поскольку это нарушит ограничение последовательной оценки.

Гигиенические макросы

В стандарте R5RS, а также в более поздних отчетах, синтаксис Scheme может быть легко расширен с помощью макросистемы. Стандарт R5RS ввел мощную гигиеническую макросистему, которая позволяет программисту добавлять новые синтаксические конструкции в язык, используя простой подъязык сопоставления шаблонов (R5RS sec 4.3). [4] До этого гигиеническая макросистема была отнесена к приложению стандарта R4RS, как система «высокого уровня» наряду с макросистемой «низкого уровня», обе из которых рассматривались как расширения Scheme, а не как существенная часть языка. [25]

Реализации гигиенической макросистемы, также называемой syntax-rules, должны соблюдать лексическую область видимости остальной части языка. Это обеспечивается специальными правилами именования и области видимости для расширения макросов и позволяет избежать распространенных ошибок программирования, которые могут возникнуть в макросистемах других языков программирования. R6RS определяет более сложную систему преобразования, syntax-case, которая некоторое время была доступна как языковое расширение для R5RS Scheme.

;; Определите макрос для реализации варианта "if" с множественным выражением ;; с ветвью true и без ветвей false. ( define-syntax when ( syntax-rules () (( when pred exp exps ... ) ( if pred ( begin exp exps ... )))))              

Вызовы макросов и процедур очень похожи — оба являются s-выражениями, — но обрабатываются по-разному. Когда компилятор встречает s-выражение в программе, он сначала проверяет, определен ли символ как синтаксическое ключевое слово в текущей лексической области. Если да, то он пытается расширить макрос, обрабатывая элементы в хвосте s-выражения как аргументы без компиляции кода для их оценки, и этот процесс повторяется рекурсивно до тех пор, пока не останется ни одного вызова макроса. Если это не синтаксическое ключевое слово, компилятор компилирует код для оценки аргументов в хвосте s-выражения, а затем для оценки переменной, представленной символом в начале s-выражения, и вызывает его как процедуру с переданными ему в качестве аргументов оцененными выражениями хвоста.

Большинство реализаций Scheme также предоставляют дополнительные макросистемы. Среди популярных — синтаксические замыкания , явные макросы переименования и define-macroнегигиеничная макросистема, похожая на defmacroсистему, предоставляемую в Common Lisp .

Невозможность указать, является ли макрос гигиеничным или нет, является одним из недостатков макросистемы. Альтернативные модели расширения, такие как наборы областей действия, предоставляют потенциальное решение. [26]

Окружающая среда и оценка

До R5RS в Scheme не было стандартного эквивалента процедуры eval, которая повсеместно встречается в других Lisp, хотя в первой статье Lambda она была описана evaluateкак «похожая на функцию LISP EVAL» [18] , а в первом пересмотренном отчете 1978 года она была заменена на enclose, которая принимала два аргумента. Во втором, третьем и четвертом пересмотренных отчетах не было никаких эквивалентов eval.

Причина этой путаницы в том, что в Scheme с его лексической областью действия результат оценки выражения зависит от того, где оно оценивается. Например, неясно, должен ли результат оценки следующего выражения быть 5 или 6: [27]

( пусть (( имя '+ )) ( пусть (( + * )) ( вычислить ( имя списка 2 3 ))))          

Если он вычисляется во внешней среде, где nameопределено, результатом является сумма операндов. Если он вычисляется во внутренней среде, где символ "+" был привязан к значению процедуры "*", результатом является произведение двух операндов.

R5RS устраняет эту путаницу, указывая три процедуры, которые возвращают среды, и предоставляя процедуру eval, которая принимает s-выражение и среду и оценивает выражение в предоставленной среде. (R5RS раздел 6.5) [4] R6RS расширяет это, предоставляя процедуру, вызываемую environmentс помощью которой программист может точно указать, какие объекты следует импортировать в среду оценки.

При использовании современной схемы (обычно совместимой с R5RS) для оценки этого выражения необходимо определить функцию evaluate, которая может выглядеть следующим образом:

( определить ( оценить выражение ) ( оценить выражение ( взаимодействие-среда )))     

interaction-environmentэто глобальная среда переводчика.

Обработка небулевых значений в булевых выражениях

В большинстве диалектов Lisp, включая Common Lisp, по соглашению значение NILвычисляется как значение false в булевом выражении. В Scheme, начиная со стандарта IEEE 1991 года, [3] все значения, кроме #f, включая NILэквивалент 's в Scheme, который записывается как '(), вычисляются как значение true в булевом выражении. (R5RS sec. 6.3.1) [4]

Если в большинстве языков Lisp константа, представляющая логическое значение true, — T, то в Scheme это #t.

Непересекаемость примитивных типов данных

В Scheme примитивные типы данных не пересекаются. Только один из следующих предикатов может быть истинным для любого объекта Scheme: boolean?, pair?, symbol?, number?, char?, string?, vector?, port?, procedure?. (R5RS sec 3.2) [4]

В численном типе данных, напротив, числовые значения перекрываются. Например, целочисленное значение удовлетворяет всем предикатам integer?, rational?, real?, complex?и number?одновременно. (R5RS sec 6.2) [4]

Предикаты эквивалентности

В схеме есть три различных типа эквивалентности между произвольными объектами, обозначенными тремя различными предикатами эквивалентности , реляционными операторами для проверки равенства eq?, eqv?и equal?:

В Scheme также существуют операции эквивалентности, зависящие от типа: string=?и string-ci=?сравнивает две строки (последняя выполняет сравнение, не зависящее от регистра); char=?и char-ci=?сравнивает символы; =сравнивает числа. [4]

Комментарии

До стандарта R5RS стандартным комментарием в Scheme была точка с запятой, которая делала остальную часть строки невидимой для Scheme. Многочисленные реализации поддерживали альтернативные соглашения, позволяющие комментариям распространяться более чем на одну строку, и стандарт R6RS допускает два из них: целое s-выражение может быть превращено в комментарий (или «закомментировано»), если предварить его #;(введено в SRFI 62 [28] ), а многострочный комментарий или «блочный комментарий» может быть получен путем окружения текста #|и |#.

Ввод/вывод

Ввод и вывод Scheme основаны на типе данных порта . (R5RS sec 6.6) [4] R5RS определяет два порта по умолчанию, доступных с помощью процедур current-input-portи current-output-port, которые соответствуют понятиям Unix стандартного ввода и стандартного вывода . Большинство реализаций также предоставляют current-error-port. Перенаправление ввода и стандартного вывода поддерживается в стандарте стандартными процедурами, такими как with-input-from-fileи with-output-to-file. Большинство реализаций предоставляют строковые порты с аналогичными возможностями перенаправления, что позволяет выполнять многие обычные операции ввода-вывода над строковыми буферами вместо файлов, используя процедуры, описанные в SRFI 6. [29] Стандарт R6RS определяет гораздо более сложные и эффективные процедуры порта и много новых типов портов.

Следующие примеры написаны в строгой схеме R5RS.

Пример 1: С выходом по умолчанию (текущий-выходной-порт):

( пусть (( hello0 ( лямбда () ( дисплей "Привет, мир" ) ( новая строка )))) ( hello0 ))      

Пример 2: Как 1, но с использованием необязательного аргумента порта для вывода процедур

( пусть (( привет1 ( лямбда ( p ) ( вывести "Привет, мир" p ) ( новая строка p )))) ( привет1 ( текущий-выходной-порт )))          

Пример 3: Как 1, но вывод перенаправляется во вновь созданный файл

;; Примечание: with-output-to-file — необязательная процедура в R5RS ( let (( hello0 ( lambda () ( display "Hello world" ) ( newline )))) ( with-output-to-file "helloworldoutputfile" hello0 ))         

Пример 4: Как 2, но с явным открытием файла и закрытием порта для отправки вывода в файл

( let (( hello1 ( lambda ( p ) ( display "Hello world" p ) ( newline p ))) ( output-port ( open-output-file "helloworldoutputfile" ))) ( hello1 output-port ) ( close-output-port output-port ))               

Пример 5: То же, что и 2, но с использованием call-with-output-file для отправки вывода в файл.

( let (( hello1 ( lambda ( p ) ( display "Hello world" p ) ( newline p )))) ( call-with-output-file "helloworldoutputfile" hello1 ))           

Аналогичные процедуры предусмотрены для ввода. Схема R5RS предоставляет предикаты input-port?и output-port?. Для ввода и вывода символов предоставляются write-char, read-charи peek-char. Для записи и чтения выражений Scheme, Scheme предоставляет и . При операции чтения возвращаемый результат является объектом конца файла, если порт ввода достиг конца файла, и это можно проверить с помощью предиката .char-ready?readwriteeof-object?

В стандарте SRFI 28 также определяется базовая процедура форматирования, напоминающая formatфункцию Common Lisp, в честь которой она и названа. [30]

Переопределение стандартных процедур

В Scheme процедуры привязаны к переменным. В R5RS стандарт языка формально предписал, что программы могут изменять привязки переменных встроенных процедур, фактически переопределяя их. (R5RS "Изменения языка") [4] Например, +можно расширить, чтобы принимать строки, а также числа, переопределив его:

( set! + ( let (( original+ + )) ( lambda args ( apply ( if ( or ( null? args ) ( string? ( car args ))) string-append original+ ) args )))) ( + 1 2 3 ) ===> 6 ( + "1" "2" "3" ) ===> "123"                         

В R6RS каждая привязка, включая стандартную, принадлежит некоторой библиотеке, и все экспортированные привязки являются неизменяемыми. (R6RS sec 7.1) [6] Из-за этого переопределение стандартных процедур мутацией запрещено. Вместо этого можно импортировать другую процедуру под именем стандартной, что по сути аналогично переопределению.

Номенклатура и соглашения по наименованию

В стандартной схеме процедуры, преобразующие один тип данных в другой, содержат в своем имени строку символов "->", предикаты заканчиваются на "?", а процедуры, изменяющие значение уже выделенных данных, заканчиваются на "!". Эти соглашения часто соблюдаются программистами Scheme.

В формальных контекстах, таких как стандарты Scheme, слово «процедура» используется вместо слова «функция» для обозначения лямбда-выражения или примитивной процедуры. В обычном использовании слова «процедура» и «функция» используются взаимозаменяемо. Применение процедуры иногда формально называют комбинацией .

Как и в других Lisp, термин " thunk " используется в Scheme для обозначения процедуры без аргументов. Термин "правильная хвостовая рекурсия" относится к свойству всех реализаций Scheme, заключающемуся в том, что они выполняют оптимизацию хвостовых вызовов, чтобы поддерживать неограниченное количество активных хвостовых вызовов .

Форма заголовков документов стандартов, начиная с R3RS, «Пересмотренный отчет по схеме алгоритмического языка», является ссылкой на заголовок стандартного документа ALGOL 60 , «Пересмотренный отчет по алгоритмическому языку Algol 60». Страница «Сводка» R3RS во многом скопирована со страницы «Сводка» отчета ALGOL 60. [31] [32]

Обзор стандартных форм и процедур

Язык формально определен в стандартах R5RS (1998) [4] и R6RS (2007). [6] Они описывают стандартные «формы»: ключевые слова и сопутствующий синтаксис, которые обеспечивают структуру управления языком, а также стандартные процедуры, которые выполняют общие задачи.

Стандартные формы

В этой таблице описаны стандартные формы в Scheme. Некоторые формы появляются в более чем одной строке, поскольку их нельзя легко классифицировать в одну функцию в языке.

Формы, отмеченные в этой таблице буквой «L», классифицируются в стандарте как производные «библиотечные» формы и часто реализуются как макросы с использованием на практике более фундаментальных форм, что значительно упрощает задачу реализации по сравнению с другими языками.

Хотя beginв R5RS определен как библиотечный синтаксис, расширитель должен знать о нем, чтобы достичь функции сплайсинга. В R6RS это больше не библиотечный синтаксис.

Стандартные процедуры

В следующих двух таблицах описываются стандартные процедуры в схеме R5RS. R6RS гораздо более обширен, и краткое изложение такого типа было бы непрактичным.

Некоторые процедуры появляются более чем в одной строке, поскольку их нельзя легко отнести к одной функции в языке.

Строковые и символьные процедуры, содержащие «-ci» в своих именах, выполняют независимые от регистра сравнения между своими аргументами: версии одного и того же символа в верхнем и нижнем регистре считаются равными.

Реализации - и /, которые принимают более двух аргументов, определены, но оставлены необязательными в R5RS.

Запросы на реализацию схем

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

SRFI с довольно широкой поддержкой в ​​различных реализациях включают: [33]

Реализации

Элегантный минималистский дизайн сделал Scheme популярной целью для разработчиков языков, любителей и преподавателей, а из-за своего небольшого размера, типичного интерпретатора , он также является популярным выбором для встраиваемых систем и сценариев . Это привело к появлению множества реализаций, [34] большинство из которых отличаются друг от друга настолько, что перенос программ из одной реализации в другую становится довольно сложным, а небольшой размер стандартного языка означает, что написание полезной программы любой большой сложности на стандартной переносимой Scheme практически невозможно. [14] Стандарт R6RS определяет гораздо более широкий язык в попытке расширить его привлекательность для программистов.

Почти все реализации предоставляют традиционный цикл чтения–вычисления–печати в стиле Lisp для разработки и отладки. Многие также компилируют программы Scheme в исполняемый двоичный файл. Поддержка встраивания кода Scheme в программы, написанные на других языках, также распространена, поскольку относительная простота реализаций Scheme делает его популярным выбором для добавления возможностей скриптинга в более крупные системы, разработанные на таких языках, как C. Интерпретаторы Scheme Gambit , Chicken и Bigloo компилируют Scheme в C, что значительно упрощает встраивание. Кроме того, компилятор Bigloo можно настроить для генерации байт-кода для виртуальной машины Java (JVM), и он имеет экспериментальный генератор байт-кода для .NET .

Некоторые реализации поддерживают дополнительные функции. Например, Kawa и JScheme обеспечивают интеграцию с классами Java , а компиляторы Scheme to C часто упрощают использование внешних библиотек, написанных на C, вплоть до встраивания кода C в исходный код Scheme. Другим примером является Pvts, который предлагает набор визуальных инструментов, поддерживающих обучение Scheme.

Использование

Scheme широко используется несколькими [35] школами; в частности, несколько вводных курсов по информатике используют Scheme в сочетании с учебником Structure and Interpretation of Computer Programs (SICP). [36] В течение последних 12 лет PLT реализует проект ProgramByDesign (ранее TeachScheme!), который познакомил около 600 учителей старших классов и тысячи учеников старших классов с элементарным программированием на Scheme. Старый вводный курс программирования 6.001 Массачусетского технологического института преподавался на Scheme, [37] Хотя 6.001 был заменен более современными курсами, SICP продолжает преподаваться в MIT. [38] Аналогичным образом, вводный курс в Калифорнийском университете в Беркли , CS 61A, до 2011 года преподавался полностью на Scheme, за исключением небольших отклонений в Logo для демонстрации динамического охвата. Сегодня, как и Массачусетский технологический институт, Беркли заменил учебную программу более современной версией, которая в основном преподается на Python 3 , но текущая учебная программа по-прежнему основана на старой программе, и части занятий по-прежнему преподаются на Scheme. [39]

Учебник «Как разрабатывать программы» Маттиаса Феллейзена, в настоящее время находящийся в Северо-Восточном университете, используется некоторыми высшими учебными заведениями для вводных курсов по информатике. И Северо-Восточный университет , и Вустерский политехнический институт используют Scheme исключительно для своих вводных курсов «Основы информатики» (CS2500) и «Введение в проектирование программ» (CS1101) соответственно. [40] [41] Rose-Hulman использует Scheme в своем более продвинутом курсе «Концепции языка программирования». [42] Основной курс Университета Брандейса «Структура и интерпретации компьютерных программ» (COSI121b) также преподается исключительно на Scheme теоретиком-компьютерщиком Гарри Мейрсоном . [43] Вводный курс Университета Индианы , C211, преподается полностью на Scheme. Самостоятельная версия курса, CS 61AS, продолжает использовать Scheme. [44] Вводные курсы по информатике в Йельском университете и Гриннелл-колледже также преподаются на Scheme. [45] Programming Design Paradigms, [46] обязательный курс для аспирантов по информатике в Северо-Восточном университете , также широко использует Scheme. Бывший вводный курс по информатике в Университете Миннесоты - Города-побратимы, CSCI 1901, также использовал Scheme в качестве основного языка, за которым последовал курс, знакомивший студентов с языком Java; [47] однако, следуя примеру MIT, факультет заменил 1901 на CSCI 1133 на основе Python, [48] в то время как функциональное программирование подробно рассматривается в курсе третьего семестра CSCI 2041. [49]

Схема также использовалась/использовалась для следующего:

Смотрите также

Ссылки

  1. ^ "Влияния - The Rust Reference". The Rust Reference . Получено 2023-04-18 .
  2. ^ Common LISP: The Language, 2-е изд., Guy L. Steele Jr. Digital Press; 1981. ISBN 978-1-55558-041-4 . «Common Lisp — это новый диалект Lisp, преемник MacLisp, на который сильно повлиял ZetaLisp и в некоторой степени Scheme и InterLisp». 
  3. ^ ab 1178-1990 (Reaff 2008) Стандарт IEEE для языка программирования Scheme. Номер части IEEE STDPD14209, единогласно подтвержден на заседании Комитета по рассмотрению стандартов Совета по стандартам IEEE-SA (RevCom) 26 марта 2008 г. (пункт 6.3 протокола), протокол подтверждения доступен в октябре 2009 г. Этот документ доступен только для покупки в IEEE, а не в Интернете на момент написания: 2009 г.
  4. ^ abcdefghijklmnopqr Ричард Келси; Уильям Клингер; Джонатан Риз; и др. (август 1998 г.). «Пересмотренный5 отчет о схеме алгоритмического языка». Вычисления высшего порядка и символьные вычисления . 11 (1): 7–105. doi :10.1023/A:1010051815785. S2CID  14069423. Получено 09.08.2012 .
  5. ^ ab "Окончательный вариант R7RS доступен" (PDF) . 2013-07-06.
  6. ^ abcde Sperber, Michael; Dybvig, R. Kent; Flatt, Matthew; Van Straaten, Anton; et al. (август 2007 г.). "Revised6 Report on the Algorithmic Language Scheme (R6RS)". Руководящий комитет схемы . Получено 13 сентября 2011 г.
  7. ^ abcd Сассман, Джеральд Джей; Стил, Гай Л. (1 декабря 1998 г.). «Первый отчет о схеме снова пересмотрен». Вычисления высшего порядка и символьные вычисления . 11 (4): 399–404. doi :10.1023/A:1010079421970. S2CID  7704398.
  8. ^ "Реализации R6RS". r6rs.org . Получено 24.11.2017 .
  9. ^ Абдулазиз Гулум (2007-10-27). "Библиотеки R6RS и система синтаксиса-падежа (psyntax)". Схема Ikarus . Получено 20-10-2009 .
  10. ^ Keep, Andrew W.; Dybvig, R. Kent (ноябрь 2014 г.). «Представление типов записей схемы во время выполнения». Журнал функционального программирования . 24 (6): 675–716. doi : 10.1017/S0956796814000203 . S2CID  40001845.
  11. ^ "Пересмотренный^6 Отчет по Схеме алгоритмического языка, Приложение E: изменения языка". Руководящий комитет Схемы. 2007-09-26 . Получено 2009-10-20 .
  12. ^ "R6RS Electorate". Руководящий комитет схемы. 2007. Получено 2012-08-09 .
  13. ^ Марк Фили (сборник) (2007-10-26). "Намерения исполнителей относительно R6RS". Руководящий комитет схемы, список рассылки r6rs-discuss . Получено 2012-08-09 .
  14. ^ ab Уилл Клингер, Марк Фили, Крис Хэнсон, Джонатан Риз и Олин Шиверс (2009-08-20). "Заявление о позиции (черновик)". Руководящий комитет схемы . Получено 2012-08-09 .{{cite web}}: CS1 maint: несколько имен: список авторов ( ссылка )
  15. ^ "Доступен 9-й проект R7RS" (PDF) . 2013-04-15.
  16. ^ Уилл Клингер (2013-05-10). "продление периода голосования". Руководящий комитет по языку схемы, список рассылки отчетов по схеме. Архивировано из оригинала 2013-07-21 . Получено 2013-07-07 .
  17. ^ Реализация Scheme 48 так названа, потому что интерпретатор был написан Ричардом Келси и Джонатаном Ризом за 48 часов (6–7 августа 1986 г. См. Ричард Келси; Джонатан Риз; Майк Спербер (10.01.2008). «Неполное справочное руководство по Scheme 48 для версии 1.8». Джонатан Риз, s48.org . Получено 09.08.2012 .
  18. ^ ab Gerald Jay Sussman & Guy Lewis Steele Jr. (декабрь 1975 г.). "Scheme: An Interpreter for Extended Lambda Calculus" (PDF) . AI Memos . AIM-349. MIT AI Lab . hdl :1721.1/5794 . Получено 23 декабря 2021 г. .
  19. ^ Джоэл Мозес (июнь 1970 г.), Функция FUNCTION в LISP, или Почему проблема FUNARG должна называться проблемой окружения , hdl :1721.1/5854, AI Memo 199, Полезная метафора для различия между FUNCTION и QUOTE в LISP — думать о QUOTE как о пористом или открытом покрытии функции, поскольку свободные переменные ускользают в текущее окружение. FUNCTION действует как закрытое или непористое покрытие (отсюда термин «замыкание», используемый Ландином). Таким образом, мы говорим об «открытых» лямбда-выражениях (функции в LISP обычно являются лямбда-выражениями) и «закрытых» лямбда-выражениях. [...] Мой интерес к проблеме окружения возник, когда Ландин, который имел глубокое понимание проблемы, посетил Массачусетский технологический институт в 1966-67 гг. Затем я осознал соответствие между списками FUNARG, которые являются результатами оценки «закрытых» лямбда-выражений в LISP , и лямбда-замыканиями ISWIM .
  20. ^ Ван Тондер, Андре (1 января 2004 г.). «Лямбда-исчисление для квантовых вычислений». Журнал SIAM по вычислениям . 33 (5): 1109–1135. arXiv : quant-ph/0307150 . doi :10.1137/S0097539703432165. S2CID  613571.
  21. ^ Нирен, Дж.; Швингхаммер, Дж.; Смолка, Г. (ноябрь 2006 г.). «Параллельное лямбда-исчисление с будущими» (PDF) . Теоретическая информатика . 364 (3): 338–356. doi :10.1016/j.tcs.2006.08.016.
  22. Джеральд Джей Сассман и Гай Льюис Стил-младший (март 1976 г.). «Лямбда: абсолютный императив». AI Memos . AIM-353. MIT AI Lab . Архивировано из оригинала (postscript или PDF) 2016-05-10 . Получено 2012-08-09 .
  23. ^ Габриэль, Ричард П .; Питман, Кент (1988). «Технические вопросы разделения в функциональных ячейках и ячейках значений». LISP и символьные вычисления . Том 1, № 1 (опубликовано в июне 1988 г.). стр. 81–101. doi :10.1007/BF01806178 . Получено 09.08.2012 .
  24. ^ ab Philip L. Bewig (2008-01-24). "SRFI 41: Streams". Редакторы SRFI, schemers.org . Получено 2012-08-09 .
  25. ^ Уильям Клингер и Джонатан Риз, ред. (1991). «Пересмотренный4 отчет о схеме алгоритмического языка». ACM Lisp Pointers . 4 (3): 1–55 . Получено 09.08.2012 .
  26. ^ Флэтт, Мэтью (2016). «Связывание как наборы областей». Труды 43-го ежегодного симпозиума ACM SIGPLAN-SIGACT по принципам языков программирования . стр. 705–717. doi :10.1145/2837614.2837620. ISBN 978-1-4503-3549-2. S2CID  15401805.
  27. Джонатан Риз, «Схема вещей». Встреча в июне 1992 г. Архивировано 16 июля 2011 г. на Wayback Machine (постскриптум), в Lisp Pointers, V(4), октябрь–декабрь 1992 г. Получено 9 августа 2012 г.
  28. ^ Тейлор Кэмпбелл (21 июля 2005 г.). "SRFI 62: комментарии по S-выражению". Редакторы SRFI, schemers.org . Получено 09 августа 2012 г.
  29. ^ Уильям Д. Клингер (1999-07-01). "SRFI 6: Базовые струнные порты". Редакторы SRFI, schemers.org . Получено 09.08.2012 .
  30. ^ Скотт Г. Миллер (2002-06-25). "SRFI 28: Basic Format Strings". Редакторы SRFI, schemers.org . Получено 2012-08-09 .
  31. ^ JW Backus; FL Bauer; J.Green; C. Katz; J. McCarthy P. Naur; et al. (январь–апрель 1960 г.). «Пересмотренный отчет об алгоритмическом языке Algol 60». Numerische Mathematik, Communications of the ACM и Journal of the British Computer Society . Получено 09.08.2012 .
  32. ^ Джонатан Риз; Уильям Клингер, ред. (декабрь 1986 г.). «Пересмотренный(3) отчет о схеме алгоритмического языка (посвященный памяти АЛГОЛа 60)». ACM SIGPLAN Notices . 21 (12): 37–79. CiteSeerX 10.1.1.29.3015 . doi :10.1145/15042.15043. hdl :1721.1/6424. S2CID  43884422. Получено 09.08.2012 . 
  33. ^ "Scheme Systems Supporting SRFIs". Редакторы SRFI, schemers.org. 2009-08-30 . Получено 2012-08-09 .
  34. ^ 75 известных реализаций Scheme перечислены в "scheme-faq-standards". Сообщество Scheme Wiki. 2009-06-25 . Получено 2009-10-20 .
  35. ^ Эд Мартин (2009-07-20). "Список школ, использующих схему". Schemers Inc. Получено 2009-10-20 .
  36. ^ "Список школ, использующих SICP". MIT Press. 1999-01-26 . Получено 2009-10-20 .
  37. ^ Эрик Гримсон (весна 2005 г.). "6.001 Структура и интерпретация компьютерных программ". MIT Open Courseware . Получено 20 октября 2009 г.
  38. ^ Алекс Вандивер; Нельсон Эльхадж; и др. (январь 2009 г.). «6.184 — Зомби пьют кофеин 6.001». MIT CSAIL . Проверено 20 октября 2009 г.
  39. ^ Джон ДеНеро (осень 2019 г.). "Computer Science 61A, Berkeley". Department of Electrical Engineering and Computer Sciences, Berkeley . Получено 17 декабря 2019 г.
  40. ^ CS 2500: Основы компьютерных наук I, Северо-Восточный университет
  41. ^ CS 1101: Введение в проектирование программ (A05): программное обеспечение курса, Вустерский политехнический институт
  42. ^ "CSSE 304: Концепции языка программирования". Технологический институт Роуз-Халман .
  43. ^ "Весна 2021 CS121b Syllabus" (PDF) . Университет Брандейса .
  44. ^ "Главная". berkeley-cs61as.github.io .
  45. ^ Дэна Энглуин (осень 2009 г.). «Введение в информатику (CPSC 201)». Зоопарк, факультет компьютерных наук Йельского университета . Получено 20 октября 2009 г.
  46. ^ "Programming Design Paradigms CSG107 Course Readings". Северо-восточный университетский колледж компьютерных и информационных наук. Осень 2009 г. Получено 2012-08-09 .
  47. Структура компьютерного программирования I. Архивировано 19 июня 2010 г. на Wayback Machine , факультет компьютерных наук, Университет Миннесоты, весна 2010 г. (дата обращения 30 января 2010 г.).
  48. ^ Описание обязательных курсов CSci и другая информация. Архивировано 25 октября 2019 г. на Wayback Machine , кафедра компьютерных наук, Университет Миннесоты (дата обращения 25 октября 2019 г.)
  49. ^ CSCI 2041 — Комитет по учебной программе нового курса CSE, Университет Миннесоты (дата обращения: 25.10.2019)
  50. ^ Робин Кавер (25.02.2002). "DSSSL - Язык семантики и спецификации стилей документов. ISO/IEC 10179:1996". Титульные страницы . Получено 09.08.2012 .
  51. ^ " Основной язык сценариев для GIMP, который был присоединен к нему сегодня, — это Scheme. " Из Дова Гробгельда (2002). "Учебник по базовой схеме GIMP". Команда GIMP . Получено 09.08.2012 .
  52. ^ Тодд Грэм Льюис; Дэвид Золл; Джулиан Миссиг (2002). "GNOME FAQ из интернет-архива". Команда Gnome, gnome.org. Архивировано из оригинала 2000-05-22 . Получено 2012-08-09 .
  53. ^ "guile-gnome". Free Software Foundation . Получено 2012-08-09 .
  54. ^ Лоренс Бревард (2006-11-09). "Обновление программы Synopsys MAP-inSM: Форум разработчиков взаимодействия с EDA" (PDF) . Synopsis Inc . Получено 2012-08-09 .
  55. ^ Каваи, Сиро (октябрь 2002 г.). «Склеивание вещей — схема в реальном времени производства контента CG». Труды Первой международной конференции Lisp, Сан-Франциско : 342–348 . Получено 09.08.2012 .
  56. ^ Билл Магнусон; Хэл Абельсон и Марк Фридман (2009-08-11). «Под капотом App Inventor для Android». Google Inc, Официальный блог Google Research . Получено 2012-08-09 .

Дальнейшее чтение

Внешние ссылки