| Scheme | |
|---|---|
| パラダイム | マルチパラダイム:関数型、命令型、メタ |
| ファミリー | Lisp |
| 設計者 | Guy L. Steele、 Gerald Jay Sussman |
| 初登場 | 1975年 ( 1975 ) |
| 安定版リリース | R7RS / 2013 ( 2013 ) |
| 型付け規律 | 動的、潜在的、強力 |
| スコープ | レキシカル |
| ファイル名拡張子 | .scm、.ss |
| ウェブサイト | www.scheme.org |
| 主要な | |
| 多数 (Schemeの実装を参照) | |
| 影響を受けたもの | |
| ALGOL、Lisp、MDL | |
| 影響を受けたもの | |
| Clojure、Common Lisp、Dylan、EuLisp、Haskell、Hop、JavaScript、Julia、Lua、MultiLisp、Python、R、Racket、Ruby、Rust、[1] S、Scala、T | |
Schemeは、 Lisp系プログラミング言語の方言です。Schemeは1970年代にMITコンピュータ科学・人工知能研究所(MIT CSAIL)で開発され、開発者のGuy L. SteeleとGerald Jay Sussmanによって、現在Lambda Papersとして知られる一連のメモを通じて公開されました。Schemeは、レキシカルスコープを選択した最初のLisp方言であり、実装に末尾呼び出し最適化の実行を要求した最初のLisp方言でもあり、関数型プログラミングや再帰アルゴリズムなどの関連技術をより強力にサポートしました。また、第一級継続をサポートした最初のプログラミング言語の1つでもありました。Common Lispの開発につながる取り組みに大きな影響を与えました。[2]
Scheme言語は、電気電子学会(IEEE)の公式標準[3]および「アルゴリズム言語Schemeの改訂版報告書(RnRS )」と呼ばれる事実上の標準で標準化されています。広く実装されている標準はR5RS(1998年)です。[4] Schemeの最も最近承認された標準は「R7RS-small」(2013年)です。[5]より拡張性とモジュール性を備えたR6RSは2007年に承認されました。[6]どちらもR5RSから派生しており、以下のタイムラインは承認の時系列を示しています
歴史
起源
Schemeは1970年代にCarl HewittのActorモデルを理解する試みとして始まり、SteeleとSussmanはMaclispを使って「小さなLispインタプリタ」を書き、その後「アクターを作成してメッセージを送信するためのメカニズムを追加」しました。[7] Schemeは当初、 PlannerやConniverなどの他のLisp派生言語 と同様に「Schemer」と呼ばれていました。現在の名前は、作者がITSオペレーティングシステムを使用していたことに由来しています。ITSオペレーティングシステムでは、ファイル名が最大6文字の2つの要素に制限されていました。現在、「Schemer」はSchemeプログラマーを指すために一般的に使用されています。
R6RS
2003年のSchemeワークショップで新しい言語標準化プロセスが開始され、2006年にR6RS標準を作成することが目標となりました。このプロセスは、以前のR n RSの全会一致のアプローチ を打ち破りました
R6RSは標準モジュールシステムを備えており、コア言語とライブラリを分割できます。R6RS仕様のドラフトがいくつかリリースされ、最終バージョンはR5.97RSです。投票の結果、2007年8月28日に発表された新しい標準が承認されました。[6]
現在、様々なScheme実装[8]の最新リリースはR6RS標準をサポートしています。R6RS用に提案された暗黙的に段階的に実行されるライブラリの移植可能なリファレンス実装であるpsyntaxがあり、これは様々な古いScheme実装上で適切にロードおよびブートストラップされます。[9]
R6RSの機能の一つは、レコード型記述子(RTD)です。RTDを作成して使用すると、レコード型表現によってメモリレイアウトを示すことができます。また、オブジェクトフィールドのビットマスクと変更可能なSchemeオブジェクトフィールドのビットマスクを計算し、ガベージコレクタがRTDに保存されているフィールドリスト全体を走査することなく、フィールドをどのように処理するかを判断するのに役立ちました。RTDを使用すると、ユーザーは基本的なRTDを拡張して新しいレコードシステムを作成できます。[10]
R6RS では、言語に数多くの重要な変更が導入されています。[11] ソース コードはUnicodeで指定されるようになり、Unicode 文字の大部分のサブセットが Scheme のシンボルと識別子に表示できるようになりました。また、字句規則にその他の小さな変更もあります。文字データも Unicode で指定されるようになりました。多くの標準手続きが新しい標準ライブラリに移動されました。新しい標準ライブラリ自体は、以前は標準の一部ではなかった手続きと構文形式を含み、標準の大幅な拡張を構成しています。新しいモジュール システムが導入され、例外処理のシステムが標準化されました。syntax-rules は、マクロ展開時に Scheme 全体を使用できる、より表現力の高い構文抽象化機能 (syntax-case) に置き換えられました。準拠した実装では、 Scheme の完全な数値タワーをサポートすることが必須になり、数値の意味が拡張され、主に浮動小数点数値表現のIEEE 754標準をサポートする方向になりました。
R7RS
R6RS標準は、ミニマリストの哲学からの逸脱と見なす人もいるため、論争を巻き起こしています。[12] [13] 2009年8月、標準化プロセスを監督するScheme運営委員会は、Schemeを2つの言語に分割することを推奨する意向を発表しました。1つはプログラマー向けの大規模な現代プログラミング言語、もう1つは教育者や一般の実装者から高く評価されているミニマリズムを維持した大規模バージョンのサブセットである小規模バージョンです。[14] Schemeのこれらの2つの新しいバージョンに取り組むために、2つのワーキンググループが設立されました。Scheme Reports Processサイトには、ワーキンググループの規約、公開討論、問題追跡システムへのリンクがあります
R7RS(小型言語)の第9次ドラフトは2013年4月15日に公開されました。[15]このドラフトの批准投票は2013年5月20日に締め切られ、[16]最終報告書は2013年8月6日から公開されており、「その取り組みにおける『小型』言語であるため、R6RSの後継として単独で考えることはできない」と説明されています。[5]
| 1958 | 1960 | 1965 | 1970 | 1975 | 1980 | 1985 | 1990 | 1995 | 2000 | 2005 | 2010 | 2015 | 2020 | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| LISP 1、1.5、LISP 2 (廃止) | |||||||||||||||
| Maclisp | |||||||||||||||
| Interlisp | |||||||||||||||
| MDL | |||||||||||||||
| Lisp Machine Lisp | |||||||||||||||
| Scheme | R5RS | R6RS | R7RS small | ||||||||||||
| NIL | |||||||||||||||
| ZIL(Zork実装言語) | |||||||||||||||
| Franz Lisp | |||||||||||||||
| muLisp | |||||||||||||||
| Common Lisp | ANSI規格 | ||||||||||||||
| Le Lisp | |||||||||||||||
| MIT Scheme | |||||||||||||||
| XLISP | |||||||||||||||
| T | |||||||||||||||
| Chez Scheme | |||||||||||||||
| Emacs Lisp | |||||||||||||||
| AutoLISP | |||||||||||||||
| PicoLisp | |||||||||||||||
| Gambit | |||||||||||||||
| EuLisp | |||||||||||||||
| ISLISP | |||||||||||||||
| OpenLisp | |||||||||||||||
| PLT Scheme | Racket | ||||||||||||||
| newLISP | |||||||||||||||
| GNU Guile | |||||||||||||||
| Visual LISP | |||||||||||||||
| Clojure | |||||||||||||||
| Arc | |||||||||||||||
| LFE | |||||||||||||||
| Hy | |||||||||||||||
特徴
Schemeは主に関数型プログラミング言語です。Lispプログラミング言語ファミリーの他のメンバーと多くの特徴を共有しています。Schemeの非常にシンプルな構文は、S式、つまり前置演算子の後に引数が続く括弧で囲まれたリストに基づいています。したがって、Schemeプログラムはネストされたリストのシーケンスで構成されます。リストはSchemeの主要なデータ構造でもあり、ソースコードとデータ形式の間には高い等価性(同図像性)がもたらされます。Schemeプログラムは、Schemeコードの一部を動的に簡単に作成および評価できます
データ構造としてのリストへの依存は、すべてのLisp方言に共通しています。Schemeは、Lispの祖先から、、などの豊富なリスト処理プリミティブを継承しています。Schemeは、厳密かつ動的に型付けされた変数を使用し、ファーストクラス手続きをサポートしています。したがって、手続きは変数に値として割り当てたり、手続きに引数として渡したりすることができます
conscarcdr
このセクションでは、Schemeを他のLISPと区別する機能を含む、言語の革新的な機能を中心に説明します。特に明記しない限り、機能の説明はR5RS標準に関連しています。このセクションの例では、「===> 結果」という表記は、直前の行の式を評価した結果を示すために使用されます。これはR5RSで使用されているのと同じ表記です。
ミニマリズム
Schemeは非常にシンプルな言語であり、同等の表現力を持つ他の多くの言語よりも実装がはるかに容易です。[17]この容易さは、ラムダ計算 を用いて言語構文の多くをより基本的な形式から導出しているためです。例えば、R5RS Scheme標準で定義されている23のs式ベースの構文構成要素のうち、14は派生形式またはライブラリ形式に分類され、主にラムダ式などのより基本的な形式を含むマクロとして記述できます。R5RS (§3.1) には、「変数束縛構文の中で最も基本的なものはラムダ式です。なぜなら、他のすべての変数束縛構文はラムダ式で説明できるからです。」と記されています。[4]
- 基本形式:define、lambda、quote、if、define-syntax、let-syntax、letrec-syntax、syntax-rules、set!
- 派生形式:do、let、let*、letrec、cond、case、and、or、begin、named let、delay、unquote、unquote-splicing、quasiquote
例:変数束縛を実行するために
let使用する式として実装するマクロ。lambda
( define-syntax let ( syntax-rules () (( let (( var expr ) ... ) body ... ) (( lambda ( var ... ) body ... ) expr ... ))))
したがって、上記の定義を使用すると、letScheme実装では「(let ((a 1)(b 2)) (+ b a))」を「((lambda (a b) (+ b a)) 1 2)」に書き換え、実装のタスクを手続きのインスタンス化のコーディングにまで削減します
1998年、サスマンとスティールは、Schemeのミニマリズムは意識的な設計目標ではなく、設計プロセスの意図しない結果であると述べました。「私たちは実際には複雑なものを作ろうとしていましたが、偶然にも、すべての目標を満たしながらも、当初の意図よりもはるかに単純なものを設計してしまったことに気づきました。…ラムダ計算、つまり小さくシンプルな形式主義が、強力で表現力豊かなプログラミング言語の中核となる可能性があることに気づきました。」[7]
レキシカルスコープ
ほとんどの現代プログラミング言語と同様、そしてMaclispなどの初期の Lisp とは異なり、Scheme はレキシカル スコープを持ちます。つまり、プログラム単位内のすべての変数バインディングは、それが呼び出されるコンテキストを考慮せずに、プログラム単位のテキストを読み取ることによって解析できます。これは、当時のコンパイラやインタープリタでレキシカル スコープ アルゴリズムを実装するために使用されていた原始的なテキスト置換方法に関連する処理コストが原因であった、初期の Lisp 方言の特徴である動的スコープとは対照的です。当時の Lisp では、呼び出しのコンテキストに応じて、プロシージャ内の自由変数への参照がプロシージャ外部のまったく異なるバインディングを参照することが完全に可能でした。
1970年代初頭には珍しいスコープモデルであったレキシカルスコープを新しいバージョンのLispに取り入れるきっかけは、サスマンのALGOLの研究でした。彼は、 ALGOLのようなレキシカルスコープの仕組みが、ヒューイットのアクターモデルをLispに実装するという当初の目標を実現するのに役立つだろうと示唆しました。[7]
Lisp方言にレキシカルスコープを導入する方法に関する重要な洞察は、サスマンとスティールによる1975年のラムダ論文「Scheme:拡張ラムダ計算のためのインタープリタ」[18]で広く知られるようになりました。そこで彼らは、 1970年のAIメモでジョエル・モーゼスによって記述されていたレキシカルクロージャの概念(21ページ)を採用しました。モーゼスはこのアイデアをピーター・J・ランディンに帰しています。[19]
ラムダ計算
アロンゾ・チャーチの数学的記法であるラムダ計算は、Lispにおいて手続きを導入するためのキーワードとして「ラムダ」を使用するきっかけとなり、 Lispにおける高階関数の使用を含む関数型プログラミング技術の開発にも影響を与えました。しかし、初期のLispは自由変数の扱い方のためにラムダ計算の適切な表現ではありませんでした。[7]
形式ラムダシステムは公理と完全な計算規則を持ち、数学的論理とツールを用いた解析に役立ちます。このシステムでは、計算は方向的な演繹として捉えることができます。ラムダ計算の構文は、x、y、z、…、括弧、スペース、ピリオド、記号λからなる再帰式に従います。[20]ラムダ計算の機能は以下のとおりです。第一に、強力な数学的論理の出発点となること。第二に、機械による評価を模倣できるため、プログラマが実装の詳細を考慮する必要性を軽減できること。最後に、ラムダ計算は実質的なメタ理論を生み出しました。[21]
レキシカルスコープの導入により、ラムダ記法のいくつかの形式と、実用的なプログラミング言語におけるそれらの実際の表現との間に等価性がもたらされ、この問題は解決されました。サスマンとスティールは、ラムダ式を単なる手続きのインスタンス化ではなく「制御構造と環境修飾子」として使用することで、この新しい言語を使用して、ALGOLやFortranを含む他のプログラミング言語のすべての命令型および宣言型セマンティクス、および他のLISPの動的スコープをエレガントに導出できることを示しました。[22]彼らは最初のラムダ論文でSchemeの最初の記述とともに継続渡しスタイルを導入し、その後の論文では、ラムダ計算のこの実用的な使用法の真の威力を実証しました
ブロック構造
Schemeは、以前のブロック構造言語、特にALGOLからブロック構造を継承しています。Schemeでは、ブロックは3つの束縛構造、、によって実装されていますlet。例えば、次の構造は、シンボルが数値10に束縛される
ブロックを作成します。let*letrecvar
( define var "goose" ) ;; ここでのvarへの参照はすべて"goose"に束縛されます。 ( let (( var 10 )) ;; ここでのvarへの参照はすべて10に束縛されます。) ;; ここでのvarへの参照はすべて"goose"に束縛されます。
ブロックはネストして、プログラマーのニーズに応じて任意の複雑なブロック構造を作成できます。ブロック構造を使用してローカル束縛を作成することで、そうでなければ発生する可能性のある 名前空間の衝突のリスクが軽減されます
の 1 つの変形である ではlet、let*バインディングが同じ構造内で以前に定義された変数を参照することを許可します。
( let* (( var1 10 ) ( var2 ( + var1 12 ))) ;; しかし、var1の定義はvar2を参照できませんでした)
もう1つのバリエーションは、相互再帰的な手続きを互いに結合
letrecできるように設計されています。
;; ホフスタッターの男性と女性のシーケンスをペアのリストとして計算する
( define (ホフスタッター-男性-女性n ) ( letrec ((女性( lambda ( n ) ( if ( = n0 ) 1 ( -n (男性(女性( -n1 )))))))) (男性( lambda ( n ) ( if ( = n0 ) 0 ( -n (女性(男性( -n1 ) ) ) ) )))) ( let loop (( i0 ) ) ( if ( > in ) ' ( ) ( cons ( cons (女性i ) (男性i ) ) ( loop ( + i1 ) ) ) ) )))
ホフスタッター-男性-女性)
===> (( 1 . 0 ) ( 1 . 0 ) ( 2 . 1 ) ( 2 . 2 ) ( 3 . 2 ) ( 3 . 3 ) ( 4 . 4 ) ( 5 . 4 ) ( 5 . 5 ) )
で使用されている定義については、 ホフスタッターの男性と女性の配列を参照してください。)
1 つの にバインドされたすべてのプロシージャはletrec、名前によって互いを参照したり、同じ 内で前に定義された変数の値を参照したりできますが、同じ 内で後から定義された値letrecを参照することはできません。
letrec
の変種であるlet「名前付きlet」形式は、キーワードの後に識別子を持ちますlet。これは、let変数を、指定された識別子を名前とし、let形式の本体を本体とする手続きの引数に束縛します。手続きを呼び出すことで、本体は必要に応じて繰り返すことができます。名前付きletは、反復処理を実装するために広く使用されています。
例:単純なカウンタ
( let loop (( n 1 ) ) ( if ( > n 10 ) ' ( ) ( cons n ( loop ( + n 1 )))))
===> ( 1 2 3 4 5 6 7 8 9 10 )
Schemeの他の手続きと同様に、名前付きletで作成された手続きはファーストクラスオブジェクトです。
適切な末尾再帰
Schemeには反復構造がありますdoが、反復を表現するには末尾再帰を使用する方がSchemeではより慣用的です。標準に準拠したScheme実装では、末尾呼び出しを最適化して、無制限の数のアクティブな末尾呼び出しをサポートすることが求められます(R5RS セクション3.5)[4] — Schemeレポートでは適切な末尾再帰と説明されている特性— これにより、Schemeプログラマーは、より直感的な場合もある再帰構造を使用して反復アルゴリズムを安全に記述できます。末尾再帰手続きと名前付き形式は、末尾再帰を使用した反復をサポートします
let
;; 0から9までの正方形のリストを作成する:
;; 注:loopはラベルとして使用される任意のシンボルです。任意のシンボルを使用できます
( define (正方形のリストn ) ( let loop ( ( i n ) ( res ' ())) ( if ( < i 0 ) res ( loop ( - i 1 ) ( cons ( * i i ) res )))))
( list-of-squares 9 ) ===> ( 0 1 4 9 16 25 36 49 64 81 )
第一級継続
Schemeにおける継続はファーストクラスオブジェクトです。Schemeは、プログラマーが提供する手続きの仮引数に束縛されたエスケープ手続きとして現在の継続をパックすることで、それを捕捉する手続きcall-with-current-continuation(とも呼ばれます)を提供します。(R5RS 6.4節) [4]ファーストクラス継続により、
プログラマーはイテレーター、コルーチン、バックトラックなどの非局所的な制御構造を作成できますcall/cc
継続は、命令型プログラミング言語におけるreturn文の動作をエミュレートするために使用できます。次の関数はfind-first、関数funcとリストが与えられた場合、trueを返すlst最初の要素を返します。
xlst(func x)
( define ( find-first func lst ) ( call-with-current-continuation ( lambda ( return-immediately ) ( for-each ( lambda ( x ) ( if ( func x ) ( return-immediately x ))) lst ) #f )))
( find-first integer? ' ( 1/2 3/4 5.6 7 8/9 10 11 )) ===> 7 ( find-first zero? ' ( 1 2 3 4 )) ===> #f
以下の例は、伝統的なプログラマーのパズルですが、Schemeが継続をファーストクラスオブジェクトとして扱い、変数に束縛して手続きの引数として渡すことができることを示しています。
( let* (( yin (( lambda ( cc ) ( display "@" ) cc ) ( call-with-current-continuation ( lambda ( c ) c )))) ( yang (( lambda ( cc ) ( display "*" ) cc ) ( call-with-current-continuation ( lambda ( c ) c ))))) ( yin yang ))
このコードを実行すると、カウントシーケンスが表示されます。@*@**@***@****@*****@******@*******@********...
プロシージャと変数の共有名前空間
Common Lispとは対照的に、Schemeではすべてのデータと手続きが共通の名前空間を共有しますが、Common Lispでは関数とデータが別々の名前空間を持つため、関数と変数が同じ名前を持つことが可能になり、関数を値として参照するには特別な表記法が必要になります。これは、Schemeの統一された名前空間とCommon Lispの別々の名前空間を指し、「Lisp-1 vs. Lisp-2」の区別として知られることもあります。[23]
Schemeでは、データの操作とバインドに使用される同じプリミティブを、手続きのバインドに使用できます。Common Lispのプリミティブ
defunと同等のものはありません#'
;; 数値に束縛された変数:
( 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 6.2節[4])。標準ではこれらを抽象化として扱い、実装者に特定の内部表現を強制しません
数値には正確性という性質があります。正確な数値は、他の正確な数値を含む一連の正確な演算によってのみ生成できます。したがって、不正確性は伝染します。標準では、任意の2つの実装は、正確な数値を返すすべての演算に対して同等の結果を生成しなければならないと
exact->inexactR5RS標準では、inexact->exact数値の正確性を変更するために使用できる手続きとを規定してinexact->exactいます。は「引数に数値的に最も近い正確な数値」を生成します。exact->inexactは「引数に数値的に最も近い不正確な数値」を生成します。R6RS標準では、これらの手続きをメインレポートから省略していますが、標準ライブラリ(rnrs r5rs (6))ではR5RS互換手続きとして規定しています
R5RS標準では、Scheme実装は数値タワー全体を実装する必要はありませんが、「実装の目的とScheme言語の精神の両方に一致する一貫したサブセット」を実装する必要があります(R5RS 6.2.3節)。[4] 新しいR6RS標準では、タワー全体の実装と、「実質的に無制限のサイズと精度を持つ正確な整数オブジェクトと正確な有理数オブジェクト、そして正確な引数が与えられた場合に常に正確な結果を返すような特定の手続きの実装」が要求されています(R6RS 3.4節、11.7.1節)。[6]
例1:正確な有理複素数をサポートする実装における正確な算術演算
;; 3つの有理数実数と2つの有理複素数の和
( xを定義( + 1/3 1/4 -1/5 -1/3i 40 5/50 + 2/3i )) x ===> 50 9/60 + 1/3i ;; 正確性をチェックします。(正確?x ) ===> #t
例2:正確な有理数も複素数もサポートしていないが、有理数表記の実数を受け入れる実装における同じ演算
;; 4つの有理実数の和
( xr ( + 1/3 1/4 -1/5 405/50 )と定義) ;; 2つの有理実数の和( xi ( + -1/3 2/3 )と定義) xr ===> 8.48333333333333 xi ===> 0.333333333333333 ;; 正確性をチェックします。( exact? xr ) ===> #f ( exact? xi ) ===> #f
どちらの実装も R5RS 標準に準拠していますが、2 番目の実装は完全な数値タワーを実装していないため、R6RS に準拠していません。
遅延評価
delaySchemeは、フォームと手続きを通じて遅延評価をサポートしていますforce。
( define a 10 ) ( define eval-aplus2 ( delay ( + a 2 ))) ( set! a 20 ) ( force eval-aplus2 ) ===> 22 ( define eval-aplus50 ( delay ( + a 50 ))) ( let (( a 8 )) ( force eval-aplus50 )) ===> 70 ( set! a 100 ) ( force eval-aplus2 ) ===> 22
promiseの元の定義の語彙的文脈は保存され、その値も最初に使用された後に保存されますforce。promiseは一度だけ評価されます。
これらのプリミティブは、プロミスと呼ばれる値を生成または処理し、ストリームなどの高度な遅延評価構造を実装するために使用できます。[24]
R6RS標準では、これらはもはやプリミティブではなく、R5RS互換ライブラリ(rnrs r5rs (6))の一部として提供されています。
R5RSでは、delayおよびの実装が提案forceされており、Promiseを引数のない手続き(サンク)として実装し、メモ化を使用して、呼び出される回数に関係なく、一度だけ評価されることを保証しますforce(R5RS 6.4節)。[4]
SRFI 41は、有限数列と無限数列の両方を非常に経済的に表現することを可能にします。例えば、これはSRFI 41で定義された関数を使用したフィボナッチ数列の定義です。 [24]
;; フィボナッチ数列を定義します:
( define fibs ( stream-cons 0 ( stream-cons 1 ( stream-map + fibs ( stream-cdr fibs ))))) ;; 数列の100番目の数を計算します: ( stream-ref fibs 99 ) ===> 218922995834555169026
手続き引数の評価順序
ほとんどのLispは、手続きの引数の評価順序を指定します。Schemeは指定しません。評価順序(演算子位置の式の評価順序を含む)は、呼び出しごとに実装によって選択でき、唯一の制約は「演算子とオペランド式の同時評価の効果は、何らかの順次的な評価順序と一致するように制約される」ことです。(R5RS 4.1.3節)[4]
( let (( ev ( lambda ( n ) ( display "Evaluating " ) ( display ( if ( procedure ? n ) "procedure" n ) ) ( newline ) n ))) (( ev + ) ( ev 1 ) ( ev 2 ) ) ) === > 3
を
評価中
evは渡された引数を記述し、その引数の値を返す手続きです。他のLispとは異なり、Scheme式の演算子位置(最初の項目)に式を記述することは、演算子位置の式の結果が手続きである限り、全く問題ありません。
1と2を加算する手続き「+」を呼び出す場合、式(ev +)、(ev 1)、(ev 2)は、並列に評価されたかのようにならない限り、任意の順序で評価できます。したがって、上記のサンプルコードを実行すると、次の3行は標準Schemeによって任意の順序で表示されますが、1行のテキストを別の行と交互に配置することはできません。これは、順次評価の制約に違反するためです。
衛生的なマクロ
R5RS標準およびその後の報告書では、Schemeの構文はマクロシステムを介して簡単に拡張できます。R5RS標準では、プログラマーが単純なパターンマッチングサブ言語を使用して言語に新しい構文構造を追加できる強力な衛生的なマクロシステムが導入されました(R5RS 4.3節)。[4] これ以前は、衛生的なマクロシステムは、R4RS標準の付録に、「高レベル」システムと「低レベル」マクロシステムとして格下げされており、どちらも言語の本質的な部分ではなく、Schemeの拡張機能として扱われていました。[25]
衛生的なマクロシステム( とも呼ばれるsyntax-rules)の実装は、言語の他の部分の語彙スコープを尊重する必要があります。これは、マクロ展開のための特別な命名規則とスコープ規則によって保証され、他のプログラミング言語のマクロシステムで発生する可能性のある一般的なプログラミングエラーを回避します。R6RSは、より洗練された変換システム を規定しておりsyntax-case、これはR5RS Schemeの言語拡張として以前から利用可能でした。
;; 複数式の真分岐と偽分岐のない
「if」の亜種を実装するマクロを定義します。( define-syntax when ( syntax-rules () (( when pred exp exps ... ) ( if pred ( begin exp exps ... )))))
マクロとプロシージャの呼び出しは非常によく似ています。どちらもS式ですが、扱いが異なります。コンパイラはプログラム内でS式に遭遇すると、まずそのシンボルが現在のレキシカルスコープ内で構文キーワードとして定義されているかどうかを確認します。定義されている場合、マクロの展開を試み、S式の末尾にある項目を引数として扱いますが、評価するためのコードはコンパイルしません。このプロセスは、マクロ呼び出しがなくなるまで再帰的に繰り返されます。構文キーワードでない場合、コンパイラはS式の末尾にある引数を評価するコードをコンパイルし、次にS式の先頭にあるシンボルで表される変数を評価し、評価された末尾の式を引数として渡してプロシージャとして呼び出します
ほとんどのScheme実装は、追加のマクロシステムも提供しています。人気のあるものとしては、構文クロージャ、明示的な名前変更マクロ、そしてCommon Lispで提供されているシステムdefine-macroに似た非衛生的なマクロシステムであるがあります。
defmacro
マクロが衛生的かどうかを指定できないことは、マクロシステムの欠点の1つです。スコープセットなどの拡張のための代替モデルは、潜在的な解決策となります。[26]
環境とeval
R5RS以前、Schemeにはeval他のLISPで広く普及している手続きに相当する標準的なものはありませんでしたが、最初のLambda Paperではevaluate「LISP関数EVALに似ている」[18]と説明され、1978年の最初の改訂報告書ではこれをenclose2つの引数を取るに置き換えました。2回目、3回目、4回目の改訂報告書では、同等のものは省略されましたeval。
この混乱の原因は、Schemeのレキシカルスコープでは、式の評価結果が評価場所によって異なるためです。例えば、次の式を評価した結果が5になるのか6になるのかは明確ではありません。[27]
( let (( name '+ )) ( let (( + * )) ( evaluate ( list name 2 3 ))))
が定義されている外部環境で評価された場合name、結果はオペランドの合計になります。シンボル「+」が手続き「*」の値に束縛されている内部環境で評価された場合、結果は2つのオペランドの積になります
evalR5RSは、環境を返す3つの手続きを指定し、 S式と環境を取り、提供された環境で式を評価する手続きを提供することで、この混乱を解決しています。(R5RS 6.5節) [4]environment R6RSはこれを拡張し、プログラマが評価環境にインポートするオブジェクトを正確に指定できる、
呼び出される手続きを提供しています
現代のスキーム(通常はR5RSと互換性があります)でこの式を評価するには、evaluate次のような関数を定義する必要があります。
( define ( evaluate expr ) ( eval expr ( interaction-environment )))
interaction-environmentはインタプリタのグローバル環境です。
ブール式における非ブール値の扱い
Common Lispを含むほとんどのLisp方言では、慣例により、ブール式では の値はNIL偽値として評価されます。Schemeでは、1991年のIEEE標準[3]以降、を除くすべての値(Schemeでは と表記される を#f含む)は、ブール式では の値が真値として評価されます。(R5RS sec. 6.3.1) [4]NIL'()
ほとんどのLispでは真値のブール値を表す定数は ですがT、Schemeでは です#t。
プリミティブデータ型の分離性
Schemeでは、プリミティブデータ型は互いに素です。任意のSchemeオブジェクトについて真となり得る述語は、boolean?、pair?、symbol?、number?、char?、string?、、のうち1つだけですvector?。(R5RS sec. 3.2) [4]port?procedure?
対照的に、数値データ型では、数値は重複する。例えば、整数値は、、、、の述語をすべて同時に満たす。integer?( R5RS 6.2節) [4]rational?real?complex?number?
同値述語
Schemeには、任意のオブジェクト間の3つの異なる同値述語、等価性をテストするための関係演算子、、およびで表される3つの異なるタイプの同値性があります。eq?eqv?equal?
eq?#fパラメータがメモリ内の同じデータオブジェクトを表していない限りはと評価されますeqv?は一般的にと同じですが、eq?プリミティブオブジェクト(文字や数値など)を特別に扱うため、同じ値を表す数値は、eqv?同じオブジェクトを参照していなくても偶数になります。equal?リスト、ベクター、文字列などのデータ構造を比較し、それらの構造とeqv?内容が合同かどうかを判断します。(R5RS 6.1節) [4]
Schemeには型依存の同値演算も存在します。string=?と はstring-ci=?2つの文字列を比較します(後者は大文字と小文字を区別しない比較を行います)。char=?と は文字を比較します。数値を比較します。[4]char-ci=?=
コメント
R5RS標準までは、Schemeの標準コメントはセミコロンで、これにより行の残りの部分はSchemeには見えなくなります。多くの実装では、コメントを複数行に拡張することを許可する代替規則をサポートしており、R6RS標準ではそのうち2つが許可されています。S式全体をコメント(または「コメントアウト」)にするには、その前に を置きます#;(SRFI 62 [28]で導入) 。
#|また、テキストを と で囲むことで、複数行コメントまたは「ブロックコメント」を作成できます|#
入出力
Schemeの入出力は、portデータ型に基づいています。(R5RS 6.6節) [4] R5RSは、手続き と でアクセスできる2つのデフォルトポートを定義していますcurrent-input-port。current-output-portこれらは、Unixの標準入力と標準出力の概念に対応しています。ほとんどの実装では も提供していますcurrent-error-port。入力と標準出力のリダイレクトは、標準ではwith-input-from-fileやなどの標準手続きによってサポートされていますwith-output-to-file。ほとんどの実装では、同様のリダイレクト機能を持つ文字列ポートが提供されており、SRFI 6で説明されている手続きを使用して、多くの通常の入出力操作をファイルではなく文字列バッファに対して実行できます。[29] R6RS標準では、より洗練され、機能豊富なポート手続きと多くの新しいタイプのポートが規定されています。
以下の例は、厳密なR5RS Schemeで記述されています。
例1:出力のデフォルトを(current-output-port)とする場合:
( let (( hello0 ( lambda () ( display "Hello world" ) ( newline )))) ( hello0 ))
例2:例1と同様ですが、出力手続きにオプションのポート引数を使用します。
( let (( hello1 ( lambda ( p ) ( display "Hello world" p ) ( newline p )))) ( hello1 ( current-output-port )))
例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 Schemeは述語input-port?とを提供していますoutput-port?。文字の入出力にはwrite-char、、、が提供されています。Scheme式の書き込みと読み取りには、Schemeはとを提供していますread-char。読み取り操作では、入力ポートがファイルの末尾に達した場合、返される結果はファイル終端オブジェクトであり、これは述語を使用してテストできます。
peek-charchar-ready?readwriteeof-object?
この標準では、SRFI 28でCommon Lispの 関数に似た基本的なフォーマット手続きも定義されておりformat、その名前が付けられています。[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 7.1節) [6] このため、標準手続きの突然変異による再定義は禁止されています。代わりに、標準手続きの名前で別の手続きをインポートすることが可能であり、これは事実上再定義に似ています
命名法と命名規則
標準Schemeでは、あるデータ型から別のデータ型に変換する手続きの名前には文字列「->」が含まれ、述語は「?」で終わり、すでに割り当てられたデータの値を変更する手続きは「!」で終わります。これらの規則は、Schemeプログラマーがしばしば従います。
Scheme標準などの正式な文脈では、ラムダ式またはプリミティブ手続きを指す場合、「関数」よりも「手続き」という単語が優先的に使用されます。通常の用法では、「手続き」と「関数」という単語は同じ意味で使用されます。手続き適用は、正式には組み合わせと呼ばれることもあります。
他のLispと同様に、Schemeでは「サンク」という用語は引数のない手続きを指すために使用されます。「適切な末尾再帰」という用語は、すべてのScheme実装の特性、つまり、 無限数のアクティブな末尾呼び出しをサポートするために末尾呼び出し最適化を実行することを指します
R3RS以降の標準文書のタイトル形式「アルゴリズム言語スキームの改訂報告書」は、 ALGOL 60標準文書のタイトル「アルゴリズム言語Algol 60の改訂報告書」を参照しています。R3RSの要約ページは、ALGOL 60報告書の要約ページを忠実にモデル化しています。[31] [32]
標準形式と手続きのレビュー
この言語は、標準R5RS(1998)[4]およびR6RS(2007)[6]で正式に定義されています。 これらは、言語の制御構造を提供するキーワードとそれに付随する構文、および一般的なタスクを実行する標準手続きという標準的な「形式」を記述しています。
標準形式
この表は、Schemeの標準形式について説明しています。一部の形式は、言語内の単一の関数に簡単に分類できないため、複数の行に表示されます
この表で「L」とマークされたフォームは、標準では派生「ライブラリ」フォームとして分類されており、実際にはより基本的なフォームを使用してマクロとして実装されることが多く、他の言語よりも実装がはるかに容易になります。
| 目的 | フォーム |
|---|---|
| 定義 | define |
| 束縛構造 | lambda、do (L)、let (L)、let* (L)、letrec (L) |
| 条件評価 | if、cond (L)、case (L)、and (L)、or (L) |
| 逐次評価 | begin (*) |
| 反復 | lambda、do (L)、名前付きlet (L) |
| 構文拡張 | define-syntax、let-syntax、letrec-syntax、syntax-rules (R5RS)、syntax-case (R6RS) |
| 引用 | quote(')、unquote(,)、quasiquote(`)、unquote-splicing(,@) |
| 代入 | set! |
| 遅延評価 | delay (L) |
beginR5RSではライブラリ構文として定義されています
が、スプライシング機能を実現するためには、展開側はこれを認識している必要があります。R6RSでは、ライブラリ構文ではなくなりました。
標準手続き
次の2つの表は、R5RS Schemeの標準手続きについて説明しています。R6RSははるかに広範囲にわたるため、このタイプの要約は現実的ではありません。
一部の手続きは、言語の単一の関数に簡単に分類できないため、複数の行に表示されます。
| 目的 | 手続き |
|---|---|
| 構築 | vector、make-vector、make-string、list |
| 同値述語 | eq?、eqv?、equal?、string=?、string-ci=?、char=?、char-ci=? |
| 型変換 | vector->list、list->vector、number->string、string->number、symbol->string、string->symbol、char->integer、integer->char、string->list、list->string |
| 数値 | 別表を参照 |
| 文字列 | string?、make-string、string、string-length、string-ref、string-set!、string=?、string-ci=?、string<? string-ci<?、string<=? string-ci<=?、string>? string-ci>?、string>=? string-ci>=?、substring、string-append、string->list、list->string、string-copy、string-fill! |
| 文字 | char?、char=?、char-ci=?、char<? char-ci<?、char<=? char-ci<=?、char>? char-ci>?、char>=? char-ci>=?、char-alphabetic?、char-numeric?、char-whitespace?、char-upper-case?、char-lower-case?、char->integer、integer->char、char-upcase、char-downcase |
| ベクトル | make-vector、vector、vector?、vector-length、vector-ref、vector-set!、vector->list、list->vector、vector-fill! |
| シンボル | symbol->string、string->symbol、symbol? |
| ペアとリスト | pair?、cons、car、cdr、set-car!、set-cdr!、null?、list?、list、length、append、reverse、list-tail、list-ref、memq、memv、member、assq、assv、assoc、list->vector、vector->list、list->string、string->list |
| 同一性述語 | boolean?、pair?、symbol?、number?、char?、string?、vector?、port?、procedure? |
| 継続 | call-with-current-continuation (call/cc)、values、call-with-values、dynamic-wind |
| 環境 | eval、scheme-report-environment、null-environment、interaction-environment(オプション) |
| 入出力 | display、newline、read、write、read-char、write-char、peek-char、char-ready?、eof-object?、open-input-file、open-output-file、close-input-port、close-output-port、input-port?、output-port?、current-input-port、current-output-port、call-with-input-file、call-with-output-file、with-input-from-file(optional)、with-output-to-file(optional) |
| システムインターフェース | load (optional)、transcript-on (optional)、transcript-off (optional) |
| 遅延評価 | force |
| 関数型プログラミング | procedure?、apply、map、for-each |
| ブール値 | boolean? not |
名前に「-ci」を含む文字列および文字のプロシージャは、引数間の大文字と小文字を区別しない比較を行います。同じ文字の大文字と小文字は等しいとみなされます
| 目的 | 手続き |
|---|---|
| 基本的な算術演算子 | +、-、*、/、絶対値、商、剰余、剰余、最大公約数、最小公倍数、指数、平方根 |
| 有理数 | 分子、分母、有理数?、合理化 |
| 近似 | 切り捨て、切り上げ、切り捨て、丸め |
| 正確性 | 不正確→正確、正確→不正確、正確?、不正確? |
| 不等式 | <、<=、>、>=、= |
| その他の述語 | ゼロ?、負?、正?、奇数?、偶数? |
| 最大値と最小値 | 最大値、最小値 |
| 三角法 | sin、cos、tan、asin、acos、atan |
| 指数 | 指数、対数 |
| 複素数 | 直交変換、極変換、実部、虚部、大きさ、角度、複素数? |
| 入出力 | 数値->文字列、文字列->数値 |
| 型述語 | 整数?、有理数?、実数?、複素数?、数値? |
2つ以上の引数を取る-と/の実装はR5RSで定義されていますが、オプションとなっています。
Scheme実装要求
Schemeのミニマリズムのため、多くの共通手続きと構文形式は標準では定義されていません。コア言語を小さく保ちながら拡張機能の標準化を促進するために、Schemeコミュニティには「Scheme実装要求」(SRFI)プロセスがあり、拡張提案について慎重に議論することで拡張ライブラリが定義されます。これにより、コードの移植性が促進されます。多くのSRFIは、すべてまたはほとんどのScheme実装でサポートされています。
さまざまな実装でかなり広くサポートされているSRFIには、以下のものがあります。 [33]
- 0:機能ベースの条件付き展開構造
- 1:リストライブラリ
- 4:同種の数値ベクトルデータ型
- 6:基本文字列ポート
- 8:受信、複数の値へのバインディング
- 9: レコード型の定義
- 13: 文字列ライブラリ
- 14: 文字セットライブラリ
- 16: 可変個引数の手続きの構文
- 17: 一般化された集合
- 18: マルチスレッドのサポート
- 19: 時間データ型と手続き
- 25: 多次元配列プリミティブ
- 26:カリー化なしでパラメータを特殊化するための表記法
- 27: ランダムビットの発生源
- 28: 基本書式文字列
- 29:ローカライゼーション
- 30: ネストされた複数行コメント
- 31: 再帰評価のための特殊形式
- 37: args-fold: プログラム引数プロセッサ
- 39: パラメータオブジェクト
- 41:ストリーム
- 42:先行内包表記
- 43: ベクトルライブラリ
- 45: 反復的な遅延評価アルゴリズムを表現するためのプリミティブ
- 60: 整数をビットとして
- 61: より一般的なcond節
- 66: オクテットベクトル
- 67: 比較手続き
実装
エレガントでミニマリスト的な設計により、Schemeは言語設計者、愛好家、教育者にとって人気のあるターゲットとなっています。また、典型的なインタプリタと同じくらい小さいサイズであるため、組み込みシステムやスクリプトでも人気のある選択肢となっています。その結果、数多くの実装[34]が生まれましたが、そのほとんどは互いに大きく異なるため、ある実装から別の実装へのプログラムの移植は非常に困難です。また、標準言語のサイズが小さいため、標準的で移植性の高いSchemeで非常に複雑な有用なプログラムを作成することはほぼ不可能です。[14] R6RS標準は、プログラマーへの魅力を広げるために、はるかに幅広い言語を規定しています
ほぼすべての実装は、開発とデバッグのために、従来のLispスタイルのread-eval-printループを提供しています。また、多くの実装はSchemeプログラムを実行可能バイナリにコンパイルします。Scheme実装は比較的単純なため、Cなどの言語で開発された大規模システムにスクリプト機能を追加する際によく選ばれており、他の言語で書かれたプログラムへのSchemeコードの埋め込みもサポートされています。Gambit 、Chicken、BiglooのSchemeインタープリタはSchemeをCにコンパイルするため、埋め込みがはるかに容易になります。さらに、BiglooのコンパイラはJava仮想マシン(JVM)用のバイトコードを生成するように設定でき、 .NET用の実験的なバイトコードジェネレータも備えています。
一部の実装は追加機能をサポートしています。たとえば、KawaとJSchemeはJavaクラスとの統合を提供し、SchemeからCへのコンパイラはCで書かれた外部ライブラリの使用を容易にし、SchemeソースコードへのCコードの埋め込みまで可能にします。もう1つの例はPvtsで、Scheme学習をサポートするビジュアルツールセットを提供しています。
使用方法
Scheme は多くの学校で広く使用されています[35]。特に、いくつかの入門コンピュータサイエンスのコースでは、教科書Structure and Interpretation of Computer Programs (SICP)と併せて Scheme を使用しています[36] 。過去 12 年間、PLT はProgramByDesign (旧称 TeachScheme!) プロジェクトを運営し、600 人近くの高校教師と何千人もの高校生に初歩的な Scheme プログラミングに触れさせてきました。MITの古い入門プログラミング クラス 6.001 は Scheme で教えられていました[ 37] 。6.001はより現代的なコースに置き換えられましたが、SICP は引き続き MIT で教えられています[38] 。同様に、カリフォルニア大学バークレー校の入門クラスCS 61A は、動的スコープを示すためにLogoに少し転用した以外は、2011 年まで完全に Scheme で教えられていました。現在、MITと同様に、バークレー校もシラバスをより現代的なバージョンに置き換え、主にPython 3で教えていますが、現在のシラバスは依然として古いカリキュラムに基づいており、授業の一部は依然としてSchemeで教えられています。[39]
教科書「プログラムの設計方法」は、一部の高等教育機関のコンピュータサイエンスの入門コースで使用されています。ウースター工科大学は、入門コース「プログラム設計入門」(CS1101) でのみ Scheme を使用しています。[40] ローズハルマン工科大学では、より高度なプログラミング言語の概念のコースで Scheme を使用しています。[41] ブランダイス大学の主要コースである「コンピュータプログラムの構造と解釈」(COSI121b) も、理論計算機科学者のハリー・メアソンによって Scheme のみで教えられています。[42] インディアナ大学の入門クラス C211 は、完全に Scheme で教えられています。自分のペースで学習できるバージョンのコースである CS 61AS では、引き続き Scheme を使用しています。[43]イェール大学とグリネル大学のコンピュータサイエンスの入門コースも Scheme で教えられています。[44] ミネソタ大学ツインシティ校の以前のコンピュータサイエンス入門コースであるCSCI 1901でもSchemeを主要言語として使用し、その後、学生にJava言語を紹介するコースが続きました。[45]しかし、MITの例に倣い、学科は1901をPythonベースのCSCI 1133に置き換えました。[46 ]一方、関数型プログラミングは3学期目のコースであるCSCI 2041で詳細に扱われています。[47]
Schemeは、以下の目的にも使用されていました。
- SGMLスタイルシートを指定する方法を提供する文書スタイルセマンティクスおよび仕様言語(DSSSL)は、Schemeのサブセットを使用しています。[48]
- よく知られているオープンソースの ラスターグラフィックエディタである GIMPは、スクリプト言語としてTinySchemeを使用しています。[49]
- GuileはGNUプロジェクトによって公式スクリプト言語として採用されており、Schemeの実装はGNU LilyPondやGnuCashなどのアプリケーションに拡張機能用のスクリプト言語として組み込まれています。同様に、Guileはかつてデスクトップ環境 GNOMEのスクリプト言語でした。 [ 50]また、GNOMEには現在もライブラリスタックにGuileバインディングを提供するプロジェクトがあります。[51] GNUの主力プログラムであるGNU EmacsにGuileを組み込み、現在のEmacs Lispインタプリタを置き換えるプロジェクトもあります。[要出典]
- Elk Schemeは、シノプシスのテクノロジーCAD(TCAD)ツールのスクリプト言語として使用されています。[52]
- 映画『ファイナルファンタジー ザ・スピリッツ・ウィズイン』のシニアプログラマーである河合史朗氏は、リアルタイムレンダリングエンジンを管理するためのスクリプト言語としてSchemeを使用しました。[53]
- Android版Google App InventorはSchemeを使用しており、KawaはAndroidデバイス上で実行されるJava仮想マシン用のバイトコードにSchemeコードをコンパイルするために使用されています。[54]
参照
- Schemeを基礎とした教科書『プログラミング言語の基礎』
参考文献
- ^ 「影響 - Rustリファレンス」。Rustリファレンス。2023年4月18日閲覧
- ^ Common LISP: The Language, 2nd Ed., Guy L. Steele Jr. Digital Press; 1981. ISBN 978-1-55558-041-4。「Common LispはLispの新しい方言であり、MacLispの後継であり、ZetaLispの影響を強く受け、ある程度はSchemeとInterLispの影響を受けています。」
- ^ ab 1178-1990 (Reaff 2008) Schemeプログラミング言語のIEEE標準。IEEE部品番号STDPD14209、2008年3月26日のIEEE-SA標準化委員会標準審査委員会(RevCom)会議(議事録に関する項目6.3)で全会一致で再確認。再確認議事録は2009年10月にアクセス。この文書はIEEEからのみ購入可能であり、執筆時点(2009年)ではオンラインでは入手できません
- ^ abcdefghijklmnopqr リチャード・ケルシー、ウィリアム・クリンガー、ジョナサン・リース他 (1998年8月). 「アルゴリズム言語Schemeに関する改訂報告書」 .高階および記号計算. 11 (1): 7–105 . doi :10.1023/A:1010051815785. S2CID 14069423. 2012年8月9日閲覧.
- ^ ab 「R7RS最終版公開」(PDF) . 2013年7月6日
- ^ abcde Sperber, Michael; Dybvig, R. Kent; Flatt, Matthew; Van Straaten, Anton; et al. (2007年8月). 「アルゴリズム言語Scheme (R6RS) に関する改訂報告書」. Scheme運営委員会. 2011年9月13日閲覧.
- ^ abcd Sussman, Gerald Jay; Steele, Guy L. (1998年12月1日). 「Scheme再考に関する最初の報告書」. Higher-Order and Symbolic Computation . 11 (4): 399– 404. doi :10.1023/A:1010079421970. S2CID 7704398
- ^ 「R6RS実装」r6rs.org 。 2017年11月24日閲覧。
- ^ Abdulaziz Ghuloum (2007年10月27日).「R6RSライブラリと構文ケースシステム(psyntax)」Ikarus Scheme 。2009年10月20日閲覧
- ^ Keep, Andrew W.; Dybvig, R. Kent (2014年11月). 「Schemeレコード型の実行時表現」. Journal of Functional Programming . 24 (6): 675– 716. doi : 10.1017/S0956796814000203 . S2CID 40001845.
- ^ 「アルゴリズム言語Schemeに関する改訂版^6報告書、付録E:言語の変更」Scheme運営委員会。2007年9月26日。2009年10月20日閲覧。
- ^ 「R6RS選挙区」Scheme運営委員会。2007年。 2012年8月9日閲覧。
- ^ Marc Feeley(編集)(2007年10月26日)。「R6RSに関する実装者の意図」Scheme運営委員会、r6rs-discussメーリングリスト。2008年8月20 日時点のオリジナルからのアーカイブ。 2012年8月9日閲覧
- ^ Will Clinger、Marc Feeley、Chris Hanson、Jonathan Rees、Olin Shivers (2009年8月20日). 「立場表明(草案)」. Scheme運営委員会. 2012年8月9日閲覧.
{{cite web}}: CS1 maint: multiple names: authors list ( link ) - ^ 「R7RS第9版草案公開」(PDF) . 2013年4月15日閲覧.
- ^ Will Clinger (2013年5月10日). 「投票期間の延長」. Scheme言語運営委員会、scheme-reportsメーリングリスト. 2013年7月21日時点のオリジナルからのアーカイブ。2013年7月7日閲覧
- ^ The Scheme 48 implementation is so-named because the interpreter was written by Richard Kelsey and Jonathan Rees in 48 hours (August 6th – 7th, 1986. See Richard Kelsey; Jonathan Rees; Mike Sperber (2008-01-10). "The Incomplete Scheme 48 Reference Manual for release 1.8". Jonathan Rees, s48.org. Retrieved 2012-08-09.
- ^ a b Gerald Jay Sussman & Guy Lewis Steele Jr. (December 1975). "Scheme: An Interpreter for Extended Lambda Calculus" (PDF). AI Memos. AIM-349. MIT AI Lab. hdl:1721.1/5794. Retrieved 23 December 2021.
- ^ Joel Moses (1970年6月), The Function of FUNCTION in LISP, or Why the FUNARG Problem Should Be Called the Environment Problem , hdl :1721.1/5854, AI Memo 199,
LISPにおけるFUNCTIONとQUOTEの違いを表す便利な比喩として、QUOTEを関数の多孔質または開放的な被覆と考えることが挙げられます。これは、自由変数が現在の環境に逃げ込むためです。FUNCTIONは、閉じた、または非多孔質の被覆として機能します(Landinが「閉包」という用語を使用したのはそのためです)。したがって、私たちは「開いた」ラムダ式(LISPの関数は通常ラムダ式です)と「閉じた」ラムダ式について話しているのです。[...] 環境問題への私の関心は、この問題を深く理解していたLandinが1966年から67年にかけてMITを訪れた際に始まりました。その後、
LISP
の「閉じた」ラムダ式の評価結果であるFUNARGリスト
と
ISWIM
のラムダ閉包との対応に気づきました。
- ^ van Tonder, André (2004年1月1日). 「量子計算のためのラムダ計算」. SIAM Journal on Computing . 33 (5): 1109–1135 . arXiv : quant-ph/0307150 . doi :10.1137/S0097539703432165. S2CID 613571
- ^ Niehren, J.; Schwinghammer, J.; Smolka, G. (2006年11月). 「Futuresを備えた並行ラムダ計算」(PDF) .理論計算機科学. 364 (3): 338– 356. doi :10.1016/j.tcs.2006.08.016.
- ^ Gerald Jay Sussman & Guy Lewis Steele Jr. (1976年3月). 「Lambda: The Ultimate Imperative」. AI Memos . AIM-353. MIT AI Lab . 2016年5月10日時点のオリジナル(PostscriptまたはPDF)からアーカイブ。2012年8月9日閲覧
- ^ Gabriel, Richard P. ; Pitman, Kent (1988). 「関数セルと値セルの分離に関する技術的問題」. LISP and Symbolic Computation . 第1巻第1号 (1988年6月発行). pp. 81– 101. doi :10.1007/BF01806178 . 2012年8月9日閲覧.
- ^ ab Philip L. Bewig (2008年1月24日). 「SRFI 41: ストリーム」. The SRFI Editors, schemers.org . 2012年8月9日閲覧
- ^ William ClingerとJonathan Rees編 (1991). 「アルゴリズム言語Schemeに関する改訂報告書」. ACM Lisp Pointers . 4 (3): 1– 55. 2012年8月9日閲覧.
- ^ Flatt, Matthew (2016). 「スコープの集合としての束縛」.第43回ACM SIGPLAN-SIGACTプログラミング言語の原理に関するシンポジウム議事録. pp. 705– 717. doi :10.1145/2837614.2837620. ISBN 978-1-4503-3549-2. S2CID 15401805
- ^ Jonathan Rees, The Scheme of Things The June 1992 Meeting ( Wayback Machineに2011年7月16日アーカイブ、追記)、Lisp Pointers, V(4)、1992年10~12月号。2012年8月9日閲覧。
- ^ Taylor Campbell (2005年7月21日). 「SRFI 62: S式コメント」. The SRFI Editors, schemers.org . 2012年8月9日閲覧。
- ^ William D Clinger (1999年7月1日). 「SRFI 6: 基本的な文字列ポート」. The SRFI Editors, schemers.org . 2012年8月9日閲覧
- ^ Scott G. Miller (2002-06-25). 「SRFI 28: 基本フォーマット文字列」. SRFI Editors, schemers.org . 2012-08-09閲覧.
- ^ JW Backus, FL Bauer, J. Green, C. Katz, J. McCarthy, P. Naur; et al. (1960年1月~4月). 「アルゴリズム言語 Algol 60 の改訂報告書」. Numerische Mathematik, Communications of the ACM, and Journal of the British Computer Society . 2012-08-09閲覧
- ^ ジョナサン・リース、ウィリアム・クリンガー編(1986年12月)。「アルゴリズム言語スキームに関する改訂版報告書(ALGOL 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. 2012年8月9日閲覧
- ^ 「SRFIをサポートするSchemeシステム」。SRFIエディター、schemers.org。2009年8月30日。2021年6月20日にオリジナルからアーカイブ。 2012年8月9日閲覧。
- ^ 「scheme-faq-standards」には、Schemeの既知の実装75個がリストされています。Community Scheme Wiki。2009年6月25日。2009年10月20日閲覧
- ^ Ed Martin (2009年7月20日). 「Scheme利用校一覧」 Schemers Inc. 2009年3月30日時点のオリジナルよりアーカイブ。2009年10月20日閲覧。
- ^ 「SICPを使用している学校のリスト」。MITプレス。1999年1月26日。2008年6月15日にオリジナルからアーカイブ。 2009年10月20日閲覧。
- ^ Eric Grimson(2005年春)「6.001 コンピュータプログラムの構造と解釈」。MITオープンコースウェア。2009年10月20日閲覧。
- ^ Alex Vandiver、Nelson Elhage、他(2009年1月)「6.184 - ゾンビはカフェイン入りの6.001を飲む」。MIT CSAIL。2009年8月28日にオリジナルからアーカイブ。 2009年10月20日閲覧
- ^ ジョン・デネロ(2019年秋). 「コンピュータサイエンス61A、バークレー」. バークレー大学電気工学・コンピュータサイエンス学部. 2020年11月11日時点のオリジナルからのアーカイブ。 2019年12月17日閲覧。
- ^ CS 1101:プログラム設計入門(A05):コースソフトウェア、ウースター工科大学
- ^ 「CSSE 304:プログラミング言語の概念」.ローズハルマン工科大学.
- ^ 「2021年春 CS121b シラバス」(PDF) .ブランダイス大学.
- ^ 「ホーム」. berkeley-cs61as.github.io
- ^ Dana Angluin (2009年秋). 「コンピュータサイエンス入門 (CPSC 201)」. The Zoo, イェール大学コンピュータサイエンス学部. 2009年10月20日閲覧.
- ^ Structure of Computer Programming I 2010年6月19日アーカイブ、ミネソタ大学コンピュータサイエンス学部、2010年春 (2010年1月30日アクセス).
- ^ CSci 必修科目のコース説明とその他の情報 2019年10月25日アーカイブ、ミネソタ大学コンピュータサイエンス学部 (2019年10月25日アクセス) .
- ^ CSCI 2041—新コース CSE カリキュラム委員会、ミネソタ大学 (2019年10月25日アクセス).
- ^ Robin Cover (2002-02-25). 「DSSSL - 文書スタイルセマンティクスおよび仕様言語。ISO/IEC 10179:1996」。表紙。2012-08-09閲覧。
- ^ 「現在GIMPに付属している主要なスクリプト言語はSchemeです。」Dov Grobgeld (2002). 「GIMP基本Schemeチュートリアル」。GIMPチーム。2012-08-09閲覧
- ^ Todd Graham Lewis、David Zoll、Julian Missig (2002). 「GNOME FAQ from Internet Archive」. The Gnome Team, gnome.org. 2000年5月22日時点のオリジナルよりアーカイブ。2012年8月9日閲覧。
- ^ "guile-gnome". フリーソフトウェア財団. 2012年8月9日閲覧.
- ^ Laurence Brevard (2006年11月9日). 「Synopsys MAP-inSM プログラムアップデート:EDA相互運用性開発者フォーラム」(PDF) . Synopsis Inc. 2012年8月9日閲覧.
- ^ Kawai, Shiro (2002年10月). 「Gluing Things Together - リアルタイムCGコンテンツ制作におけるScheme」.第1回国際LISP会議議事録、サンフランシスコ: 342–348 . 2012年8月9日閲覧
- ビル ・マグナソン、ハル・エイベルソン、マーク・フリードマン (2009年8月11日). 「Android向けApp Inventorの裏側」。Google Inc.、公式Google Researchブログ。 2012年8月9日閲覧。
さらに読む
- Schemeとその実装入門(ミラー)
- クリストファー・T・ヘインズ (1999年6月22日). 「Schemeプログラミング言語標準化の経験」。
- ガイ・L・スティール・ジュニア、リチャード・P・ガブリエル. 「Lispの進化」(PDF) . オリジナル(PDF)から2016年6月11日にアーカイブ
- ジェラルド・ジェイ・サスマン&ガイ・ルイス・スティール・ジュニア(1975年12月)。Scheme 。第AIメモ349巻。MIT人工知能研究所。CiteSeerX 10.1.1.128.80 – Wikisource経由。