ট্র্যাক
/
Common Lisp
Common Lisp
/
অনুশীলনী
/
মোজা আর সেক্সপ্রস সাজানো
মোজা আর সেক্সপ্রস সাজানো

মোজা আর সেক্সপ্রস সাজানো

লার্নিং অনুশীলনী

ভূমিকা

কমেন্ট

Common Lisp প্রোগ্রামারকে "কমেন্ট" লেখার সুযোগ দেয়, যা কম্পিউটার উপেক্ষা করে। একক-লাইনের কমেন্ট এক বা একাধিক সেমিকোলন (;) দিয়ে শুরু হয়, আর মাঝেমধ্যে আপনি নিচের মতো কিছু দেখতে পাবেন:

(code...) ; => value

এখানে কমেন্টটি বোঝাতে ব্যবহার করা হয়, ওই লাইনের কোড রান করার পর Common Lisp কী মান রিটার্ন করে।

লাইনের শেষে ছোট কমেন্টের জন্য একটি সেমিকোলন, কোডের একটি অংশের উপরে আরও বড় কমেন্টের জন্য দুটি, ফাংশনের মতো কিছু বর্ণনা করা লম্বা কমেন্টের জন্য তিনটি, আর সোর্স ফাইলের উপরে হেডারের মতো কমেন্টের জন্য চারটি ব্যবহার করাই প্রচলিত রীতি।

কনস

Common Lisp-এর সব অবজেক্ট হয় "অ্যাটম" (একক, অবিভাজ্য মান), নয়তো "কনস" ("cons" নামের কনস্ট্রাক্ট ফাংশন দিয়ে তৈরি)। একটি কনস দুইটি অংশ নিয়ে গঠিত: প্রথম এলিমেন্ট এবং বাকি এলিমেন্টগুলো। ঐতিহাসিক কারণে এই দুই অংশকে car ও cdr বলা হয়। এই কনসগুলো যখন কোড হিসেবে ইভ্যালুয়েট করা হয়, তখন প্রথম এলিমেন্টটি (car) কল করা ফাংশনটিকে বোঝায়, আর বাকি এলিমেন্টগুলো (cdr) ওই ফাংশনের আর্গুমেন্ট বোঝায়:

(<function> <arg1> <arg2> ... <argN>)
; ^ car ^  |        ^ cdr ^

এক্সপ্রেশন

Common Lisp-এর সব কোড S-এক্সপ্রেশন (Symbolic Expressions) দিয়ে তৈরি। সংক্ষেপে এগুলোকে sexprs বলা হয়। প্রতিটি sexpr হয় একটি অ্যাটম, নয়তো একটি কনস। S-এক্সপ্রেশন ইভ্যালুয়েট হলে সেগুলো স্বয়ংক্রিয়ভাবে কিছু মান রিটার্ন করে, যা ওই এক্সপ্রেশনের জায়গা নেয়। নিজের ফাংশন লেখার সময় (defun ব্যবহার করে), defun-এর বডির ভেতরের শেষ মানটি স্বয়ংক্রিয়ভাবে রিটার্ন হয়:

