Lisp。 最初の原子

こんにちは、Habr!

LISPには長い間興味がありましたが、残念ながら、実際に自分の知識や願望を積極的に活用する機会はありませんでした。 すぐに新しい学年度、つまり私は再び勉強する機会があり、2年目はLISPの生徒に教えることができます。 従来の複雑なことに関心がなかったことに加えて、別の問題は文学の欠如のようです。 とにかく、インターネット、特にRuNetでのLISPのトピックはあまり注目されていません。 ここおよびHabréには、十分な出版物がありません。



この記事が一般の人々にアピールし、最も興味深く、最も理解し難いプログラミング言語(LISP)についてのシリーズを開くことを願っています。 結局のところ、それは些細なことではないので、別の言語は別の人生です



LISP、アトム、リストの基本概念から始めましょう。 少し後で、興味深い場合は、前編の「アトムゼロ」で、LISPの哲学と原因、およびその使用の最新の方向性についてさらに詳しく話すことができます。



簡単な歴史



LISPは、非数値問題を解決するために1958年にジョンマッカーシーによって発明され、リスト構造の代数、ラムダ計算、再帰関数の理論の3つの主要な柱に基づいていました。 長い間、LISPは人工知能の専門家の狭いサークルによってのみ使用されていました。 しかし、前世紀の80年代から始まって、LISPは勢いを増し始め、現在ではAutoCadやEmacsなどで積極的に使用されています。



LISPと従来のプログラミング言語の違いは何ですか? 主な機能を検討してください。



データ型





従来、LISPは記号と数字の2種類の原子を考慮しています。 シンボルは、数字、線、複雑な構造、関数、およびその他のオブジェクトを表すことができます。 文字名の制限は、使用される方言に依存しますが、それらのほとんどは、名前で使用される文字に実質的に制限を課しません。 また、ほとんどの方言で、文字名は大文字と小文字が区別されません。

一部の文字には特別な目的があります-これらは定数、組み込み関数、T(true、true)およびNIL(false、false)です。



数値は、シンボルとは異なり、他のオブジェクトを表すことができないため、数値は常に定数です。 少し後、LISPで数値のタイプを検討します。

シンボルと数字は、最も単純なLISPオブジェクトである原子です。 2番目の主要なデータ型はポイントペアであり、構文的に次のように表現されます。



< > ::= (< | >.< | >)







たとえば、ポイントペアは式です。



(ab), (a.(bc)), ((ab).(c.NIL)).







原子と点のペアは、一般名S式(S式、シンボリック式)で結合されます。 特別な種類のS式は、次のように表されるリストです。



<> ::= NIL | (<S->.<>)







ほとんどの場合、NILは空のリストとして定義されます。その場合、リスト定義は次のように書き換えることができます。



<> ::= < > | (<>.<>)

< > :: = NIL

<> ::= <S->

<> ::= <>.









翼、脚...メインテール





ヘッドとテールの両方が、LISPリストコンテキストの重要な概念です。 リストの最初の要素はリストの先頭と呼ばれ、他のすべての要素は末尾と呼ばれます。 頭と尾を操作するために、以下で少し説明する一連の基本的な機能があります。

空のリストは、空の括弧のペアと同等です。

NIL <->()。

S式の記述規則に従って、要素a1、a2、a3 ...で構成される空でないリストは、次のように記述できます。



(a1.(a2.(a3…))) <-> (a1,a2,a3…)







LISPでは、ブラケットで囲まれ、スペースで区切られた一連の要素を使用してリストを作成することもできます。 概して、リストは、開き括弧と閉じ括弧のシーケンスがアーカイブされるマルチレベルのデータ構造です。

リスト項目は、空のリストを含むアトムとリストにすることができます。 たとえば、()は空のリストであり、(NIL)は1つのNIL要素で構成されるリストです(これは(())と同等です)。

S式の通常の構文はリスト構文と同等に使用できることを理解してください。たとえば、次の式は同等です。



(a.(b.nil)), (a b.nil), (ab nil), (ab)







興味がある人は、メモリ内のリストの内部表現について話すことができます。 これは、関心と量の両面で完全に独立したトピックです。



主な機能と述語





LISPには、フル機能のリスト処理を提供するプリミティブ関数のかなり小さなセットがあります。 リスト構造のコンテキストでは、これらの関数は基本的な算術演算に類似しており、完全にすべての記号計算が削減される特定のルールシステムを形成します。



従来、基本的な機能には、QUOTE、CAR、CDR、CONS、ATOM、EQが含まれます。



QUOTE関数



