Common Lispの利点

Lispは倚くの堎合、他の蚀語よりも有利な蚀語ずしお宣䌝されおいたす。これは、独自の、統合された、䟿利な機胜を備えおいるためです。

以䞋は、暙準Common Lispの䞀連の機胜を簡単に、そしお䟋を挙げお匷調する詊みです。

この蚘事は、プログラミングの経隓があり、Lispに興味があり、Lispが魅力的である理由をよりよく理解したい人に最も圹立぀ず思われたす。

テキストは、CL機胜リストずRobert StrandhのCLレビュヌに基づいおいたす。

豊富で正確な挔算


Lispは、他の蚀語ずうたく統合された豊富な数倀型の階局を提䟛したす。

長い数倀 bignumは必芁に応じお自動的に䜜成されるため、オヌバヌフロヌのリスクが軜枛され、粟床が確保されたす。 たずえば、倀10↑↑4をすばやく蚈算できたす。

> (expt (expt (expt (expt 10 10) 10) 10) 10) 100000000000000000000000000000000000[...] 

有理数は分数ずしお衚されるため、䜿甚時に䞞め誀差は発生したせん。 正確な合理的な算術が蚀語に統合されおいたす

 > (+ 5/9 3/4) 47/36 

耇玠数は、Lispの組み蟌みデヌタ型でもありたす。 それらは短い構文ずしお衚すこずができたす#c10 5は10 + 5iを意味したす。 算術挔算は、耇雑な倀でも機胜したす。

 > (* 2 (+ #c(10 5) 4)) #C(28 10) 


䞀般化されたリンク


圢状たたは堎所は、個別の可倉倉数であるかのように䜿甚できたす。 SETFおよび他の同様の構造を䜿甚しお、特定の䜍眮に抂念的に関連付けられおいる倀を倉曎できたす。

たずえば、次のようにSETFを䜿甚できたす。

 > (defvar *colours* (list 'red 'green 'blue)) *COLOURS* > (setf (first *colours*) 'yellow) YELLOW > *colours* (YELLOW BLUE GREEN) 

PUSHは次のようになりたす。

 > (push 'red (rest *colours*)) (RED BLUE GREEN) > *colours* (YELLOW RED BLUE GREEN) 

汎甚リンクは、リストに適甚されるずきだけでなく、他の倚くの皮類の構造やオブゞェクトにも適甚されたす。 たずえば、オブゞェクト指向プログラムでは、オブゞェクトの䞀郚のフィヌルドを倉曎する方法の1぀はSETFを䜿甚するこずです。

耇数の倀


リストなどの構造を明瀺的に䜜成しなくおも、倀を組み合わせるこずができたす。 たずえば、values 'foo' barは、2぀の倀-'foo and' barを返したす。 このメカニズムを䜿甚するず、関数は䞀床に耇数の倀を返すこずができ、プログラムを簡玠化できたす。

たずえば、FLOORは2぀の倀を返す暙準関数です。

 > (floor pi) 3 0.14159265358979312d0 

慣䟋により、耇数の倀を返す関数は、デフォルトでは1぀の倀のみが返されるかのように䜿甚されたす-最初の倀。
 > (+ (floor pi) 2) 5 

この堎合、残りの倀を明瀺的に取埗および䜿甚できたす。 次の䟋では、䞞め時にPIの敎数郚分ず小数郚分を分離したす。

 > (multiple-value-bind (integral fractional) (floor pi) (+ integral fractional)) 3.141592653589793d0 


マクロ


Lispのマクロは、Lispフォヌムたたはオブゞェクトを匕数ずしお取り、原則ずしおコヌドを生成し、コンパむルしお実行する䞀皮の関数です。 これは、マクロ展開ず呌ばれる段階で、プログラムが実行される前に発生したす。 マクロは、開発䞭に蚀語のすべおの機胜を䜿甚しお、ある皮の蚈算を実行できたす。

マクロの䜿甚法の1぀は、䞀郚の゜ヌスコヌドを、既存の定矩に関しお正しいビュヌに倉換するこずです。 ぀たり、マクロを䜿甚するず、蚀語に新しい構文を远加できたすこのアプロヌチは構文抜象化ず呌ばれたす。

これにより、プログラムを実行する前に特別な構文を蚀語に远加できるため、Lispにドメむン固有蚀語DSLを簡単に埋め蟌むこずができたす。

マクロを䜿甚する䞻な利点は、マクロが蚀語の機胜を拡匵し、プログラマヌがより簡単に、より少ないコヌドでアむデアを衚珟できるこずです。 新しいツヌルを組み蟌みのように蚀語に远加できたす。 さらに、マクロを䜿甚しおデヌタの事前蚈算たたは初期化を行うず、パフォヌマンスの最適化に圹立ちたす。

マクロルヌプ


LOOPマクロは、ルヌプを衚すための匷力なツヌルです。 実際、これは反埩プロセスを蚘述するためのたったく小さな組み蟌み蚀語です。 LOOPは、単玔な繰り返しから反埩子や耇雑な状態マシンたで、ルヌプを蚘述するために必芁なすべおのタむプの匏を提䟛したす。

 > (defvar *list* (loop :for x := (random 1000) :repeat 5 :collect x)) *LIST* > *list* (324 794 102 579 55) 

 > (loop :for elt :in *list* :when (oddp elt) :maximizing elt) 579 

 > (loop :for elt :in *list* :collect (log elt) :into logs :finally (return (loop :for l :in logs :if (> l 5.0) :collect l :into ms :else :collect l :into ns :finally (return (values ms ns))))) (5.7807436 6.6770835 6.3613024) (4.624973 4.0073333) 


FORMAT関数


FORMAT関数は、デヌタのフォヌマット方法を蚘述する埋め蟌み蚀語をサポヌトしたす。 単玔なテキストの眮換に加えお、FORMAT呜什は、条件、ルヌプ、境界ケヌスの凊理など、テキストを生成するためのさたざたなルヌルをコンパクトな圢匏で衚珟できたす。

この関数を䜿甚しお名前のリストをフォヌマットできたす。

 (defun format-names (list) (format nil "~{~:(~a~)~#[.~; and ~:;, ~]~}" list)) 

 > (format-names '(doc grumpy happy sleepy bashful sneezy dopey)) "Doc, Grumpy, Happy, Sleepy, Bashful, Sneezy and Dopey." > (format-names '(fry laurie)) "Fry and Laurie." > (format-names '(bluebeard)) "Bluebeard." 

FORMATは、画面ぞの暙準出力、文字列、たたはその他のストリヌムにかかわらず、結果を指定されたストリヌムに転送したす。

高階関数


Lispの関数は本圓のファヌストクラスの゚ンティティです。 機胜オブゞェクトは、動的に䜜成するか、パラメヌタヌずしお枡すか、結果ずしお返すこずができたす。 したがっお、 高階関数、぀たり匕数ず戻り倀自䜓が関数になり埗る関数がサポヌトされおいたす。

ここでは、匕数がリストず別の関数この堎合は '<であるSORT関数の呌び出しを確認できたす。

 > (sort (list 4 2 3 1) #'<) (1 2 3 4) 

枡される関数の名前の代わりに、ラムダ匏ずも呌ばれる匿名関数を䜿甚できたす。 これらは、䞍芁な名前でプログラムを詰たらせるこずなく、1回限りの䜿甚のための関数を䜜成する堎合に特に圹立ちたす。 䞀般に、それらは字句クロヌゞャを䜜成するために䜿甚できたす。

この䟋では、MAPCARの最初の匕数ずしお䜿甚する匿名関数を䜜成したす。

 > (mapcar (lambda (x) (+ x 10)) '(1 2 3 4 5)) (11 12 13 14 15) 

関数を䜜成するずき、コンテキストをキャプチャするため、完党な語圙的クロヌゞャヌを䜿甚できたす。

 (let ((counter 10)) (defun add-counter (x) (prog1 (+ counter x) (incf counter)))) 

 > (mapcar #'add-counter '(1 1 1 1)) (11 12 13 14) > (add-counter 50) 64 


リスト凊理


リストはLispの基本的な組み蟌みデヌタ型であるため、リストを操䜜するための広範な機胜セットがありたす。 このような関数ずマクロのおかげで、リストを䜿甚しお他のデヌタ構造のプロトタむプをすばやく䜜成できたす。

たずえば、通垞のリストを䜿甚しお次のように䜜業できたす。

 > (defvar *nums* (list 0 1 2 3 4 5 6 7 8 9 10 11 12)) *NUMS* > (list (fourth *nums*) (nth 8 *nums*)) (3 8) > (list (last *nums*) (butlast *nums*)) ((12) (0 1 2 3 4 5 6 7 8 9 10 11)) > (remove-if-not #'evenp *nums*) (0 2 4 6 8 10 12) 

そしお-連想リストを䜿甚しお

 > (defvar *capital-cities* '((NZ . Wellington) (AU . Canberra) (CA . Ottawa))) *CAPITAL-CITIES* > (cdr (assoc 'CA *capital-cities*)) OTTAWA > (mapcar #'car *capital-cities*) (NZ AU CA) 


ラムダリスト


ラムダリストは、関数、マクロ、バむンディングフォヌム、およびその他の構造のパラメヌタヌを定矩したす。 Lambdaリストは、必須、オプション、名前付き、テヌル残りおよびオプションのパラメヌタヌ、およびデフォルト倀などを定矩したす。 これにより、非垞に柔軟で衚珟力豊かなむンタヌフェむスを定矩できたす。

オプションのパラメヌタヌでは、呌び出し元が倀を指定する必芁はありたせん。 それらに察しおデフォルト倀を定矩できたす。それ以倖の堎合、呌び出されたコヌドは倀が提䟛されおいるかどうかを確認し、状況に応じお動䜜できたす。

次の関数は、オプションの区切り文字パラメヌタヌを受け入れたす。デフォルト倀は空癜文字です。

 (defun explode (string &optional (delimiter #\Space)) (let ((pos (position delimiter string))) (if (null pos) (list string) (cons (subseq string 0 pos) (explode (subseq string (1+ pos)) delimiter))))) 

EXPLODE関数を呌び出すずき、オプションのパラメヌタヌを指定するか、省略するこずができたす。

 > (explode "foo, bar, baz" #\,) ("foo " " bar " " baz") 

 > (explode "foo, bar, baz") ("foo," "bar," "baz") 

名前付きパラメヌタヌはオプションのパラメヌタヌに䌌おいたすが 、名前で定矩されおいるため、任意の順序で枡すこずができたす。 名前を䜿甚するず、コヌドの可読性が向䞊し、耇数のパラメヌタヌを䜿甚しお呌び出しを行う際の䞀皮のドキュメントずしお機胜したす。

たずえば、次の2぀の関数呌び出しを比范したす。

 // In C: xf86InitValuatorAxisStruct(device, 0, 0, -1, 1, 0, 1); 

 ;; In Lisp: (xf86-init-valuator-axis-struct :dev device :ax-num 0 :min-val 0 :max-val -1 :min-res 0 :max-res 1 :resolution 1) 


ファヌストクラスの゚ンティティずしおのシンボル


シンボルは、名前で完党に定矩される䞀意のオブゞェクトです。 たずえば、「fooは名前が「FOO」のキャラクタヌです。 シンボルは、識別子たたはいく぀かの抜象的な名前ずしお䜿甚できたす。 文字の比范は、䞀定時間にわたっお行われたす。

シンボルは、関数ず同様に、䞀流の゚ンティティです。 それらは、動的に䜜成、匕甚匕甚、未評䟡、保存、匕数ずしお枡され、比范、文字列に倉換、゚クスポヌトおよびむンポヌトでき、参照できたす。

ここで、「* foo *」は倉数の識別子です。

 > (defvar *foo* 5) *FOO* > (symbol-value '*foo*) 5 


ファヌストクラス゚ンティティずしおのパッケヌゞ


名前空間の圹割を果たすパッケヌゞもファヌストクラスのオブゞェクトです。 プログラムの実行䞭に䜜成、保存、結果ずしお返されるため、コンテキストを動的に切り替えたり、名前空間を動的に倉換したりするこずができたす。

次の䟋では、INTERNを䜿甚しおパッケヌゞに文字を含めたす。

 > (intern "ARBITRARY" (make-package :foo :use '(:cl))) FOO::ARBITRARY NIL 

Lispには、珟圚のパッケヌゞを指す特別な倉数* package *がありたす。 珟圚のパッケヌゞがFOOである堎合、次を実行できたす。

 > (in-package :foo) #<PACKAGE "FOO"> > (package-name *package*) "FOO" 


特別な倉数


Lispは、字句コンテキストに加えお倉数の動的コンテキストをサポヌトしたす。 動的倉数はいく぀かの堎合に圹立぀可胜性があるため、そのサポヌトにより最倧限の柔軟性が埗られたす。

たずえば、䞀郚のコヌドの出力をファむルなどの非暙準ストリヌムにリダむレクトし、特別な倉数* standard-output *のダむナミックリンクを䜜成できたす。

 (with-open-file (file-stream #p"somefile" :direction :output) (let ((*standard-output* file-stream)) (print "This prints to the file, not stdout.")) (print "And this prints to stdout, not the file.")) 

*暙準出力*に加えお、lispには、*暙準入力*、*パッケヌゞ*、*読み取り可胜*、*印刷可胜*、*印刷円など、リ゜ヌスずパラメヌタヌを含むプログラムの状態を栌玍するいく぀かの特殊倉数が含たれたす。など

コントロヌル転送


Lispには、制埡を呌び出し階局の䞊䜍にあるポむントに移す2぀の方法がありたす。 この堎合、語圙領域たたは動的領域は、それぞれロヌカル遷移および非ロヌカル遷移に考慮するこずができたす。

名前付きブロックにより、ネストされたフォヌムは、BLOCKおよびRETURN-FROMを䜿甚しお、名前付きの芪フォヌムからコントロヌルを返すこずができたす。

たずえば、ここでネストされたルヌプは、倖偎のルヌプをバむパスしお、初期ブロックからリストを返したす。

 > (block early (loop :repeat 5 :do (loop :for x :from 1 :to 10 :collect x :into xs :finally (return-from early xs)))) (1 2 3 4 5 6 7 8 9 10) 

キャッチ/スロヌは、非ロヌカルgotoのようなものです。 THROWは、最埌に怜出されたCATCHにゞャンプし、パラメヌタヌずしお指定された倀を枡したす。

前の䟋に基づいたTHROW-RANGE関数では、プログラムの動的状態を䜿甚しお、THROWずCATCHを適甚できたす。

 (defun throw-range (ab) (loop :for x :from a :to b :collect x :into xs :finally (throw :early xs))) 

 > (catch :early (loop :repeat 5 :do (throw-range 1 10))) (1 2 3 4 5 6 7 8 9 10) 

動的な状態を考慮する必芁がある堎合に、レキシカルスコヌプを䜿甚しおキャッチ/スロヌするだけで十分な堎合。

条件の再起動


Lispの条件システムは、プログラムの郚分間で信号を送信するためのメカニズムです。

考えられる䜿甚法の1぀は、JavaたたはPythonで行うのずほが同じ方法で、䟋倖をスロヌしお凊理するこずです。 しかし、他の蚀語ずは異なり、Lispでのシグナル送信䞭にスタックは拡匵しないため 、すべおのデヌタが保存され、シグナルハンドラヌはスタック䞊の任意のポむントからプログラムを再起動できたす。

䟋倖を凊理するこのアプロヌチにより、タスクの分離が改善され、より構造化されたコヌドを実珟できたす。 しかし、そのようなメカニズムは、プログラムの各郚分間で゚ラヌだけでなく任意のメッセヌゞを送信するなど、より広い範囲を持っおいたす。

条件システムの䜿甚䟋は、蚘事Common LispA Tutorial on Conditions and Restartsで芋るこずができたす。

䞀般化された関数


Common LispオブゞェクトシステムCommon Lisp Object System、CLOSは、メ゜ッドをクラスにバむンドしたせんが、䞀般化された関数の䜿甚を蚱可したす。

汎甚関数は、いく぀かの異なるメ゜ッドが満たすこずができる眲名を定矩したす。 呌び出されるず、匕数に最も䞀臎するメ゜ッドが遞択されたす。

ここで、キヌボヌドからのむベントを凊理する䞀般化された関数を定矩したす。
 (defgeneric key-input (key-name)) 

次に、異なるKEY-NAME倀を満たすいく぀かのメ゜ッドを定矩したす。

 (defmethod key-input (key-name) ;; Default case (format nil "No keybinding for ~a" key-name)) (defmethod key-input ((key-name (eql :escape))) (format nil "Escape key pressed")) (defmethod key-input ((key-name (eql :space))) (format nil "Space key pressed")) 

アクションのメ゜ッド呌び出しを芋おみたしょう

 > (key-input :space) "Space key pressed" > (key-input :return) "No keybinding for RETURN" > (defmethod key-input ((key-name (eql :return))) (format nil "Return key pressed")) > (key-input :return) "Return key pressed" 

私たちは、コンストラクションなしで、スむッチずメ゜ッドのテヌブルを䜿甚した明瀺的な䜜業を行いたした。 したがっお、新しい特別なケヌスの凊理を、必芁に応じお独立しお、動的に、通垞はプログラムのどこにでも远加できたす。 これにより、特にボトムアップのLispプログラムの開発が保蚌されたす。

䞀般化関数は、メ゜ッドのグルヌプのいく぀かの共通の特性を定矩したす。 たずえば、メ゜ッドの組み合わせのメ゜ッド、特殊化オプション、およびその他のプロパティは、汎甚関数によっお指定できたす。

Lispは倚くの䟿利な暙準汎甚関数を提䟛したす。 たずえば、PRINT-OBJECTは、テキスト衚珟を定矩するために任意のクラスに特化できたす。

メ゜ッドの組み合わせ


メ゜ッドの組み合わせにより、メ゜ッドを呌び出すずきに、ある順序で、たたは䞀郚の関数が他の関数の結果を凊理するように、メ゜ッドのチェヌン党䜓を実行できたす。

特定の順序でメ゜ッドを配眮するメ゜ッドを結合するための組み蟌みメ゜ッドがありたす。 キヌワヌドbefore 、: after、たたはaroundで提䟛されるメ゜ッドは、呌び出しチェヌンの適切な堎所に配眮されたす。

たずえば、前の䟋では、各KEY-INPUTメ゜ッドは、「キヌが抌されたした」ずいうフレヌズの出力を繰り返したす。 次のような組み合わせでコヌドを改善できたすaround

 (defmethod key-input :around (key-name) (format nil "~:(~a~) key pressed" (call-next-method key-name))) 

その埌、KEY-INPUTメ゜ッドを再定矩しお、それぞれに1行のみを指定したす。

 (defmethod key-input ((key-name (eql :escape))) "escape") 

KEY-INPUTを呌び出すず、次のこずが起こりたす。

デフォルトのオプションは異なる方法で凊理できるこずに泚意しおください。 THROW / CATCHペアを䜿甚するだけですより高床な実装では条件を䜿甚できたす。

 (defmethod key-input (key-name) (throw :default (format nil "No keybinding for ~a" key-name))) (defmethod key-input :around (key-name) (catch :default (format nil "~:(~a~) key pressed" (call-next-method key-name)))) 

その結果、統合されたメ゜ッドの組み合わせメ゜ッドにより、キヌボヌドからのむベントの凊理をモゞュヌル化された拡匵可胜な簡単に倉曎可胜なメカニズムに䞀般化するこずができたす。 この手法は、ナヌザヌ定矩の組み合わせ方法を䜿甚しお補足できたす。 たずえば、メ゜ッドの結果を合蚈たたは゜ヌトする組み合わせメ゜ッドを远加できたす。

倚重継承


どのクラスにも倚くの祖先を含めるこずができたす。これにより、より豊富なモデルを䜜成し、より効率的なコヌドの再利甚を実珟できたす。 子クラスの動䜜は、先祖クラスの定矩に埓っお構築されたシヌケンスに埓っお決定されたす。

メ゜ッドの組み合わせ、メタオブゞェクトプロトコル、およびその他のCLOS機胜を䜿甚するず、埓来の倚重継承の問題fork-joinなどを回避できたす。

メタオブゞェクトプロトコル


メタオブゞェクトプロトコルMOPは、CLOSを䜿甚しお実装されるCLOSプログラミングむンタヌフェむスです。 MOPを䜿甚するず、プログラマはCLOS自䜓を䜿甚しお内郚CLOSデバむスを調査、䜿甚、および倉曎できたす。

ファヌストクラスの゚ンティティずしおのクラス


クラス自䜓もオブゞェクトです。 MOPを䜿甚するず、クラスの定矩ず動䜜を倉曎できたす。

FOOクラスをBARクラスの子孫ずし、ENSURE-CLASS関数を䜿甚しお、たずえばBAZクラスをFOO先祖のリストに远加できたす。

 (defclass bar () ()) (defclass foo (bar) ()) (defclass baz () ()) 

 > (class-direct-superclasses (find-class 'foo)) (#<STANDARD-CLASS BAR>) > (ensure-class 'foo :direct-superclasses '(bar baz)) #<STANDARD-CLASS FOO> > (class-direct-superclasses (find-class 'foo)) (#<STANDARD-CLASS BAR> #<STANDARD-CLASS BAZ>) 

クラスの祖先に関する情報を取埗するために、CLASS-DIRECT-SUPERCLASSES関数を䜿甚したした。 この堎合、FIND-CLASSから受け取ったオブゞェクトの圢匏のクラスを匕数ずしお受け取りたす。

䞊蚘の䟋は、プログラムの実行䞭にクラスを倉曎できるメカニズムを瀺しおいたす。これにより、ずりわけクラスにミックスむンを動的に远加できたす。

動的なオヌバヌラむド


Lispは非垞にむンタラクティブでダむナミックな環境です。 関数、マクロ、クラス、パッケヌゞ、パラメヌタヌ、オブゞェクトはほがい぀でも再定矩でき、結果は適切で予枬可胜です。

したがっお、プログラムの実行䞭にクラスを再定矩するず、倉曎はこのクラスのすべおのオブゞェクトずサブクラスにすぐに適甚されたす。 radiusプロパティずそのサブクラスTENNIS-BALLでBALLクラスを定矩できたす。

 > (defclass ball () ((%radius :initform 10 :accessor radius))) #<STANDARD-CLASS BALL> > (defclass tennis-ball (ball) ()) #<STANDARD-CLASS TENNIS-BALL> 

TENNIS-BALLクラスのオブゞェクトは次のずおりです。radiusプロパティ甚のスロットがありたす。

 > (defvar *my-ball* (make-instance 'tennis-ball)) *MY-BALL* > (radius *my-ball*) 10 

そしお、別のボリュヌムスロットを远加するこずで、BALLクラスをオヌバヌラむドできたす。

 > (defclass ball () ((%radius :initform 10 :accessor radius) (%volume :initform (* 4/3 pi 1e3) :accessor volume))) #<STANDARD-CLASS BALL> 

そしお* MY-BALL *は自動的に曎新され、先祖クラスで定矩された新しいスロットを取埗したす。

 > (volume *my-ball*) 4188.790204786391d0 


実行時のコンパむラヌぞのアクセス


COMPILEおよびCOMPILE-FILE関数のおかげで、Lispコンパむラは実行可胜プログラムから盎接䜿甚できたす。したがっお、プログラムの実行䞭に䜜成たたは倉曎された関数もコンパむルできたす。

プログラムは段階的にコンパむルできるため、開発がむンタラクティブで動的か぀高速になりたす。起動したプログラムは、埐々に倉曎、デバッグ、および成長できたす。

コンパむルマクロ


コンパむルマクロは、関数たたはマクロをコンパむルするための代替戊略を定矩したす。通垞のマクロずは異なり、コンパむルマクロは蚀語の構文を拡匵せず、コンパむル時にのみ適甚できたす。したがっお、これらは䞻にコヌド自䜓ずは別にコヌドを最適化する方法を決定するために䜿甚されたす。

型定矩


Lispは動的に型付けされた蚀語ですが、ラピッドプロトタむピングには非垞に䟿利ですが、プログラマは倉数の型を明瀺的に指定できたす。これは、他のディレクティブず同様に、コンパむラヌが蚀語が静的に型指定されおいるかのようにコヌドを最適化できるようにしたす。

たずえば、次のようにEXPLODE関数でパラメヌタタむプを定矩できたす。

 (defun explode (string &optional (delimiter #\Space)) (declare (type character delimiter) (type string string)) ...) 


プログラマブルパヌサヌ


Lispパヌサヌを䜿甚するず、入力デヌタを簡単に解析できたす。入力ストリヌムからテキストを取埗し、通垞はS匏ず呌ばれるLispオブゞェクトを䜜成したす。これにより、入力デヌタの分析が倧幅に簡玠化されたす。

パヌサヌは、READ、READ-CHAR、READ-LINE、READ-FROM-STRINGなどのいく぀かの関数を通じお䜿甚できたす。入力ストリヌムには、ファむル、キヌボヌド入力などを䜿甚できたすが、さらに、適切な関数を䜿甚しお文字列たたは文字シヌケンスからデヌタを読み取るこずができたす。

READ-FROM-STRINGを䜿甚した読み取りの最も簡単な䟋は、文字列「400 500 600」からオブゞェクト400 500 600、぀たりリストを䜜成したす。

 > (read-from-string "(400 500 600)") (400 500 600) 13 > (type-of (read-from-string "t")) BOOLEAN 

リヌダヌマクロを䜿甚するず、特定の構文に特別なセマンティクスを定矩できたす。これは、Lispパヌサヌがプログラム可胜なため可胜です。マクロの読み取りは、蚀語の構文を拡匵する別の方法ですマクロは䞀般的に構文糖を远加するために䜿甚されたす。

いく぀かの暙準的な読み取りマクロ

パヌサヌは、読み取りルヌルが定矩されおいるオブゞェクトを生成できたす。特に、これらのルヌルは読み取りマクロを䜿甚しお蚭定できたす。実際、問題のパヌサヌは察話型むンタヌプリタヌ読み取り-評䟡-印刷ルヌプ、REPLにも䜿甚されたす。

これは、暙準の読み取りマクロを䜿甚しお16進衚蚘で数倀を読み取る方法です。

 > (read-from-string "#xBB") 187 


プログラム可胜な印刷


Lispのテキスト出力システムは、構造、オブゞェクト、たたは他のデヌタを異なる圢匏で印刷する機胜を提䟛したす。

PRINT-OBJECTは、匕数ずしおオブゞェクトずストリヌムを受け取る組み蟌みの䞀般化された関数です。察応するメ゜ッドは、指定されたオブゞェクトのテキスト衚珟をストリヌムに出力したす。いずれにせよ、オブゞェクトのテキスト衚珟が必芁な堎合は、FORMAT、PRINT、REPLなどのこの関数が䜿甚されたす。

JOURNEYクラスを怜蚎しおください。

 (defclass journey () ((%from :initarg :from :accessor from) (%to :initarg :to :accessor to) (%period :initarg :period :accessor period) (%mode :initarg :mode :accessor mode))) 

クラスJOURNEYのオブゞェクトを印刷しようずするず、次のようなものが衚瀺されたす。

 > (defvar *journey* (make-instance 'journey :from "Christchurch" :to "Dunedin" :period 20 :mode "bicycle")) *JOURNEY* > (format nil "~a" *journey*) "#<JOURNEY {10044DCCA1}>" 

JOURNEYクラスのPRINT-OBJECTメ゜ッドを定矩し、それを䜿甚しおオブゞェクトの䜕らかのテキスト衚珟を蚭定できたす。

 (defmethod print-object ((j journey) (s stream)) (format s "~A to ~A (~A hours) by ~A." (from j) (to j) (period j) (mode j))) 

オブゞェクトは新しいテキストビュヌを䜿甚したす。

 > (format nil "~a" *journey*) "Christchurch to Dunedin (20 hours) by bicycle." 

Source: https://habr.com/ru/post/J143490/


All Articles