Common Lisp में The Printer की संकल्पना है, जिसमें Lisp डेटा का टेक्स्ट रूप लिखने वाले सभी फंक्शन शामिल हैं। ऐसा ही एक फंक्शन format है, जो प्रोग्रामर को डेटा को अपनी इच्छा के अनुसार फॉर्मैट करने देता है।
format की क्षमताएँ, और सामान्य रूप से Lisp Printer, एक बड़ा विषय हैं। यहाँ 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 पढ़ता है और चलाता है। सभी डायरेक्टिव ~ से शुरू होते हैं और उनके बाद एक अक्षर आता है (जैसे ~A, ~D, ~&)। अक्षर के बड़े या छोटे रूप से कोई फर्क नहीं पड़ता।
ज़्यादातर फॉर्मैट डायरेक्टिव बस 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)"
एक और काम का फॉर्मैट डायरेक्टिव ~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"
अंत में, ~~ एक सरल डायरेक्टिव है जो सीधे-सीधे एक ~ लिखता है।
नौकरी करने वाले लगभग हर व्यक्ति की तरह, Lisp Alien लैला को भी कभी-कभी रिपोर्ट बनानी पड़ती है ताकि वे दूसरों को जानकारी दे सकें। वे आपसे पूछती हैं कि क्या आप इन रिपोर्टों के लिए उनके पास मौजूद डेटा को फॉर्मेट करने में उनकी मदद कर सकते हैं।
लैला को सबसे पहले एक फंक्शन चाहिए: 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"
लैला आपको format-quarter-value फंक्शन के लिए धन्यवाद देती हैं और कहती हैं कि जो अगला फंक्शन चाहिए, उसमें यह बहुत काम आएगा।
अगली रिपोर्ट में दो तिमाहियों की तिमाही और वैल्यू दो लाइनों में छपी हुई दिखनी चाहिए।
साथ ही आउटपुट उस स्ट्रीम में जाना चाहिए जो पहले आर्गुमेंट के रूप में दी गई है।
उदाहरण के लिए: (format-two-quarters t "last" 3.14 "this" 0) स्टैंडर्ड आउटपुट पर यह दिखाएगा:
The value last quarter: 3.14
The value this quarter: 0
ध्यान दीजिए कि इसके आगे-पीछे खाली लाइनें हैं।
लैला आपको बताना भूल गईं कि Lisp Alien वैल्यू को ऐसे रूप में देखना पसंद करते हैं जिसे 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 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।