قبل از اینکه شروع کنیم بد نیست بدونید که، اگر نیاز به REPL انلاین دارید و می خواین کد های این قسمت رو تست کنید می تونین از این REPL استفاده کنین. فقط نکته ای که باید بهش توجه کنید این هست که این REPL در واقع clojurescript هست و ممکن هست بعضی از نتایج با REPL کلوژر متفاوت باشه.
قبل از اینکه بریم سراغ اصل داستان نیاز هست که یه سری اصطلاحات پر کاربرد تو دنیای کلوژر رو بدونید که در طی یادگیری راحت باشید.
List
ساید خیلی شنیده باشید که میگن lisp و clojure زبان های پردازش لیست هستند. اما منظور از لیست چی هست ؟ لیست یکی از ساختار های اصلی داده در lisp و clojure برای کالکشن ها (Collection) هست که از نظر روش استفاده و ظاهر شباهت داره به آرایه ها در زبان های دیگه. برای مثال:
(1 2 3 4)
در کد بالا یک لیست از اعداد ۱ تا ۴ رو می بینید. برای تعریف لیست باید از پرانتز استفاده کنید و عناصر لیست رو با فاصله از هم جدا کنید. لیست ها در کنار ارزیابی (evaluation) مهمترین مفاهیم lisp و clojure هستند.
نکته مهمی که باید به اون توجه داشت اینه که اگر لیست بالا رو در REPL وارد کنید با خطایی مواجه می شید. دلیل این خطا این هست که clojure به صورت پیشفرض ( در ادامه خواهد خواند ) برای ارزیابی لیست عنصر اول رو به عنوان فانکشن در نظر می گیره و سعی می کنه که اون رو پیدا کنه اما چون همچین فانکشنی ( 1 ) وجود نداره اون خطا رو ایجاد می کنه. اما اگر می خواین یه لیست درست کنید بدون این که کدتون ارزیابی شه باید کد رو quote کنین. به این شکل:
(4 3 2 1)'
.
Evaluation
در همه زبان های برنامه نویسی، عبارات برنامه نویسی در زمان اجرا ارزیابی می شن و با ارزش یا عبارت حاصل از ارزیابی جابه جا می شن. دقیقا مثل عملیات ریاضی. مثلا 4 * (2 + 3)
با ارزیابی (2 + 3)
شروع می شه که نتیجه ارزیابی می شه 5
و عبارت اولیه به شکل در میاد 4 * 5
که ارزیابی نهایی می شه 20
. البته ارزیابی یه عدد می شه خود اون عدد. در زبان آمیانه می گیم نتیجه اجرای عبارت.
در کلوژر هم هر عبارتی یه روش ارزیابی می شه. مثلا اعداد، رشته ها (strings)، وکتورها (Vector) و تقریبا همه چیز به خود اون چیز ارزیابی می شن. اما در این میون ارزیابی لیست ها با همه چی فرق داره. کلوژر برای ارزیابی یه لیست به این شکل عمل می کنه که اولین عنصر (element) لیست رو به عنوان نام فانکشن و بقیه عناصر رو به عنوان پارامترهای اون فانکشن در نظر می گیره. بعد سعی می کنه اون فانکشن رو با پاس دادن پارامترهاش صدا بزنه. ارزیابی لیست میشه ارزش بازگشتی از اون فانکشن. به همین سادگی. برای مثال:
(myfunc 1 2 3 4)
کلوژر برای ارزیابی یا اجرای لیست بالا اول دنبال یه قانکشن به اسم myfunc
می گرده و وقتی پبداش کرد با پاس دادن چهار تا پارمتر بعدی 1، 2، 3 و 4 اون رو صدا می زنه به کل لیست رو با نتیجه صدا زدن اون فانکشن که در واقع ارزش بازگشتی از تابع هست جایگذین میکنه. به مثال پیچیده تر:
(println (str "3+2 = " (+ 3 2)))
در مثال بالا کلوژر از داخلی ترین لیست شروع به ارزیابی کردن می کنه. و با ارزیابی هر لیست اون رو با مقدار به دست اومده از ارزیابیش جایگزین می کنه. روند به این شکل هست:
۱. داخلی ترین لیست (2 3 +)
هست. برای ارزیابی این لیست فانکشنی به اسم +
رو پیدا می کنه، 2 و 3 رو بهش پاس میده و نتیجه برگشتی که 5 باشه رو با کل لیست جابه جا می کنه که. کل لیست در این مرحله به این شکل در میاد:
(println (str "3+2 = " 5))
۲. حالا نوبت به لیست بعدی میرسه که به این شکل هست (str "3+2 = " 5)
. فانکشن str
رو پیدا می کنه ( این فانکشن با چسباندن همه پارامترهاش به هم یه رشته می سازه و اون رو برمی گردونه) و "= 2+3"
و 5 رو بهش پاس می ده و رشته بازگشتی رو با خود لیست جا به چا می کنه. لیست این مثال تا اینجا به این شکل هست:
(println "3+2 = 5")
۳. حالا فقط یه لیست مونده. هموجور که حدس زیدن با صدا زدن فانکش println
و پاس دادن رشته ای که در عنصر دوم لیست هست، اون رشته رو در خروجی چاپ می کنه.
با دونستن در مورد لیست ها و روش ارزیابی اونها شما می تونین ۹۹٪ کد های کلوژر رو به راحتی بخونین.
خیلی ها می گن lisp و clojure سینتکس ندارن و این به این معناست که دستور زبانی برای این زبان ها وجود نداره ( البته بنده مخالف این گفته هستم). اما دلیل اصلیش این هست که شما در هنگام نوشتن کد یه نرم افزار با کلوژر به جای نوشتن دستور زبان در هال ساختن یه سری دیتا استراکچر هستید. در واقع کد همون دیتا هست. یه سری لیست تو در تو.
همین باعث شده که دستور زبان lisp، clojure و همه زبان های شبیه لیسپ در طی این همه سال پایدار بمونه. برعکس زبان هایی مثل جاواسکریپت که دستور زبانش هر سال تغییر مکنه lisp و clojure همیشه ثابت هست.
Immutable
شاید زیاد شنیده می گن دیتا استراکچر های فلان زبان immutable هستند. منظور از این عبارت این هست که دیتا استراکچر های اون زبان غیر قابل تغییر هست. یه دیتا رو نمی شه تغییر داد. اگر این موضوع رو خوب درک نمی کنین نگران نباشین. آروم آروم باهاش آشنا خواهید شد.
REPL
REPL مخفف عبارت Read, Eval, Print, Loop
به معنی بخوان، اجرا کن، چاپ کن، و لوپ انجام بده ( برگرد به اول) هست. کلوژر با خواندن دیتا به شکل متن و تبدیل اون به دیتا استراکچر هایی مثل لیست و اجرای ( ارزیابی) اون ها نتیجه رو در خروجی چاپ می کنه و دوباره منتظر ورودی میشه.
به زبان ساده تر REPL یه محیط محاوره ای (شبیه به ترمینال و شل) برای کد های کلوژر هست. آلتبه خیلی بیشتر از اینهاست اما فعلا این توضیح تا اینجا کافیست.
شما می تونین با فرمان زیر به یه REPL دسترسی داشته باشید. lein repl
Binding
در کلوژر مفهومی با عنوان متغیرر ( variable ) و جود ندارد. همون جور که در بالا توضیح داده شد دیتا استراکچر های کلوژر immutable هستند و تغییر ناپذیر، پس متغییر کاملا بی معنی هست.
با اختصاص دادن یک اسم رو به یه مقدار یه بایندیگ ساخته می شه. در واقع یک باندیگ یه اسم برای یه داده هست. برای مثال:
(def myname "sameer")
در کد بالا سمبل myname
به مقدار “sameer” اختصاص داده مشه (به صورت سراسری).
Symbol
ردرک سمبل ها برای افرادی که از زبان هایی به کلوژر میان که در اونها همچین مفهومی وجود نداره، سخت هست.
سمبل ها فقط شناسنده هستند و بس. یه سمبل یه اسم هست که به چیزی اشاره می کنه. برای مثال اسمی که به یه بایندیگ یا یه فانکشن اشاره می کنه.
دوست دارم نظرتون رو در مورد این قسمت بدونم دوستان.