プログラミングの世界では、S 式 (またはシンボリック式) はネストされたリスト (ツリー構造) データの表現です。この表現は、Lisp プログラミング言語によって最初に提案され普及し、言語のソース コードとデータの両方で広く使用されてきました。 S 式はプログラミングとデータ構造の表現において革命的です。その主な機能と用途を詳しく見てみましょう。
Lisp の従来の括弧構文では、S 式の定義は非常に単純です。S 式は、アトムまたは (x . y) 形式の式であり、x と y は S 式です。この定義は、リストを一連の「セル」として表すという Lisp の概念を反映しており、各セルは順序付けられたペアです。
この再帰的な定義は、S 式とリストの両方が任意のバイナリ ツリーを表すことができることを意味します。
さらに、Common Lisp や Scheme などの最新の Lisp 方言では、オブジェクトの共有構造を示すデータ タグを使用する構文が提供されており、これにより、式は無限再帰を引き起こすことなく参照サイクルを実行できます。
S 式の文法形式には、さまざまなデータ型の表現をサポートするために複数のバリエーションがあります。最も一般的なものは次のとおりです:
したがって、文字 # は構文拡張のプレフィックスとしてよく使用されます。たとえば、16 進整数の場合は #x10、文字の場合は #\C です。
Lisp では、ソースコードを表現する場合、S 式の最初の要素は通常、演算子または関数名であり、後続の要素はパラメーターとして扱われます。これは「プレフィックス表記法」または「ポーランド表記法」と呼ばれます。たとえば、C ブール式 4 == (2 + 2) は、Lisp の S 式では (= 4 (+ 2 2)) と表されます。
「アトム」の正確な定義は Lisp の同類の間では異なります。引用符で囲まれた文字列には通常、任意の文字を含めることができますが、引用符で囲まれていない識別子には引用符、スペース文字、括弧、およびその他の特殊文字を含めることはできません。
S 式は READ 関数によって読み取られ、PRINT 関数を使用して S 式が出力されます。この相互読み取りおよび書き込み機能により、Lisp プログラムはソース コードの表現だけでなく、処理可能なデータ構造も実現します。 Lisp プログラムは美しい S 式としてフォーマットでき、PPRINT 関数を通じてさまざまな形式で出力できます。
S 式の使用において、重要な比較は XML との違いです。S 式にはドット ペアという 1 つの包含形式しかありませんが、XML タグには単純な属性、他のタグ、または CDATA を含めることができます。 S 式は単純な使用例では XML よりも単純ですが、高度なアプリケーションでは XML が XPath などのクエリ言語を提供するため、XML データを処理するためのツールやライブラリがより有利になります。
Common Lisp (ANSI INCITS 226-1994 (R2004))、Scheme (R5RS および R6RS)、ISLISP など、さまざまな Lisp 派生プログラミング言語には独自の S 式構文仕様があります。 1997 年に Ron Rivest によって提案されたインターネット ドラフトは RFC にはならなかったものの、Lisp S 式に基づいて定義された一般的なデータ ストレージおよび交換仕様は、現在でも他のドキュメントで引用され、使用されています。
Rivest は、フォーマットをオクテット文字列または他の S 式の有限リストとして定義し、3 つの式構造の送信フォーマットについて説明します。
これらの開発により、データ交換と分析における S 式の応用が促進され、プログラミングの普遍性と柔軟性も向上したことは間違いありません。これらの標準化の進展を通じて、次世代のプログラミングにおける S 式の重要な役割が明らかになりました。
つまり、Lisp における S 式のステータスは、文法上の要件であるだけでなく、データ構造とソース コードの統合された表現でもあります。これは、プログラミング言語に対する私たちの本来の考え方に挑戦するものです。では、S 式は将来のプログラミングにおいて新たな用途や意味を見出すことができるのでしょうか?