;; Defining a new function
(defun gimme-foo () 'foo)
;; Calling the function as an S-Expression
(gimme-foo) ; => FOO

সিম্বল

Common Lisp-এ সিম্বল হলো বিশেষ ধরনের মান, যা অন্য মানের দিকে নির্দেশ করতে পারে, কিংবা কিওয়ার্ড-এর ক্ষেত্রে নিজের দিকে। লিস্প যখন সিম্বল ইভ্যালুয়েট করে, তখন সেগুলো যে মানের দিকে নির্দেশ করে, তা দিয়ে প্রতিস্থাপিত হয়:

foo  ; => <whatever-foo-points-to>
:foo ; => :FOO

মনে রাখবেন, কিওয়ার্ড বোঝানো হয় শুরুর কোলন (:) দিয়ে।

কোটিং, অর্থাৎ S-এক্সপ্রেশনের আগে ' যোগ করা, লিস্পকে ওই এক্সপ্রেশনটি ইভ্যালুয়েট না করতে বলে। আমাদের defun উদাহরণে 'foo কোট করার মাধ্যমে আমরা লিস্পকে FOO যে দিকে নির্দেশ করার কথা ছিল, তা খুঁজতে (এবং খুঁজে না পেতে) বাধা দিয়েছি, বরং FOO মানটি নিজেই রিটার্ন করেছি। আমাদের প্রোগ্রামে যদি কোথাও FOO ডিফাইন করা না থাকে:

foo  ; => <ERROR! Lisp doesn't know what foo points to!>
'foo ; => FOO

আপাতত আপনি এটিকে কেবল একটি ফাংশন থেকে সিম্বল রিটার্ন করার একটি উপায় হিসেবে ভাবতে পারেন, তবে আমরা কোটিং নিয়ে আবার ফিরে আসব এবং ভবিষ্যতের কনসেপ্ট অনুশীলনীতে এর আরও নানা দিক নিয়ে আলোচনা করব।

নির্দেশনা

আপনি! হ্যাঁ, আপনি, সাহসী লিস্পার! লেনি নামের Lisp এলিয়েনটির আপনার সাহায্য দরকার! লেনি বাকি সব Lisp এলিয়েনের সাথে আড্ডা দিতে যেতে চায়, কিন্তু তার বাবা-মা বলেছে ঘর পরিষ্কার না হলে সে কোথাও যাবে না।

সমস্যা হলো, লেনি মেঝেটা প্রায় দেখতেই পায় না! লেনি বুঝতেই পারে না কোনটা অ্যাটম আর কোনটা কনস, কোনটা সিম্বল আর কোনটা কিওয়ার্ড, কোনটা car আর কোনটা cdr!

এই জঞ্জাল গুছিয়ে ফেলতে লেনিকে সাহায্য করবেন? আপনার বন্ধনীগুলো ভুলে যাবেন না, এগুলো আপনার লাগবেই!

1. সিম্বল সম্পর্কে লেনিকে মনে করিয়ে দিন

শুরু করার আগে সিম্বল আর কিওয়ার্ড দেখতে কেমন হয়, সেটা লেনির একবার মনে করা দরকার। অনেক দিন হয়ে গেছে, শেষবার সে কিছু গুছিয়েছিল... দুটি ফাংশন ডিফাইন করে লেনিকে সাহায্য করুন: lennys-favorite-food, যেটা ইভ্যালুয়েট করলে কিছু একটা সিম্বল পাওয়া যায়, আর lennys-secret-keyword, যেটা ইভ্যালুয়েট করলে কিছু একটা কিওয়ার্ড পাওয়া যায়। উদাহরণ:

(lennys-favorite-food) ; => LASAGNA
(lennys-secret-keyword) ; => :ALIENS-ARE-REAL

মনে রাখবেন, আপনি চাইলে যেকোনো সিম্বল বা কিওয়ার্ড রিটার্ন করতে পারেন (যদি লাসাগনা পছন্দ না হয় বা এলিয়েনে বিশ্বাস না থাকে)।

2. অ্যাটম আর কনসের পার্থক্য করতে লেনিকে সাহায্য করুন

সিম্বল আর কিওয়ার্ড নিয়ে একবার মনে করিয়ে নেওয়া হয়ে গেলে, এবার পরিষ্কারের পালা! ঘরে ছড়িয়ে থাকা সব S-এক্সপ্রেশন গুছিয়ে ফেলতে হলে কোনটা কনস আর কোনটা অ্যাটম, সেটা বের করতে লেনির সাহায্য দরকার। আপনি দুটি ফাংশন ইমপ্লিমেন্ট করে সাহায্য করতে পারেন, is-an-atom-p আর is-a-cons-p:

(is-an-atom-p 'one-thing)    ; => T
(is-an-atom-p '(two things)) ; => NIL
(is-a-cons-p 'one-thing)    ; => NIL
(is-a-cons-p '(two things)) ; => T

এই অংশে লিস্পের বেশ কিছু বিল্ট-ইন ফাংশন আছে, যেগুলো আপনার কাজে লাগতে পারে। এছাড়া আপাতত T-কে ট্রু আর NIL-কে ফলস ধরে নিতে পারেন।

3. লেনির কনসগুলো ভাগ করতে সাহায্য করুন

শেষে, লেনির কনসগুলো এত ভারী যে পরিপাটি করে গুছিয়ে রাখা যায় না, তাই সেগুলোকে ছোট ছোট অংশে ভাগ করা দরকার। আরও দুটি ফাংশন ডিফাইন করে এই কনসগুলো ভাঙতে লেনিকে সাহায্য করবেন (first-thing আর rest-of-it)?

(first-thing '(first second third)) ; => FIRST
(rest-of-it  '(first second third)) ; => (SECOND THIRD)

এখানেও Common Lisp-এর কিছু বিল্ট-ইন ফাংশন কাজে লাগতে পারে।

GitHub-এর মাধ্যমে সম্পাদনা করুন লিংকটি একটি নতুন উইন্ডো বা ট্যাবে খোলে
Common Lisp Exercism

মোজা আর সেক্সপ্রস সাজানো শুরু করতে প্রস্তুত?

Exercism-এ সাইন আপ করুন, Common Lisp ট্র্যাকের 27টি কনসেপ্ট92টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।