format
Common Lisp مفهومی به اسم چاپگر دارد که همهی توابع نوشتن بازنماییهای متنی دادههای Lisp را در بر میگیرد. یکی از این توابع format است که به برنامهنویس اجازه میدهد داده را به شکلی که میخواهد قالببندی کند.
تواناییهای format و چاپگر Lisp به طور کلی موضوع گستردهای است؛ اینجا مبانی استفاده از format توصیف میشود.
format
تابع format حداقل دو آرگومان میگیرد: یک جریان برای چاپ و یک رشتهی کنترلی که تعیین میکند چه چیزی و چگونه چاپ شود.
جریانها خودشان مفهومی جداگانهاند و جای دیگری توصیف میشوند. اما فعلاً فقط کافی است بدانید که چاپ روی جریان انجام میشود و برای این آرگومان دو مقدار ویژه وجود دارد: t و nil. t یعنی چاپ روی خروجی استاندارد (در واقع همان جریانی که متغیر *standard-output* به آن مقید شده است) و nil یعنی ساختن یک رشته و برگرداندن آن.
توجه کنید که format همیشه به nil ارزیابی میشود، مگر در همان حالت دوم که nil به عنوان جریان مشخص شده است. این روشی رایج برای درج یا ساختن سادهی رشته است.
(format nil "hello world") ; => "hello world"
(format t "hello world") ; => NIL (but "hello world" is printed to standard output)
format
رشتهی کنترلی میتواند شامل «دستورهای format» باشد که به format میگویند چه چیزی چاپ کند و سایر پارامترهای format را چگونه تفسیر کند. به یک معنا، رشتهی کنترلی برنامهای است که format آن را تفسیر و اجرا میکند. همهی دستورها با ~ شروع میشوند و بعد از آن یک نویسه میآید (مثلاً ~A، ~D، ~&). بزرگ یا کوچک بودن نویسه اهمیتی ندارد.
بیشتر دستورهای format صرفاً یک آرگومان format را در خروجی درج میکنند. به این کار میگویند آرگومان را «مصرف» میکند. بعضی دستورها آرگومان مصرف نمیکنند، یا بیشتر از یکی مصرف میکنند. حتی یک دستور به شما اجازه میدهد در فهرست آرگومانها جابهجا شوید یا از روی آرگومانها بپرید.
یک دستور format بسیار همهکاره ~A است. این دستور نسخهای «خوانا برای انسان» از داده را چاپ میکند.
(format nil "Value = ~a" 10) ; => "10"
(format nil "hello ~a" "world") ; => "hello world"
(format nil "The list is: ~A" (list 1 2 3)) ; => "The list is: (1 2 3)"
دستور format مفید دیگر ~S است. این دستور نسخهای «خوانا برای ماشین» از داده را چاپ میکند. اگر بخواهید بتوانید خروجی تولیدشده را به عنوان دادهی Lisp تفسیر کنید، این میتواند بسیار مفید باشد. برای بسیاری از موارد، خروجی آن مثل ~A به نظر میرسد، اما توجه کنید که مثلاً برای رشتهها، خروجی شامل علامتهای نقلقول میشود (که هنگام قرار گرفتن در رشتهی دیگری اسکیپ میشود) تا بتوان مقدار را دوباره به عنوان پارامتر رشتهای خواند.
(format nil "~s" 10) ; => "10"
(format nil "~s" "hello world") ; => "\"hello world\""
(format nil "~s" (list 1 2 3)) ; => "(1 2 3)"
دو دستور بسیار مفید دیگر ~% و ~& هستند. اولی یک نویسهی خط جدید تولید میکند و دومی یک «خط تازه». تفاوت این است که ~% همیشه یک خط جدید تولید میکند، در حالی که ~& تنها وقتی آن را تولید میکند که در ابتدای خط نباشیم. هیچکدام از اینها آرگومان مصرف نمیکنند.
(format nil "~%new~%lines") ; => "
new
lines"
(format nil "~&new~&lines" ; => "new
lines"
در پایان، ~~ دستور سادهای است که یک ~ عینی چاپ میکند.
مثل تقریباً هر کسی که شغلی دارد، Layla، فضایی Lisp، گاهی لازم دارد گزارشهایی تهیه کند تا دیگران را از اطلاعاتی باخبر کند. او از شما میپرسد که آیا میتوانید به او کمک کنید تا دادههایی را که برای این گزارشها در اختیار دارد قالببندی کند.
Layla اول از همه به یک تابع نیاز دارد: format-quarter-value که دو پارامتر میگیرد، یعنی فصل تقویمی و مقدار، و آنها را برای گزارش قالببندی میکند. باید به یک رشته ارزیابی شود.
(format-quarter-value "last" 3.14) ; => "The value last quarter: 3.14"
(format-quarter-value "this" 0) ; => "The value this quarter: 0"
Layla برای تابع format-quarter-value از شما تشکر میکند و میگوید که در تابع بعدی که لازم است، بسیار به کار خواهد آمد.
گزارش بعدی باید فصل و مقدار را برای ۲ فصل، روی دو خط نشان دهد.
همچنین خروجی باید به جریانی برود که به عنوان آرگومان اول داده شده است.
برای مثال، (format-two-quarters t "last" 3.14 "this" 0) نتیجهی زیر را روی خروجی استاندارد تولید میکند:
The value last quarter: 3.14
The value this quarter: 0
به خطوط خالی اطراف آن دقت کنید.
Layla فراموش کرد به شما بگوید که فضاییهای Lisp دوست دارند مقادیر را به شکلی ببینند که به عنوان دادهی Lisp خوانا باشد. بنابراین به یک تابع جدید نیاز دارند که خروجی آن به عنوان دادهی Lisp قابل خواندن باشد (و باز هم به جریان مشخصشده فرستاده شود):
(format-two-quarters-for-reading nil "last" 3.14 "this" 0) ; =>
"(\"The value last quarter: 3.14\" \"The value this quarter: 0\")"
در Exercism ثبتنام کنید تا Common Lisp را همراه با 27 مفهوم92 تمرین و مربیگری انسانی واقعی یاد بگیرید و در آن استاد شوید، همهی اینها رایگان.