Schemeは、Lispプログラミング言語のミニマリスト方言であり、機能的プログラミングスタイルを促進し、シンプルでクリーンな構文を提供するように設計されています。括弧の使用、強力なマクロシステム、再帰と第一級手続きへの強い強調が特徴です。この言語は機能的プログラミングのパラダイムを奨励し、機能的、命令的、論理プログラミングを含む複数のプログラミング技法をサポートしています。
Schemeは1970年代にマサチューセッツ工科大学(MIT)のジェラルド・ジェイ・サスマンとガイ・L・スティール・ジュニアによって創造されました。これは、時間の経過とともに複雑化した元のLisp言語を簡素化し改善する試みとして開発されました。Schemeの背後にある動機は、実装と教育が容易でありながら、複雑なアイデアを表現するのに十分な力を持つ言語を作成することでした。
年月が経つにつれて、Schemeはさまざまな改訂と標準化の努力を経てきました。これらの標準の中で最も注目すべきは、言語とその機能を正式に定義したRnRS(Revisedn Reports on the Algorithmic Language Scheme)です。Schemeコミュニティはその後も言語の開発を続け、新しい機能と改善を導入したR6RSやR7RSなどの新しい標準が生まれました。
現在、Schemeはその優雅さとクリーンな構文により、特にコンピュータサイエンス教育において学術環境で人気があります。その影響は多くの現代プログラミング言語やパラダイムに見られます。Schemeはしばしば機能的プログラミングコミュニティと関連付けられ、ClojureやRacketなどの言語にインスピレーションを与え、これらの言語はSchemeの原則を基にし、その能力を拡張しています。
Schemeは完全に括弧を用いた構文を使用し、コードは前置記法で書かれます。例えば、加算操作は(+ 1 2)
と書かれます。
Schemeの関数は第一級市民であり、引数として渡したり、他の関数から返したりすることができます。例:
(define (make-adder x)
(lambda (y) (+ x y)))
(define add5 (make-adder 5))
(add5 10) ; 15を返す
Schemeは尾呼び最適化をサポートしており、尾位置で発生する再帰呼び出しに対して現在のスタックフレームを再利用できるため、スタックオーバーフローを防ぎます。
Schemeは継続を使用することを許可し、プログラマーが計算の現在の状態をキャプチャし、制御フローを操作できるようにします:
(call-with-current-continuation
(lambda (exit)
(exit 'done)))
Schemeには強力なマクロシステムがあり、プログラマーが構文拡張を作成することを可能にします。シンプルなマクロは次のように定義できます:
(define-syntax my-if
(syntax-rules ()
((_ test then else)
(if test then else))))
Schemeはリスト、ペア、高階関数などの構造を通じてデータ抽象をサポートし、データの効率的な操作を可能にします。
Schemeはレキシカルスコープを採用しており、変数のスコープはソースコード内の物理的な位置によって決まります。これにより、変数バインディングに関する予測可能な動作が得られます。
Schemeは動的型付けであり、変数は明示的な型宣言なしに任意の型の値を保持できます。
Lisp方言として、Schemeはリスト処理に最適化されており、リストに対する操作が容易です:
(define my-list (list 1 2 3 4))
(car my-list) ; 1を返す
(cdr my-list) ; (2 3 4)を返す
Schemeの関数は、メモリ使用量とパフォーマンスを最適化するために尾位置で再帰的に定義できます。例えば:
(define (factorial n)
(define (fact-helper n acc)
(if (zero? n)
acc
(fact-helper (- n 1) (* n acc))))
(fact-helper n 1))
Schemeアプリケーションは、一般的に選択した実装のランタイム環境を使用して構築できます。例えば、Racketでは、コマンドラインツールracket
を使用して.rkt
ファイルを実行したり、実行可能ファイルにコンパイルしたりできます。
Scheme用のいくつかのコンパイラとインタプリタが利用可能です:
Schemeは、プログラミング原則の教育やコンピュータサイエンスの研究ツールとして、学術界で広く使用されています。人工知能、言語設計、スクリプティング、シンボリック計算や複雑なデータ操作を必要とするさまざまな分野でも応用されています。
両言語は機能的プログラミングスタイルをサポートしていますが、Pythonは可読性とシンプルさを強調し、Schemeは強力で簡潔な表現に焦点を当てています。Schemeの括弧が多い構文は初心者にとって障壁と見なされることがありますが、Pythonのインデントベースの構文は一般的によりアクセスしやすいです。
JavaScriptも機能的プログラミングをサポートし、第一級関数を持っています。しかし、JavaScriptはプロトタイプベースのオブジェクトシステムを持ち、Schemeは機能的パラダイムに依存しています。SchemeのマクロシステムはJavaScriptにはない機能を提供します。
Cはシステムプログラミングのために設計された低水準の静的型付け言語であり、Schemeは高水準で動的型付けです。Cはパフォーマンスとハードウェアレベルの操作に焦点を当てているのに対し、Schemeは抽象化と計算の理論的側面を強調しています。
両言語は機能的プログラミングに根ざしています。Haskellはより厳格な型システムを使用し、遅延評価をサポートしていますが、Schemeの動的型付けと即時評価は、いくつかのパフォーマンスのコストを伴いながら、より柔軟なプログラミングを可能にします。
Rubyは機能的プログラミングの特徴を混ぜたオブジェクト指向プログラミング言語であり、Schemeは純粋に機能的です。Rubyの構文はより冗長であり、Schemeのシンプルさはそのミニマリスト設計から来ています。
Schemeコードを他の言語に翻訳する際には、Scheme構文とターゲット言語の両方を理解するツールが役立ちます。いくつかの便利なソースからソースへのコード翻訳ツールには以下が含まれます:
Chicken Schemeは、SchemeコードをCに翻訳するコンパイラを提供し、Cライブラリを活用し、効率的な実行可能ファイルを作成することを可能にします。
Schemeの派生であるRacketは、コードをJavaScriptに変換およびコンパイルするための組み込み機能を持ち、Webアプリケーションの展開を容易にします。
Gambit Schemeは、SchemeコードをCおよびネイティブ実行可能ファイルにコンパイルでき、パフォーマンスクリティカルなアプリケーションのための効率的な翻訳オプションを提供します。