最初に、式の評価をブロックするように設計されたQUOTE関数を検討します。 この関数の操作を示す最も簡単な方法は、簡単な例を使用することです。



(+ 5 10) -> 15 ; 5+10

(quote (+ 5 10)) -> (+5 10) ;









QUOTE関数は短く書くこともできます:



'(+ 5 10) -> (+ 5 10) ; ' – quote









CAR機能



ポイントペアの最初の要素(またはリストの先頭)を取得するように設計されています。 この関数はリストコンテキストでのみ使用できます。アトムに使用するとエラーになります。



car(リスト)-> S-expression。



いくつかの例:



(car '(abc)) -> a

(car '(a)) -> a

(car 'a) -> ERROR: a is not a list

(car '(nil)) -> nil

(car nil) -> nil

(car '(nil a)) -> nil








便宜上、空のリストの先頭はNILです。



機能CDR



ポイントペアの2番目の要素(またはリストの末尾)を取得するように設計されています。 この関数はリストコンテキストでのみ使用できます。アトムに使用するとエラーになります。



cdr(リスト)->リスト



リストの末尾は、最初の要素を除いたリスト全体です。 リストが1つの要素で構成されている場合、末尾はNILになります。 便宜上、nilは空のリストの末尾とも見なされます。

いくつかの例:



(cdr '(abc)) -> (bc)

(cdr '(a)) -> nil

(cdr 'a) -> ERROR: a is not a list

(cdr '(a (bc))) -> ((bc))

(cdr '(nil a)) -> (a)

(cdr ()) -> nil








CARおよびCDR機能はすべてのLISP方言で実装されていますが、それらの同義語がいくつか作成されています:FIRSTおよびREST、HEADおよびTAIL)。



CONS関数



引数として渡されたヘッドとテールの新しいリストを作成するように設計されています:

cons(s式、リスト)->リスト



例:



(cons 'a '(bc)) -> (abc)

(cons 'a nil) -> (a)

(cons nil '(bc)) ->(nil bc)

(cons nil nil) ->(nil)

(cons '(ab) '(c)) ->((ab) c)








実際、CONS関数はCARおよびCDR関数の対極です。



(cons (car '(abc)) (cdr '(abc))) -> (abc)







ATOM関数



ATOMとEQは述語です-つまり 引数が特定のプロパティに一致するかどうかをチェックし、チェックの成功に応じてTまたはNILを返す関数。



ATOM述語は、引数として渡されたオブジェクトがアトムかどうかをチェックします。



アトム(S式)



例:



(atom 'a) -> t

(atom '(abc)) -> nil

(atom ()) -> t ;.. nil,









EQ機能



2つの文字の同一性を検証する述語。



eq(原子、原子)



例:



(eq 'a 'b) -> nil

(eq 'a 'a) -> t

(eq 'a (car '(ab)) -> t

(eq () nil) -> t









述語EQはアトミック引数にのみ適用され、リストには使用できないことに注意してください。 また、数値を比較するときにEQを使用しないでください。



EQよりも一般的なのはEQL述語です。これにより、同じタイプの数値を比較できます。



(eq 1.0 1.0) -> nil

(eql 1.0 1.0) -> t









数値のさらに一般的な述語は=です 。これにより、さまざまなタイプの数値の値を比較できます。



(eql 1 1.0) -> nil

(= 1 1.0) -> t









リストのより一般的なものはEQUAL述語で、2つのリストの同一性を比較できます。



(equal 'a 'a) -> t

(equal '(ab) '(ab)) -> t









最も一般的な述語はEQUALPで 、これにより任意のオブジェクトを比較できます。



ヌル関数



NULLは、引数として渡されたオブジェクトが空のリストであるかどうかをチェックします。



例:



(null '()) -> t

(null '(abc)) -> nil

(null nil) -> t

(null t) -> nil









最後の2つの例から判断すると、NULL関数は論理否定としても使用できると結論付けることができます。 同じ目的で、LISPには述語NOTが存在します。



次は?



興味を持っていただければ幸いです。 次回は、既存のLISP方言(最初は大学のXLispで十分ですが)、あまり使用されないコア関数、CARとCDRをCAAAADDAARなどに折り畳み、独自の関数を定義することについて話します。 後で-再帰、制御構造、スコープ、入出力。 後で-疲れないなら-機能、マクロ、キャラクターのプロパティ、クロージャーについて。 そしてもちろん、一般大衆が尋ねることについて。

じゃあね!



PS批判するが、あまり多くはないが、初めて公開する:)




All Articles