SlideShare a Scribd company logo
1 of 31
Download to read offline
مصاحبه ریچ هیکی سازنده کلوژر با رادیو مهندسی نرم افزار 
(jzinedine@gmail.com) ترجمه: جهانگیر زین الدین 
صحبت کنیم. مهمان ما آقای کلوژر، Clojure مارکوس: این بار ما می خواهیم در مورد 
ریچ هیکی است. 
لطفا قبل از صحبت در مورد آنچه که ساخته اید، در مورد خودتان حرف بزنید. 
ریچ: خوب من ریچ هیکی هستم و کلوژر را نوشته ام، یک زبان برنامه نویسی دینامیک که 
محیط اجرایی مربوط به دات نت) اجرا می شود، چهار ویژگی اصلی )CLR و JVM روی 
میزبانی VM دارد، یک زبان مبتنی بر لیسپ است و طوری طراحی شده که توسط یک 
.JVM شود، بنابراین رابطه نزدیکی با پلتفرم میزبان دارد مانند 
مبتنی بر توابع) است و روی تغییر ناپذیری و توابع محض و ) functional عمدتا 
ساختمان داده های تغییر ناپذیر تاکید دارد، همچنین روی همزمانی متمرکز است. 
تمام جنبه های زبان طوری طراحی شده اند که در متن یک برنامه همزمان 
درستی داشته باشند. (semantic) معنای 
مارکوس: بعدا در مورد آن بیشتر کنکاش خواهیم کرد. 
می خواهم خوانندگان بدانند که ما قبلا برنامه ای در مورد لیسپ داشته ایم، برنامه شماره 
۸۴ با گابریل. همچنانکه ما ممکن است در مورد مقدمات لیسپ به صورت مختصر صحبت 
کنیم، اما به خاطر ضیق وقت بنا نداریم اینجا معرفی کاملی از لیسپ ارایه کنیم. 
اگر با لیسپ آشنا نیستید لااقل به صورت کلی می بایست به برنامه ۸۴ رجوع کنید. 
ریچ، علیرغم این به نظرم فکر خوبی است اگر لیسپ را به صورت اجمالی معرفی کنید. 
مبانی اصلی لیسپ چه هستند، چه تفاوتی با زبانهای برنامه نویسی دیگر دارد که به 
خاطر آن از نظر بسیاری افراد یک زبان خاص تلقی میشود.
ریچ: خوب، سوال آخر احتمالا بهترین سوال است، بسیاری از چیزها که لیسپ ابداع کرده 
است در زبان های دیگر نیز به صورت گسترده وجود دارد. فکر می کنم آنچه که لیسپ را 
منحصر به فرد می کند، این است که برنامه به صورت ساختمان داده به کامپایلر عرضه 
می شود، پس کامپایلر لیسپ متن را کامپایل نمی کند بلکه ساختمان داده ها را کامپایل 
می کند، و زمانی که شما با لیسپ(کلوژر) برنامه ای می نویسید در واقع با ساختمان 
داده ها و از طریق آنها برنامه می نویسید. 
اگر شما متنی را در فایلی ذخیره می کنید در واقع داده های عینی را ذخیره می کنید. 
می سازند که AST پس تفاوت این با زبانهایی که برنامه را ترجمه می کنند و از روی آن 
به نوعی یک ساختمان داده است که به کامپایلر عرضه میشود، چیست؟ 
از چیزهایی ساخته شده که برنامه AST این موضوع خیلی مرتبط است با اینکه آیا آن 
شما معمولا با آن سر و کار دارد، در یک برنامه لیسپ و به طور خاص در کلوژر، داده 
های عینی چیزهایی هستند که شما به صورت روزمره از انها استفاده می کنید. 
پس کتابخانه بزرگی برای کار با آنها وجود دارد، آنها کتابخانه ،list و map ،vector 
نیستند بلکه کتابخانه های معمولی متعلق به زبان هستند، AST های خاصی برای کار با 
بنویسید. AST که بدین معنی است که لازم نیست برنامه خاص یا عجیبی برای دستکاری 
هر دو یک (meta programming) مارکوس: پس برنامه نویسی و فرا-برنامه نویسی 
چیز هستند! 
ریچ: دقیقا، تفاوتی وجود ندارد، و این بسیار مهم است، اگر شما قبلا با کتابخانه ای 
API کار کرده باشید که شی گرا بوده باشد، می فهمید که دارید یک AST مربوط به 
خاص را می خوانید، اما زمانی که کد مربوط به یک ماکرو را در لیسپ یا کلوژر می 
خوانید کدهای کاملا معمولی برای پردازش دادها هستند.
مارکوس: خوب شما از چه ساختمان داده های دیگری استفاده کرده اید که پیشتر در 
مورد آنها صحبت کردید، چون لیسپ به نظر فقط لیست های تو در تو است، درست است؟ 
ریچ: این برای لیسپ به صورت سنتی درست است، اما در کلوژر چندین ساختمان داده 
دیگر وجود دارد که همگی در اولویت بالایی قرار دارند و مانند لیست درجه یک محسوب 
.(hash table) که شبیه جداول درهم سازی است map و vector ، می شوند 
در نحو زبان فرم هایی وجود دارند که بر مبنای همین ساختمان داده ها ساخته شده اند، 
ها. map ها و گاهی vector گاهی مبتنی بر 
مارکوس: شما می دانید و در برنامه ۸۴ هم آمده که لیسپ زبان جدیدی نیست و یک 
رویکرد قدیمی است و در زمینه های خاصی با موفقیت مورد استفاده قرار کرفته است اما 
هیچگاه یکی از زبانهای اصلی مورد استفاده عموم نبوده است. شما چه فکری می کنید، 
چرا این اتفاق نیافتاده است؟ و سوال بعدی اینکه چرا شما در سال ۲۰۰۹ یا ۲۰۱۰ لیسپ 
خودتان را ساختید؟ 
ریچ: هاها، اینها دو سوال مجزا هستند، من مطمئن نیستم که لیسپ برای استفاده عموم 
طراحی شده باشد، آن زمان که بوجود آمده برای کاربران ارشد طراحی شده مانند 
محققین و افراد بسیار باهوش که سعی می کردند مسایل بسیار سخت را حل کنند و 
لیسپ کاملا اهرم مناسبی برای تلاشهای آنها بود. به عنوان یک فرد شما قدرت 
باورنکردنی ای به واسطه لیسپ داشتید. ما همه می دانیم که برنامه نویسی در مقیاس 
بزرگ یک فعالیت اجتماعی است که افراد دیگری هم در آن درگیر هستند، کتابخانه های 
برنامه نویسی در آن دخیل هستند و به طور خاص بسیار مهم است که بتوانید با کتابخانه 
هایی که دیگران به همان زبان یا به زبان دیگری نوشته اند تعامل کنید. 
این یکی از زمینه هایی است که لیسپ به طور سنتی در آن خوب عمل نکرده است چون 
این محدوده ها و رویکردها بیشتر شبیه جزیره اند، جزیره هایی با درختها و مناظر زیبا،
اما به خوبی به جاهای دیگر دنیا وصل نیستند. عوامل اجتماعی و تاریخی دیگری وجود 
دارند که مربوط به هوش مصنوعی هستند، مرگ آن در دهه ۸۰ و ۹۰ که با عدم اقبال به 
لیسپ همراه شد، اما لیسپ قدرتش را از دست نداد، برای اینکه به سوال دوم شما برسم، 
که چرا من امروز اینکار را کرده ام؟ ویژگی دومی که لیسپ دارد هنوز منحصر به فرد 
است چون برنامه ها همان ساختمان داده ها هستند شما می توانید برنامه هایی بنویسید 
که آن برنامه ها به نوبه خود برنامه بنویسند. و جنبه مهم دیگر لیسپ این است که وقتی 
کامپایلر لیسپ برنامه شما را ارزیابی می کند، به ماکروها که برنامه های کوچک دیگری 
هستند اجازه می دهد در حین کامپایل اجرا شوند که بدین معنی است که برنامه های 
شما که برنامه می نویسند، می توانند با کامپایلر یکپارچه شوند. 
مارکوس: فکر می کنم این یک خاصیت بسیار مهم است، چون چندان سخت نیست که 
استفاده کند که یک برنامه جاوا تولید کند، Eclipse AST API برنامه ای نوشت که از 
شاید به اندازه کلوژر راحت نباشد هر چند این موضوع سلیقه ای است، اما اینکه قادر 
باشید آنرا در فرآیند تبدیل یا کامپایل اضافه کنید باعث می شود این کار بسیار بی 
دردسر و یکپارچه باشد و این مهم است. 
ریچ: درست است، این ویژگی ای را مهیا میکند که موسوم به گسترش پذیری نحو 
است که چیز قدرتمندی است و برای برنامه ها مهم (syntactic extensibility) زبان 
است، همانطور که انتزاع تابع مهم است، ما نمی خواهیم یک چیز را چندین بار بنویسیم، 
می خواهیم یکبار بنویسیم و از آنها استفاده مجدد کنیم. الگوهای زیادی در نرم افزار 
وجود دارد که به درستی توسط آبجکت ها و متدها کپسوله نمی شود، مثال ساده در جاوا 
است، الگوهایی که شما مجبورید آنها را مدام تکرار کنید چون ابزاری برای try بلوک کد 
کپسوله کردن آن ندارید که از آن طریق تکرار را از بین ببرید. 
به نظر من این امکان چیز بسیار ارزشمندی است و هنوز ارزش دنبال کردن دارد. کاری 
که من می خواستم انجام دهم ساختن لیسپی بود که نکات قوتش پا بر جا باشد اما مشکل
جزیره بودن آن را حل کند. کلوژر چون یک زبان میزبانی شده است و روی جزییات پیاده 
سازی نشده است مانند یک ویژگی است و در دسترس است بدین معنی است که به 
عنوان یک زبان جدید به تمام کتابخانه های جاوا دسترسی کامل دارد و توان بالایی برای 
تعامل با برنامه های جاوا دارد و شما بلافاصله از جزیره بودن رها شده اید. 
مارکوس: من بعدا به این موضوع بر میگردم اما الان می خواهم مختصر در مورد فرا- 
صحبت کنم. گسترش پذیری نحو خصیصه ی (meta programming) برنامه نویسی 
مهمی است و مقیاس شما برای سنجش قدرت زبانهایی مانند لیسپ بود. اما اگر من 
بخواهم نقش وکیل مدافع شیطان را بازی کنم خواهم گفت که اصلا لیسپ نحوی ندارد، 
اگر همه چیز در زبان لیست است پس نمایش هر چیزی به عنوان لیست کار ساده ای 
است، البته که من دارم اغراق می کنم اما آنچه که می خواهم بگویم این است که این 
واقعیت که لیسپ از نظر نحوی قابل گسترش است و رشد می کند با وجود اینکه بسیار 
قدیمی است، به این خاطر است که لیست نحو و دستور زبان جزیی دارد و شاید بتوان 
گفت اصلا نحوی ندارد. 
انجام این کارها در زبانهای دیگر مانند جاوا ممکن نیست به خاطر استقلال ابزار فرا- 
برنامه نویسی، حال این خاصیت چقدر مهم است اگر شما بخواهید آن را توضیح دهید. 
ریچ: این بحث بسیار مهم است، سیستم های فرا-برنامه نویسی زیادی وجود دارند که 
استفاده از آنها به اندازه لیسپ ساده است، این موضوع ربطی به این ندارد که در لیسپ 
همه چیز لیست است، در واقع در کلوژر همه چیز لیست نیست و این موضوع مهمی است 
چرا که اگر همه چیز لیست است باعث میشود همه چیز پیچیده تر شود و لیست دچار 
سربار اضافی شود. چون نحو زبان وجود دارد اما در نمایش کاراکتر ها نیست، کاراکتر 
ها برای نمایش ساختمان داده ها هستند، نحو در تعبیر آن ساختمان داده ها مستتر 
است.
مارکوس: نحو در سطح کلمات است. 
ریچ: نه بالاتر در سطح لیست ها و بردارهای تو در تو. این واقعیت که نحو زبان، 
ساختمان داده است و زمانی که شما مبدلی می نویسید دوباره ساختمان داده های 
جدیدی می سازید و اینها همان ساختمان دادهای ساده موجود و تعبیه شده در سیستم 
هستند باعث می شود فرا-برنامه نویسی بی نهایت ساده شود. 
مارکوس: شما گفتید که مخاطب لیسپ دانشمندان بودند که روی هوش مصنوعی کار می 
کردند، مخاطبان کلوژر چه کسانی اند؟ برنامه نویسان جاوا، لیسپ؟ 
ریچ: فکر می کنم هر برنامه نویسی با ذهنی به اندازه کافی باز کار کردن با لیسپ را 
تجربه ای جالب و هیجان انگیز خواهد یافت، تجربه من اینگونه بوده است، من بیش از یک 
دهه با سی پلاس پلاس و جاوا و سی شارپ کار کرده ام، لیسپ به طرز باور نکردنی ای 
شما را تواناتر می کند و فکر می کنم برداشت اولیه اکثرا افراد در مورد لیسپ غیر واقعی 
است چرا که هسته اصلی کلوژر بسیار ساده تر از جاوا است. آنچه که مشاهده میکنید 
این است که زبان بسیار ساده و موجز است اما بالقوه بسیار قوی تر از جاوا است. 
مارکوس: این بحث به خاطر این پیش می آید که هر کسی برداشتی از سادگی دارد، شما 
ممکن است بگویید لیسپ ساده است چرا که نحو بسیار ساده و موجزی دارد و تنها 
(orthogonal) شامل چند انتزاع است که پیشتر در مورد آن گفتید، ساختاری متعامد 
دارد، می توانید برنامه هایی بنویسید که برنامه ای بنویسند که برنامه بنویسد، اما 
شخص دیگری می گوید جاوا ساده است چرا که راه مشخص است و ما اجزای برنامه 
نویسی مشخصی داریم و ما در برهوت رها نشده ایم و در یک مسیر از پیش تعیین شده
قرار می گیریم که ممکن است تحت عنوان سادگی تعبیر شود، نمی دانم می خواستم چه 
بگویم! 
است، وقتی شما (familiarity) ریچ: من فکر میکنم منظور اکثر افراد در آنجا آشنایی 
در جاوا را به او نشان می Hello World دست یک نفر را در خیابان بگیرید و برنامه 
دهید اگر شما واقعا بخواهید هر خط آن برنامه را برای او توضیح دهید خواهید فهمید که 
جاوا چقدر پیچیده است. ما فقط با آن راحتیم اما اصلا ساده نیست. اما وقتی که من در 
مورد سادگی لیسپ و کلوژر به صورت صحبت می کنم، منظورم سادگی نحو زبان نیست 
هر چند نحو ساده ای دارد منظورم عدم وجود پیچیدگی های پنهان و ضمنی است که 
دقیقا چیزی که ما را اذیت می کند. 
مارکوس: من باید بگویم که من تجربه عملی با لیسپ ندارم اما می توانم انچه را که می 
گویید بفهمم. دوست دارم چهار هفته ای وقت بگذارم و کار معنا داری با لیسپ انجام دهم 
ها داشتیم و حدود ده DSL تا تجربه کسب کنم. دو هفته پیش ما کنفرانسی در مورد 
صحبت DSL نفری جمع شده بودیم که در مورد ابزار و امکانات و زبانها برای ساختن 
مارتین فاولر را نشان داد و کدها state machine کنیم، و یکی از جمع تعدادی مثال 
بسیار تمیز و زیبا بود. من می فهمم شما چه میگویید اما نمی توانم آنرا به واسطه فقدان 
تجربه کار با لیسپ تایید و تحسین کنم و به همین خاطر است که ممکن است کمی مردد و 
بد بین به نظر برسم اما قصدم این نیست. 
ریچ: من قطعا بحث آشنایی را تایید می کنم. این یک جنبه مهم و یک مانع است که افراد 
باید از آن رد شوند اگر می خواهند کشف کنند که آن طرف مانع چیست و چه امکاناتی 
مهیاست، اما این موضوع بیشتر به آشنایی مربوط است تا به سادگی.
مارکوس: من از همین استدلال استفاده می کنم آنگاه که می خواهم افراد را قانع کنم که 
استفاده کنند، شما باید باور ASCII به جای MPS Projector از ویرایشگرهای کد 
کنید که چمن های آن طرف سبزترند و باید این سختی را تحمل کنید. 
خوب کلوژر چه تفاوتی با لیسپ کلاسیک یا نرمال دارد، شما قبلا گفتید که به خوبی با 
یکپارچه شده است که به آن هم می رسیم اما از نظر زبان چه تفاوتهایی وجود دارد؟ VM 
ریچ: دو تفاوت اصلی وجود دارد، یکی اینکه در لیسپ سنتی ساختمان داده های اصلی 
و دیگر ساختار داده hashtable ، را دارند که همان لیست است cons تغییرپذیرند، آنها 
های مدرن اما همه آنها تغییرپذیرند. چون من می خواستم همه ساختمان داده های 
اصلی در کلوژر تغییرناپذیر باشند، به همین خاطر نمی توانستم کلوژر را بر مبنای 
بسازم. common lisp یا scheme 
همینطور و در واقع scheme زمینه بعدی تفاوت این است که لیسپ بسیار قدیمی است و 
Polymorphic API و Interface آنها قبل از بوجود آمدن مفاهیم مدرنی مانند 
به وجود آمده اند، لیسپ زمانی ارایه شد که دستورات شرطی جزو ابداعات Design 
کلوژر مبتنی بر یک سری انتزاعات ساخته شده است API . جدید در برنامه نویسی بود 
در حالی که در لیسپ سنتی توابع کتابخانه ای برای کار کردن با لیست، به صورت جدایی 
vector و map ناپذیری به یک ساختمان داده متصل شده اند همچنانکه توابع مربوط به 
ها همینطور هستند، در حالی که در کلوژر انتزاعی برای همه ساختمان داده ها وجود 
دارد و تمام کدهای مربوط به کتابخانه ها با توجه به این موضوع نوشته شده اند، شما می 
توانید فکر کنید که شبیه اینترفیس های جاوا هستند، همچنانکه واقعا در لایه های زیرین 
ها با sequence اینترفیس های جاوا هستند. این بدین معنی است که کتابخانه مربوط به 
هستند یا اینکه می توانند به صورت سری remote همه داده هایی که به صورت سری 
نمایش داده شوند، کار می کند. این بسیار مهم است شما حالا می توانید از کد های 
کتابخانه، موثرتر استفاده کنید و شما را توانمندتر می سازد. اینها دو تفاوت اصلی 
هستند.
مارکوس: 
خواص شی گرایی دارد هر چند که این شی گرایی با آنچه ما در common lisp 
زبانهای اصلی دیگر می شناسیم تفاوت دارد، آیا شما هم این را دارید، می توان کلاس 
تعریف کرد؟ و چه تفاوتهایی با کلاس های جاوا دارند یا شاید تفاوتی ندارند؟ 
ریچ: شما دو کار می توانید انجام دهید، می توانید اینترفیس و کلاسهایی تعریف کنید که 
در واقع همان اینترفیس و کلاس های جاوا هستند و برای تعامل با جاوا ساخته شده اند 
و همچنین به عنوان ابزاری برای انتزاع. در نسخه بعدی مفهومی به نام پروتکل وجود دارد 
که شبیه اینترفیس های جاوا هستند با این مزیت که می توانید کلاس های موجود را که 
کنترلی روی آنها ندارید، گسترش دهید و در یک پروتکل شرکت دهید، در حالی که در 
اینترفیس ها شما مجبورید که کلاسی مشتق کنید. این مکانیسم اصلی انتزاع است، هر 
چند این شی گرا نیست اگر بخواهید از دیدگاه شی گرایی سنتی به موضوع نگاه کنید، 
چون اکثر افراد به آبجکت به عنوان یک چیز قابل تغییر که حاوی وضعیت هایی است فکر 
می کنند، هر چند کلوژر همچنان این امکان را نیز از طریق تعامل با جاوا فراهم می کند. 
مارکوس: پس انتزاع اصلی که شما می خواهید در کلوژر بسازید ساختمان داده ها به 
همراه توابعی است که روی آنها کار میکنند. 
ریچ: درست است، در پروتکل ها شما همچنان قادر خواهید بود مجموعه ای از توابع با 
اسم را به عنوان انتزاع ها تعریف کنید و رفتار چند ریختی را داشته باشید. من چند 
ریختی را دوست دارم و فکر میکنم شما می توانید به شی گرایی افتخار کنید که توانسته 
آن را خوب ارائه کند.
مارکوس: آیا پروتکل ها به عنوان آداپتوری برای سایر ساختمان داده هایی کار می کنند 
که هنوز این رفتارها را به صورت مستقیم پیاده سازی نکرده اند؟ 
ها نیست. wrapper ریچ: آنها شبیه آداپتور ها هستند با این تفاوت که نیازی به 
نیست. wrapper مارکوس: پس کامپایلر اینجا حرکتی انجام می دهد که نیازی به 
ریچ: بله. 
مارکوس: این مرا به سوالی رهمنون می کند که من آنرا قبلا جواب داده ام، این زبان 
کامپایل می شود نه تفسیر. 
هم REPL ریچ: درست است در کلوژر مفسری وجود ندارد. شما لود دینامیک دارید و 
دارید. فقط هر چیزی در زمان لود کامپایل می شود. 
مارکوس: 
است. read-eval-print-loop مخفف REPL 
ریچ: بله یک رابط تعاملی است که می توان همان لحظه کد نوشت و نتیجه آنرا دید.
مارکوس: آیا شما در مورد سرعت عملکرد کلوژر نسبت به جاوا بررسی ای انجام داده 
اید؟ 
ریچ: بله، در مورد فراخوانی متدهای معمولی سرعت به همان اندازه جاوا است، چون 
است، تفاوت بزرگ با جاوا در این است که در کلوژر اعداد همیشه byte code همان 
استفاده می کنید و این BigLong و BigInteger شده اند، پس شما همیشه از box 
سربار خواهد داشت، و به وضوح پیداست که عملیات ریاضی با آنها کندتر است. اما 
و ،long و int شما در توابع می توانید انواع داده ابتدایی جاوا را تعریف کنید مانند 
عملیات ریاضی با آنها به همان سرعت جاوا است. البته که طبقات متفاوتی وجود دارد 
چون لیسپ به صورت پیش فرض اعداد صحیح بزرگ را به انواع داده ی بزرگتر برای 
نگهداری نتایج عملیات تبدیل میکند(به جای سرریز شدن)، کلوژر سه نوع عملیات ریاضی 
روی داده های ابتدایی native ارائه می کند، یکی این است که گفته شد، دیگری عملیات 
انجام می دهد و سرریزی را چک می کند که استفاده از آن امن است و نوع سوم اساسا 
بد است و آن همانی است که جاوا انجام می دهد، جاوا سرریزی پنهانی دارد، شما اگر 
این را می خواهید این سریعترین است و در کلوژر در دسترس است. 
مارکوس: حال بیاید در مورد رویکرد کلوژر به همزمانی حرف بزنیم، چرا که اولا این روزها 
همزمانی عموما موضوع جالبی است علاوه بر اینکه این موضوع یکی از انگیزه های شما 
و از ویژگی طراحی این زبان بوده است، یکی از دلایلی که کلوژر با همزمانی جفت و جور 
است این است که ساختمان داده ها تغییرناپذیرند، می توانید کمی در مورد آن صحبت 
کنید. 
ریچ: بله حتما، من می خواهم دقیقا از همینجا شروع کنم، به صورت کلی رویکرد کلوژر به 
ساختمان داده ها، شی گرایی و همزمانی به شدت به هم پیوسته اند، و اینها همه ناشی 
داشته ایم. (state) از دردسرهایی است که ما در رابطه با وضعیت
مارکوس: من فکر می کنم سخنرانی شما در مورد زمان را دیده ام، یادم نیست دقیقا در 
بود یا جای دیگری. QCon 
بود. JVM Language Summit ریچ: بله در 
بله این دقیقا توجیه وجود کلوژر است، حتی اگر شما همزمانی نداشته باشید، برنامه های 
شی گرای بزرگ با پیچیدگی رو به افزایشی دست به گریبان خواهند بود وقتی که گراف 
بزرگی از آبجکت های تغییرپذیر را می سازند و تلاش برای فهمیدن و به خاطر سپردن 
اینکه وقتی یک متد را فراخوانی می کنید چه اتفاقی رخ می دهد و اثرات جانبی آن چه ها 
هستند و چه تاثیراتی در کجاها دارند، بسیار سخت خواهد بود. 
مارکوس: آیا این فقط به این خاطر است که اتفاقات داخل سیستم اثرات جانبی دارند؟ یا 
شما به چیز نامعلوم یا غریب دیگری اشاره دارید؟ 
ریچ: نه من دارم در مورد آبجکت های تغییرپذیر حرف می زنم با این سادگی که اگر به 
شما یک آبجکت تغییرپذیر بدهند می توانید به عنوان یک مقدار به آن رفرنس داشته 
باشید؟ آیا شما می توانید مطمئن باشید که اگر بعدا دوباره به آن مراجعه کنید همان 
است و کسی آنرا تغییر نداده است؟ این مفاهیم در برنامه نویسی شی گرا در هم آمیخته 
شده اند و از این دیدگاه این مشکل بزرگی است. 
که این JVM Language Summit مارکوس: من می توانم به خاطر بیاورم از کنفرانس 
است. (state and identity) تفاوت بین وضعیت و شناسه 
ریچ: بله درست است.
مارکوس: شی در طول زمان بدون تغییر باقی می ماند اما مقدار و وضعیت آن تغییر می 
کند. 
ریچ: پس اگر شما قادر باشید که آن مقادیر را نگه دارید آنگاه بخش بسیار بزرگی از 
بخشی که تغییر می کند) خواهد بود. )(identity) برنامه اتان مستقل از شناسه ها 
مارکوس: به کلام دیگر شما مقادیر را نگهداری می کنید نه شناسه ها را. 
ریچ: بله می توانید مقادیر را به سادگی نگه دارید و بدون نگرانی روی آنها محاسبات 
انجام دهید. و ما باید بیشتر اینکار را انجام دهیم، فکر می کنم وقتی ما شروع به برنامه 
نویسی شی گرا کردیم و کلاس ها را ساختیم و تصمیم گرفتیم که اعضای کلاس را به 
صورت پیش فرض قابل تغییر قرار دهیم ما بسیار بیشتر از آنچه نیاز بود تغییر داشتیم و 
حذف این همه امکان تغییر کار سختی خواهد بود. کلوژر رویکردی برعکس دارد و می 
گوید بیایید با مقادیر برنامه نویسی را شروع کنیم که تغییر نمی کنند و تا آنجایی که 
ممکن است با آنها کار کنیم و تنها بعد از آنکه به شناسه ها نیاز داشتیم آنگاه با آنها به 
صورت مستقل برخورد خواهیم کرد و تلاش خواهیم کرد که تصمیمات متعامد و صحیحی 
درباره موضوعات اتخاذ کنیم. پس با برنامه نویسی از طریق مقادیر شروع می کنیم، 
که به سوال اول شما برمیگردد که چگونه می خواهید چیزهای بزرگتر از اعداد و رشته ها 
را به صورت مقدار نمایش دهید، شما به ساختمان داده های کارآمدی نیاز دارید که به 
ها را به صورت مقدار نمایش دهید یا حتی چیزهای کوچکتر مانند collection طور مثال 
آبجکت ها، برای همین کلوژر مجموعه ای از ساختمان داده ها دارد که موسوم به 
ساختمان داده های پایدار است، پایدار به معنی ذخیره شدن در دیسک نیست در این 
مورد پایداری به معنای ساختمان داده ای است که تغییرناپذیر است، و اگر بخواهید آنرا 
تغییر دهید یک نسخه جدید از آن را تولید خواهید کرد.
مارکوس: یک کپی دیگر از آن! 
ریچ: نه چون ویژگی دیگر این ساختمان داده ها این است که آنها سرعت را برای شما 
خواهد بود. log(n) یعنی اضافه کردن با پیچیدگی ،O تضمین می کنند، ضمانت 
مارکوس: اجازه دهید اینطور بگویم که از نظر مفهومی به نظر میرسد که داده ها تماما 
کپی شده اند اما به روشی هوشمندانه تر این کار انجام میشود. 
ریچ: دقیقا و این همان نکته اصلی است، و لازم است اینها را بگوییم چون برداشت اولیه 
افراد این است که داده ها کپی میشوند و این نمی تواند کارآمد باشد اما این اتفاق نمی 
افتد. 
در ساختمان داده های پایدار شما یک نسخه جدید می سازید و این از نظر سرعت 
تضمین شده است، پس بنا نیست که داده ها کپی شوند چرا که اگر شما تعهد داده اید 
O(n) است و بخواهید دادها را کپی کنید این کار log(n) که پیچیدگی این عملیات 
خواهد بود. 
ویژگی های دیگر ساختمان داده ها این است که نسخه قبلی همچنان در دسترس است، 
و از بین نرفته است یا تنزلی پیدا نکرده است پس سرعت نسخه قبلی همان است که بود. 
چرا که الگوهایی برای پایداری وجود دارد که باعث میشود نسخه قدیمی به مرور تنزل پیدا 
کند، به واسطه روشی که این نسخه ها ساختارشان را به همدیگر به اشتراک گذاشته اند. 
پس همه نسخه ها به یک اندازه خوب هستند. 
زمانی که شما همه اینها را دارید، کلی ابزار متفاوت برای برنامه نوبسی دارید، نگهداری 
همه (stack) برگشت عملیات)، پشته ها )undo ، مقادیر ساده است، ذخیره سازی 
ارزان به دست می آیند، انجام طراحی عملیات به صورت بازگشتی ارزان است، و مواجهه 
با همزمانی راحت خواهد بود، چون همه مقادیر تغییرناپذیرند، آنها نیازی به قفل کردن یا 
چیز دیگری ندارند برای اینکه در یک محیط همزمان مورد استفاده قرار گیرند.
مارکوس: به نظرم می ارزد که پنج دقیقه ای دیگر روی این ساختمان داده های پایدار 
زمان صرف کنیم، چرا که من آنها را فراموش کرده بودم و اگر یادتان باشد اصلا جزو 
موضوعاتی نبود که قرار بود در مورد آنها صحبت کنیم، اما خیلی نکات مهمی در مورد 
آنها وجود دارد. 
فرض کنید که من یک عبارت ساده دارم که یک عدد ضربدر حاصل جمع در عدد دیگر 
۲ حالا ۴ را با ۵ عوض می *(۳+ میشود چیزی شبیه به یک ساختمان داده درختی، ( ۴ 
کنم، به صورت ساده انگارانه من باید کل درخت را کپی کنم و این اتفاق نمی افتد، لطفا 
بگویید چه اتفاقی می افتد که شما یک کپی دیگر دارید اما کپی ای انجام نمی دهید؟ 
ریچ: اگر ما ساده ترین ساختمان داده پایدار را در نظر بگیریم یک لیست پیوندی یک طرفه 
داشته باشیم و بخواهیم یک عضو به اول C و B ،A است، اگر ما یک لیست با اعضای 
شما یک گره جدید می سازید و آنرا به لیست من وصل می کنید با ،X آن اضافه کنیم مثلا 
مقدار دهی انتهای آن. 
مارکوس: در این مورد ساده است، موافقم. 
ریچ: اما نکته مهم اشتراک ساختار است، انتهای لیست شما با تمام لیست من 
ساختارشان را به اشتراک گذاشته اند. 
مارکوس: و چون من نمی توانم هیچ چیز را تغییر دهم، این نمی تواند باعث ایجاد مشکلی 
شود، مثلا این اتفاق که کسی یکی از داده های مرا تغییر دهد پیش نمی آید. 
ریچ: دقیقا و این نکته مهم بعدی است، چون من نمیتوانم لیست ام را تغییر دهم، پس نمی 
توانم لیست تو را هم دچار مشکل کنم. و برای اعمال این اصل به تمام ساختمان داده
های دیگر، باید لیست را رها کرده و سراغ درخت بروید و این بدین معنی است که تمام 
همه درخت هستند. به همین vector یا hashmap ساختمان داده های کلوژر مانند 
خاطر برای این کار لازم است تنها مسیری را کپی کنید که شامل بخشی است که آن را 
تغییر داده اید، به جای کل درخت. 
را با آرایه نمایش دهید، چاره ای جز این نخواهید vector مثلا اگر شما بخواهید یک 
داشت که کل آرایه را کپی کنید. 
مارکوس: از دیدگاهی می توان درخت را به عنوان تعدای لیست پیوندی در نظر گرفت و هر 
گره به یک انتها چندین انتها دارد و این یک درخت می سازد. 
ریچ: بله می توانید، هر چند پیاده سازی آن اینطور نیست 
مارکوس: بله منظورم از نظر مفهمومی است. 
ریچ: بله و به همین خاطر بود که من با لیست شروع کردم، اساسا شما یک زنجیره از 
چیزها را دارید و با استفاده از درخت، تغییر هر برگی از این درخت تنها نیازمند تغییر 
یک مسیر به ریشه است و نه چیز دیگری، و نسخه جدید همه چیزش شبیه نسخه قبلی 
است به جز این مسیر جدید. 
پس ساختمان داده های کلوژر درختهایی از آرایه ها هستند، بنابراین ضریب شاخه 
شاخه شدن بالایی دارند و عمق بسیار کمی دارند، و به همین خاطر سرعت بالایی دارند. 
پس اینگونه کار می کنند.
مارکوس: پس شما هیچ چیز را به اشتراک نمی گذارید و همه چیز تغییرناپذیر است پس 
نیازی به قفل کردن ندارید، و همه مشکلات مربوط به قفل گذاری بلافاصله حل می شود. 
اما مردم می پرسند اگر شما هیچ چیز را تغییر نمی دهید پس برنامه شما چگونه کار می 
کند، در یک زمان خاص شما لازم است که چیزی را تغییر دهید مانند یک پایگاه داده یا 
چیزی که باید تغییر کند. آیا شما با این موضوع مواجه میشوید، و اگر بلی، چگونه؟ 
ریچ: این یکی دیگر از نکات مهم در مورد کلوژر است، کلوژر تلاش نمی کند به شما 
بگوید که میتوانید تنها با توابع محض و ساختمان داده ای تغییرناپذیر برنامه بنویسد، 
چرا که برنامه های واقعی که در طول زمان مشغول ارائه سرویس هستند و با دنیای بیرون 
در ارتباط اند دارای وضعیت هستند، پس چگونه اینکار را انجام میدهید؟ 
نکته مهم فهم تفاوت بین مقادیر و شناسه ها است، که من در طول زمان در مورد آن 
صحبت خواهم کرد. 
مثالی که در اینجا می زنم این است که برنامه ای را در نظر بگیرید که مردم از طریق نام 
کاربری و رمز به آن وارد شده و خارج می شوند. مجموعه افرادی که وارد شده اند یک 
مجموعه است. 
در یک برنامه سنتی شما فرضتان این است که این مجموعه تغییرپذیر است، وقتی کسی 
وارد میشود شما آن مجموعه را تغییر میدهید، و این یک مشکل بزرگ دارد، اینکه کسی به 
می زند و بعد خطای تغییر foreach نسخه قدیمی آن نگاه می کند و روی آن 
می گیرد. (concurrent modification exception) همزمان 
اما آنچه که دقیقا اتفاق می افتد این است که شناسه ای وجود دارد چیزی که شما اسم 
روی آن میگذارید(مجموعه افرادی که وارد سیستم شده اند) که در هر لحظه ای از زمان 
ی تغییرناپذیر نمایش collection مقداری دارد، و شما هر کدام از آن مقادیر را به عنوان 
می دهید، پس تنها کاری که لازم است انجام دهید این است که مطمئن شوید که یک 
« مقدار خاص » از یک مجموعه و یک « مجموعه کاربران وارد شده » رابطه ترتیبی بین ایده
وجود دارد و این تنها به یک ساختمان داده ی اتمیک نیاز دارد، که رفرنسی به آن مقدار 
است و آن رفرنس چیزی است که محتوایش عوض میشود. 
مارکوس: اجازه دهید سعی کنم که بازگو کنم، کلوژر چیزی به اسم اتم در اختیار ما قرار 
میدهد، درست است؟ 
ریچ: این یکی از انتخابهای ممکن است. 
دور یک مقدار است، مقداری که در اتم قرار دارد می تواند wrapper مارکوس: اتم یک 
در طول زمان عوض شود، یک شناسه در اختیار شما قرار می دهد و دسترسی سریالی و 
ترتیبی را به داده داخل خودش ضمانت می کند. 
ریچ: درست است و من آن را یک سطح بالاتر می برم، اتم یکی از نمونه های انواع رفرنس 
موجود در کلوژر است، و انواع رفرنسی، همه به خاطر یک مشکل است که وجود دارند و 
آن ابزاری برای نمایش شناسه است و ابزاری برای مدیریت زمان و ترتیب وضعیت هایی 
که همراه آن شناسه است. 
مارکوس: یک مثال برای ما بزنید، چگونه کار میکند؟ 
ریچ: شما می توانید آنها را جعبه های کوچکی در نظر آورید که در داخل آن جعبه 
مقداری وجود دارد و منظور از مقدار چیزی است که تغییر نمی کند، پس مجموعه افرادی 
که وارد سیستم شده اند یک جعبه است و در هر زمانی داخل جعبه یک ساختمان داده 
تغییرناپذیر وجود دارد و وقتی که میخواهید یک کاربر اضافه کنید، شما آن مقدار
تغییرناپذیر را می گیرید و تابعی روی آن فراخوانی می کنید و یک مقدار تغییرناپذیر دیگر 
تولید میکند که همان مجموعه به اضافه کاربر جدید است و این مقدار جدید را داخل جعبه 
می گذارید. 
مارکوس: اگر دو نفر همزمان از دو نخ اجرایی اینکار را انجام دهند، مشکل همزمانی 
برای شما رخ خواهد داد! 
ریچ: مگر اینکه این انواع رفرنس معانی همزمانی را با خود داشته باشند. این کار 
آنهاست. نکته این است که شما دو مشکل را مجزا ببینید، ما دیگر در مورد مشکل تغییر 
و قرار دادن یک چیز جدید در آن صحبت نمی کنیم. اینها توابعی هستند collection یک 
که روی مقادیر کار می کنند، چیزی که باقی می ماند این است که ما چگونه از یک 
وضعیت به وضعیت بعدی میرویم (که هر وضعیت یک مقدار دارد) بدون اینکه با هم برخورد 
کنیم. 
این موضوع چگونه به نظر می رسد؟ API مارکوس: از نظر 
ریچ: همه انواع رفرنس یک شکل دارند، و یک مدل یکتا برای تغییر وضعیت وجود دارد. 
بدین شکل که شما یک رفرنس دارید که مقداری درخود دارد، شما برای آن رفرنس یک تابع 
میفرستید که تابع مربوط به آن مقداری است که داخل رفرنس است که ممکن است این 
تابع آرگومانهای دیگری هم داشته باشد، نوع رفرنس مسئول این است که تابع را بگیرد، 
آن را به مقدار داخلش اعمال کند و حاصل عملیات را به عنوان وضعیت بعدی خودش قرار 
دهد.
مارکوس: رفرنس اطمینان میدهد که تنها یک نفر اینکار را در لحظه انجام می دهد 
ریچ: در نتیجه شما باید توابع درجه یک را در زبان داشته باشید تا بتوانید آن تابع را به 
متقاوتی برای این (semantic) عنوان آرگومان برای کس دیگری بفرستید، سپس معانی 
دارید که این تغییر کی و چگونه اتقاق می افتد. تغییر می تواند همزمان یا ناهمزمان 
باشد (همان لحظه اتفاق بیافتد یا بعدا)، شما می توانید بخواهید تابع اعمال شود و 
زمانی که انجام شد شما باخبر شوید یا اینکه می توانید بگویید اینکار را بعدا انجام بده 
و به کارتان ادامه دهید. 
تفاوتهایی اینجا وجود دارد، تفاوتهایی در این وجود دارد که آیا این تغییری که قصد انجام 
آن را دارید یک رفرنس را متاثر می کند یا شامل هماهنگی برای تغییر چند رفرنس است. 
دیگر هم دارید که اینکار هماهنگی را انجام می دهد! wrapper مارکوس: پس شما یک 
متفاوتی دارند ما در اینجا (semantic) ریچ: رفرنس های متفاوتی وجود دارد که معانی 
در مورد سه گونه از آنها صحبت خواهیم کرد، اتم ها ساده ترین شکل هستند، آنها 
هستند و اتمیک هستند یک واحد کاری می تواند تنها شامل یک اتم در synchronous 
ها، مانند اتم ها هستند، اتمیک هستند و یک واحد کاری می تواند agent ، آن واحد باشد 
هستند، زمانی که asynchronous در آن واحد باشد ولی آنها agent تنها شامل یک 
یک تابع را می فرستید، آن تابع در آینده اعمال خواهد شد و کنترل agent برای یک 
آن تابعی را که برای او فرستاده شده از agent بلافاصله به برنامه شما بر میگردد، و 
پردازش میکند اما ضمانت می کند که این عملیات (thread pool) طریق استخر نخ ها 
به ترتیب انجام خواهد شد. 
ها تنها در تراکنش ها تغییر می کنند و ref ، است ref و نهایتا پیچیده ترین نوع رفرنس 
هستند، پس شما می (coordinated) و هم هماهنگ شده synchronous آنها هم
باشد، چیزی که مثلا زمانی به آن ref توانید یک واحد کاری داشته باشید که شامل چند 
نیاز دارید که بخواهید آیتمی را از یک دسته درآورده و به دسته دیگری اضافه کنید. 
را در آن تغییر می دهید. ref مارکوس: پس برای اینکار یک تراکنش باز می کنید و هر دو 
ریچ: این سیستم خوبی است چرا که شما همه عملیات را به توابع محض برده اید و اگر 
بخواهید تابعی را تست کنید که مثلا آیتمی را به دسته ای اضافه میکند شما نیازی به 
کردن چیزی ندارید، وضعیتی در آن تابع نخواهید داشت، و به آن نیازی ندارید، mock 
یک تابع محض دارید. پس تست این تابع بسیار ساده خواهد بود چون چیزی در مورد 
تغییر وضعیت در آن نیست. سپس شما مساله دیگری خواهید داشت و آن این است که 
فرستادم می خواهم مطمئن باشم که در محیط ref حالا که من یک تابع را برای یک 
همزمان به صورت امنی اجرا خواهد شد. این دو مساله از هم مجزا شده اند، می توانید 
همه این معانی متفاوت را شبیه هم کنید، مدل تغییر وضعیت، ارسال یک تابع به رفرنس ها 
همه یکی هستند. 
مارکوس: یکی از چیزهایی که این روز ها در مورد کلوژر صحبت می شود در مورد همین 
موضوع است: حافظه تراکنشی. 
ها از این طریق پیاده سازی شده اند، بله. ref ، ریچ: آخرین نوع انواع رفرنس ها
مارکوس: ما قبلا در مورد حافظه تراکنشی برنامه ای داشته ایم هرچند شماره آن را به 
خاطر نمی آورم. 
ریچ: باید بگویم که رویکرد کلوژر به حافظه تراکنشی نرم افزاری بسیار متفاوت است از 
آنچه که در مقالات یا گفتگوها دیده اید، افراد زیادی روی این موضوع کار کرده اند با این 
هدف که به شما اجازه دهند کد موجودتان را نگه دارید (که آبجکت های تغییرپذیر را 
دستکاری می کند) اما آن عملیات را در یک تراکنش قرار دهید و نیازی به استفاده از قفل 
ها نداشته باشید. 
من شخصا طرفدار چنین رویکردی نیستم و فکر می کنم این روش نمی تواند کار را 
انجام نمی دهد، روش کلوژر بسیار متفاوت است، اینجا ما روی برنامه نویسی با مقادیر 
ها پس اندازه aggregate تاکید داریم، استفاده از توابع محض، استفاده از مقادیر برای 
و از روش کنترل (coarse granularity) ای که ما با آن کار می کنیم بزرگتر است 
همزمانی مبتنی بر چند نسخه ای بودن در لایه های زیرین استفاده می کند، پس کاملا 
متفاوت است. 
مارکوس: شما این واقعیت را آشکار کردید که می توان بعضی مقادیر را در داخل تراکنش 
ها تغییر داد، پس شما تلاشی برای شفاف کردن انجام نمی دهید. 
ریچ: نه، شفافیت در این مورد چیز خوبی نیست. 
مارکوس: موافقم.
مارکوس: می خواهم حرف دهن شما بگذارم، با فرض اینکه پشتیبانی موجه از زمان، 
مقدار، شناسه و همزمانی دلایل اصلی برای ساختن کلوژر بوده اند. آیا اینکار با اضافه 
کردن یک کتابخانه یا فریم ورک به یک زبان موجود ممکن نبود؟ 
به عبارت دیگر چرا چنین چیزهایی نیاز به پشتیبانی شدن در سطح یک زبان نیاز دارند؟ 
ریچ: در واقع کلوژر یک کتابخانه است، یک کتابخانه است که به جاوا نوشته شده است و 
می توان از آن در جاوا استفاده کرد. 
و (idiomatic) موضوع زبان این است که باعث می شود استفاده از این مفاهیم طبیعی 
STM(Software راحت باشد، شما می توانید دقیقا از همین انواع رفرنس و 
و ساختمان داده های کلوژر در جاوا استفاده کنید. Transactional Memory) 
را در کلاس anonymous مارکوس: بله اما شما تلف می شوید اگر بخواهید این همه 
ها به عنوان تابع تعریف کنید. 
ریچ: در مورد توابع، عدم پشتیبانی کتابخانه هایی که به صورت طبیعی بتوان با استفاده 
از مقادیر برنامه نوشت، باید مقادیر بازگشتی را به متغییر دیگری انتساب دهید، این 
ها و پشتیبانی زبان بدین معنی idiom روش طبیعی انجام کار نیست، پس عدم وجود 
است که شما باید از همان کدهای زیربنایی جاوا استفاده کنید و این بسیار سخت 
خواهد بود در مقایسه با کلوژر، جایی که همه اینها عملکرد طبیعی سیستم است، و این 
کاری است که شما به صورت پیش فرض در کلوژر انجام میدهید، زمانی که شما برنامه 
کلوژر می نویسید و از این ساختمان داده ها استفاده می کنید همواره دارید به این روش 
برنامه می نویسید. این چیزی نیست که شما بعدها مجبور به انجام آن شوید، و این چیز 
خوبی است چرا که وقتی نیاز و علاقه به همزمانی را متوجه شوید لازم نیست چیزی را 
تغییر دهید، شما پیشتر کار درست را انجام داده اید.
مارکوس: من تعریف شما از زبان را بسیار پسندیدم، چرا که من همواره با آن دست به 
ها کار میکنم و افراد همیشه از من می پرسند که تفاوت میان زبان و DSL گریبانم، من با 
چیست، چرا من به یک زبان نیاز دارم وقتی که می توانم همه چیز را با دستوراتی API 
و … بیان کنم. نکته این است که می خواهیم مفاهیم طبیعی باشند و بیان Insert مانند 
درست آنها ساده باشد، این یک تعریف بسیار خوب است. 
ریچ: بله و به همین دلیل است که همه این اجزای مستقل کلوژر با هم طراحی شده اند 
طوری که همه این جنبه ها با هم خوب کار کنند. 
مارکوس: آخرین سوال فنی قبل از اینکه بخواهیم در مورد استقبال از زبان و اجتماع 
کاربران کلوژر صحبت کنیم، یکی دیگر از روشهای مدیریت وضعیت در زبانهای تابعی 
در این باره حرف Eric Meyer با se-radio است، فکر می کنم قبلا در Monad دیگر 
زده ایم، آیا این موضوع در کلوژر نقشی دارد؟ 
مساله مربوط Monad ریچ: کتابخانه هایی برای اینکار وجود دارد، اما من فکر می کنم 
برای مساله Monad به شناسه ها را به صورت مبنایی حل نمی کند، شما نمیتوانید از 
مجموعه کابران وارد شده به سیستم استفاده کنید (برنامه ای که در طول زمان زیادی در 
Haskell حال اجرا بوده و اجزای مختلف برنامه درگیر بوده است)، و به همین خاطر 
است. اینها را دارد چون این روشی است که می توانید چند نخ MVar و STM دارای 
برای حالتی است که تنها یک نخ کنترل Monad ، کنترل مستقل را با هم هماهنگ کنید 
دارید. 
ربطی به همزمانی ندارد. Monad مارکوس: بله
نمی توانید از یک ساختار مشابه برای هر دو کار استفاده Haskell ریچ: پس شما در 
کنید، مطمئن نیستم که آیا همیشه این ساختار صحیحی خواهد بود. به علاوه با وجود 
بسیار Haskell اینکه کتابخانه هایی برای کلوژر برای اینکار وجود دارد، این مفهوم در 
که دارد. (type system) قوی تر است به خاطر سیستم انواعی 
آگاه است، پس Monad مارکوس: شاید این سوال من باشد، آیا سیستم انواع شما از 
پاسخ خیر است و استفاده از آن طبیعی به نظر نمی رسد! 
ریچ: بله همینطور است، اما با ماکروها مشکل حل میشود، نکته اصلی این است که 
قابلیت استنتاج انواع روی انواع برگشتی توابع را دارد و این یک ویژگی Haskell 
است. Monad بسیار مهم برای 
مارکوس: کلوژر دارای انواع دینامیک است، درست است؟ پس شما نمی توانید استنتاج 
را انجام دهید، درست است؟ Monad نوع 
ریچ: خوب، کلوژر استنتاج محلی انجام می دهد، برای مثال برای اینکه کد جاوا را بدون 
فراخوانی کرد، ما نیاز داریم که انواع را بدانیم. (reflection) استفاده از بازتاب 
اما در کلوژر (به نسبت جاوا) شما خیلی کمتر به انواع نیاز دارید، چرا که اگر کمی 
اطلاعات پیدا کند، قادر خواهد بود انواع حاصله این عبارت و فراخوانی را استنتاج کند 
که خود می تواند ورودی یک فراخوانی دیگر باشد و در نتیجه انواع ورودی آن فراخوانی را 
نیز استنتاج کرده است. 
(-: ؟(duck typing) مارکوس: پس آیا دارای سیستم انواع ایستا است یا مرغابی گونه 
ریچ: اینها انتخاب های صفر و یکی نیستند.
مارکوس: اگر استنتاج انواع توسط کامپایلر انجام میشود پس مرغابی گونه نیست. 
این سیستم، ایستا است که استنتاج انواع هم به آن تزریق شده است. 
ریچ: تفاوت اینها به اجبار کردن این قواعد برمی گردد، اگر بتوانم انواع را استنتاج کنم از 
آن برای تولید کد بهتر استفاده می کنم در غیر اینصورت آن را غیر مجاز نمی دانم که 
بدین معنی است که شما کد بازتابی خواهید داشت که در زمان اجرا ممکن است متوجه 
شود که اصلا متدی با آن اسم وجود ندارد. 
مارکوس: آهان! پس بدین معنی است که می توانید اطلاعات مربوط به انواع را در کلوژر 
تعیین کنید و اگر این اطلاعات موجود باشد آن کد کامپایل می شود برخلاف حالتی که کد 
بازتابی تولید میشود. 
ریچ: شما باید خیلی دقیق باشید چرا که این کد کامپایل میشود و دقیقا عین جاوا اجرا 
می شود. در مقابل کد شما مجاز به پذیرفتن انواع مختلف نخواهد بود، این تنها 
مکانیسمی برای بهینه سازی است نه برای رد کردن برخی عبارات اجرایی. این کار 
بررسی و اطمینان از صحت انواع نیست. 
مارکوس: ولی اگر این اطلاعات را فراهم کنید کد بهتری تولید خواهد شد. 
ریچ: و به درد تعامل با جاوا هم می خورد. 
مارکوس: آیا موضوع فنی ای در مورد زبان وجود دارد که من فراموش کرده باشم بپرسم و 
شما دوست داشته باشید در مورد آن صحبت کنید؟
ریچ: فنی؟ 
مارکوس: بله مثلا یک ویژگی جالب زبان یا … 
ریچ: نه، در درون کلوژر بسیار بسیار ساده است، و در واقع این یکی از چیزهایی است 
که من می خواهم افراد در مورد کلوژر بدانند که از نظر فرم محاسباتی بی نهایت ساده 
است، قواعد زیادی وجود ندارد، قواعد نحوی زیادی وجود ندارد، مخصوصا در مورد نحو، 
زبان فوق العاده ساده است. 
مارکوس: خوب، بیاید در مورد موضوعات نرم صحبت کنیم، استقبال و پذیرش کلوژر در 
در طول دو سه سال اخیر آمده اند، چگونه JVM زبانهایی که روی (zoo بازار(به جای 
بوده است؟ 
ریچ: به صورت قابل توجه ای خوب عمل کرده است با توجه به اینکه جدیدترین زبانی است 
که به این مجموعه اضافه شده است، لیست ایمیل گوگل دارای ۳۳۰۰ عضو است، این 
خیلی چشمگیر است، پذیرش و استفاده از زبان، افراد شغل هایی تحت این عنوان پیدا 
می کنند، شرکت ها از آن استفاده می کنند، با شرکت های نوپا شروع شد اما الان 
کاربردهایی در زمینه های دیگر مانند تحلیل و دیگر جاهای متفاوت می بینیم. 
مارکوس: آیا سناریوی استفاده معمولی و عمومی ای دارد؟ جایی که استفاده از کلوژر 
واقعا مناسب است؟ 
ریچ: می دانید، یکی از بزرگترین چیزها برای من این بوده که زبان طوری طراحی شده که 
همه کاره باشد و در زمینه های بسیار گوناگونی موارد استفاده ی مختلفی داشته است.
یکی از زمینه هایی که اگر بخواهم به عنوان یک زمینه داغ و پرطرفدار نام ببرم، استفاده 
برای کار یادگیری ماشین بوده است که روی خوشه ای از FlightCaster شرکت 
اجرا می شود، و کتابخانه هایی وجود دارد برای یکپارچه شدن با دیگر Hadoop 
این زمینه الان داغ است جایی که اکثرا ،encounter کتابخانه های آماری کلوژر به اسم 
استفاده می شده است که آن را به برنامه نویس می داده اند تا آن R به صورت سنتی از 
را به محیط عملیاتی ببرد، حال می توانند از کلوژر استفاده کنند برای اینکه با داده های 
حجیم کار کنند و مدلی را که بدست می آورند می توانند مستقیما در محیط عملیاتی مورد 
استفاده قرار دهند. این زمینه ای است که ترکانده است (-: اما برای برنامه نویسی وب و 
پایگاه داده ها و سیستم های انتقال پیغام نیز به کار می رود. 
مارکوس: اما می توان گفت که توان خود را جایی نشان می دهد که نیاز باشد الگوریتم 
های غیر جزیی و سنگینی به صورت همزمان اجرا شود. 
ریچ: می تواند اینطور باشد اما شاید بتوانید متوجه شوید که امکانات مربوط به برنامه 
نویسی همزمان کلوژر کمتر از آنچه فکر می کنید به کار گرفته شده است، نمی خواهم 
بگویم که این امکانات صرفا فوت و فن هستند، این زبان بسیار بیان راحتی دارد و با اکو 
سازگاری دارد پس حجم عظیمی از کتابخانه ها وجود دارد که می توانید JVM سیستم 
از آنها بهره ببرید و افراد بدین واسطه بسیار سریعتر و کارآمدتر برنامه می نویسند، و 
این مهم است. 
است. Stuart Halloway مارکوس: کتاب هم دارد که نویسنده آن 
ریچ: بله.
Manning دو کتاب دیگر هم در راه است، می توانید دسترسی زودهنگام آنها را از 
است. Joy of Clojure است و دیگری Clojure in Action دریافت کنید، یکی 
مارکوس: آیا شما در آنها دخیل بوده اید؟ 
ریچ: نه. 
مارکوس: تعجب کردم. 
ریچ: من مشغول کلوژر هستم. 
شاید یک وقتی اینکار را بکنم اما الان خیلی مشغله دارم. 
مارکوس: به نظرم این نشانه خوبی است. 
ریچ: اجتماع برنامه نویسان عالی است، لیست ایمیل بزرگ است و بگذارید نگاه کنم ۲۳۰ 
حضور دارند، اینها همه معیارهایی هستند، کمک گرفتن از دیگران کار IRC نفر در 
راحتی است، افراد عمدتا دوستانه برخورد می کنند، شروع آسان است. 
مارکوس: خیلی خوب است. 
پس تنها مشکل پیدا کردن مشتری است لااقل برای من اینطور است. که بخواهد از کلوژر 
استفاده کند به جای زبانهای اصلی. که به نظرم در بعضی محیط ها همچنان یک چالش 
است که افراد را قانع کرد.
ریچ: فقط به آنها بگویید که تنها می خواهیم از یک کتابخانه جاوا استفاده کنیم که نام آن 
است. jar کلوژر است، مانند همه کتابخانه های دیگر یک فایل 
پذیرش سطوح مختلفی در صنایع مختلف دارد، بستگی به سطح محافظه کاری دارد و 
اینکه دارند چه کار می کنند، اما جالب است که می بینیم به صورت گسترده ای به کار 
گرفته میشود. 
ها، برجسته کننده نحو زبان و … IDE ، مارکوس: ابزار برنامه نویسی آن چطور است 
اگر که آن را می پسندید، به صورت Emacs ، ریچ: قطعا. در واقع بسیار خوب است 
های سنتی خوشتان IDE سنتی جای مناسبی برای برنامه نویسی لیسپ است، اگر از 
Enclosure بسیار خوب پشتیبانی می کند، پروژه ای که نام آن Netbeans ، می آید 
است، کامل کردن کد برای کلوژر و جاوا را دارد، یکپارچگی بسیار خوبی با جاوا دارد، 
Intellij قرار گرفته است، به همین شکل IDE آن در REPL ، برجسته کننده نحو دارد 
آن را Intellij خوب از کلوژر پشتیبانی می کند، نوع پروژه کلوژر وجود دارد، بچه های 
هم به تازگی از Eclipse ، درست کرده اند، و کارشان را بسیار خوب انجام داده اند 
کلوژر حمایت می کند، خلاصه کلی انتخاب وجود دارد. 
مارکوس: شما اگر این سه تا را داشته باشید پس دیگر مشکلی وجود ندارد. 
مشترک است پس همه ابزار های JVM ریچ: بله و البته کلوژر در زیرساخت بایت کد با 
رفع خطا و بررسی عملکرد جاوا برای کلوژر هم کار خواهند کرد. 
مارکوس: در سطح سورس کد؟ 
ریچ: بله.
مارکوس: خوب این همه چیزی بود که من آماده کرده بودم، چیزی برای اضافه کردن 
دارید؟ 
اگر IRC ریچ: نه فقط می خواهم که افراد آن را امتحان کنند، و به گروه گوگل بپیوندند و 
کمک می خواهید. 
مارکوس: خوب از اینکه در این برنامه حضور یافتید متشکرم. 
ریچ: از دعوت شما ممنونم.

More Related Content

Similar to Clojure se-radio.net Interview with Rich Hickey (ترجمه مصاحبه رادیو مهندسی نرم افزار با ریچ هیکی )

How to be a better Developer & Programmer
How to be a better Developer & ProgrammerHow to be a better Developer & Programmer
How to be a better Developer & ProgrammerReza Razavi
 
چرا نود.جی اس؟
چرا نود.جی اس؟چرا نود.جی اس؟
چرا نود.جی اس؟Masoud Sharifi
 
Oracle نوشته مهندس اسمعیل دخت
Oracle  نوشته مهندس اسمعیل دختOracle  نوشته مهندس اسمعیل دخت
Oracle نوشته مهندس اسمعیل دختYashar Esmaildokht
 
Java programming languages
Java programming languagesJava programming languages
Java programming languagesjavadib
 
(ِData Structures-Java Object oriented Programming Languages)ساختارهای دیتا ...
 (ِData Structures-Java Object oriented Programming Languages)ساختارهای دیتا ... (ِData Structures-Java Object oriented Programming Languages)ساختارهای دیتا ...
(ِData Structures-Java Object oriented Programming Languages)ساختارهای دیتا ...Muhibullah Aman
 
Scalable javascript application - طراحی نرم افزارهای مقیاس پذیر با جاوا اسکریپت
Scalable javascript application -  طراحی نرم افزارهای مقیاس پذیر با جاوا اسکریپتScalable javascript application -  طراحی نرم افزارهای مقیاس پذیر با جاوا اسکریپت
Scalable javascript application - طراحی نرم افزارهای مقیاس پذیر با جاوا اسکریپتefazati
 
مقایسه دو زبان جاوا و لیسپ درس پی ال
مقایسه دو زبان  جاوا و لیسپ درس پی المقایسه دو زبان  جاوا و لیسپ درس پی ال
مقایسه دو زبان جاوا و لیسپ درس پی الAli Ghaeni
 
Load Balancing-as-a-Service (LBaaS) with octavia in openstack
Load Balancing-as-a-Service (LBaaS) with octavia in openstackLoad Balancing-as-a-Service (LBaaS) with octavia in openstack
Load Balancing-as-a-Service (LBaaS) with octavia in openstackYashar Esmaildokht
 

Similar to Clojure se-radio.net Interview with Rich Hickey (ترجمه مصاحبه رادیو مهندسی نرم افزار با ریچ هیکی ) (20)

How to be a better Developer & Programmer
How to be a better Developer & ProgrammerHow to be a better Developer & Programmer
How to be a better Developer & Programmer
 
C++
C++C++
C++
 
C++
C++C++
C++
 
Object-Oriented-Programming-in-Python
Object-Oriented-Programming-in-PythonObject-Oriented-Programming-in-Python
Object-Oriented-Programming-in-Python
 
Rbdmap ceph realease 0.2
Rbdmap ceph realease 0.2Rbdmap ceph realease 0.2
Rbdmap ceph realease 0.2
 
چرا نود.جی اس؟
چرا نود.جی اس؟چرا نود.جی اس؟
چرا نود.جی اس؟
 
Java script
Java scriptJava script
Java script
 
Oracle نوشته مهندس اسمعیل دخت
Oracle  نوشته مهندس اسمعیل دختOracle  نوشته مهندس اسمعیل دخت
Oracle نوشته مهندس اسمعیل دخت
 
how upgrade ceph
how upgrade cephhow upgrade ceph
how upgrade ceph
 
OpenStack and its service
OpenStack and its serviceOpenStack and its service
OpenStack and its service
 
Java programming languages
Java programming languagesJava programming languages
Java programming languages
 
(ِData Structures-Java Object oriented Programming Languages)ساختارهای دیتا ...
 (ِData Structures-Java Object oriented Programming Languages)ساختارهای دیتا ... (ِData Structures-Java Object oriented Programming Languages)ساختارهای دیتا ...
(ِData Structures-Java Object oriented Programming Languages)ساختارهای دیتا ...
 
Docker
DockerDocker
Docker
 
Scalable javascript application - طراحی نرم افزارهای مقیاس پذیر با جاوا اسکریپت
Scalable javascript application -  طراحی نرم افزارهای مقیاس پذیر با جاوا اسکریپتScalable javascript application -  طراحی نرم افزارهای مقیاس پذیر با جاوا اسکریپت
Scalable javascript application - طراحی نرم افزارهای مقیاس پذیر با جاوا اسکریپت
 
مقایسه دو زبان جاوا و لیسپ درس پی ال
مقایسه دو زبان  جاوا و لیسپ درس پی المقایسه دو زبان  جاوا و لیسپ درس پی ال
مقایسه دو زبان جاوا و لیسپ درس پی ال
 
لیبره‌آفیس
لیبره‌آفیسلیبره‌آفیس
لیبره‌آفیس
 
لیبره‌آفیس
لیبره‌آفیسلیبره‌آفیس
لیبره‌آفیس
 
Network management 2_sample
Network management 2_sampleNetwork management 2_sample
Network management 2_sample
 
Openstack Rally
Openstack RallyOpenstack Rally
Openstack Rally
 
Load Balancing-as-a-Service (LBaaS) with octavia in openstack
Load Balancing-as-a-Service (LBaaS) with octavia in openstackLoad Balancing-as-a-Service (LBaaS) with octavia in openstack
Load Balancing-as-a-Service (LBaaS) with octavia in openstack
 

Clojure se-radio.net Interview with Rich Hickey (ترجمه مصاحبه رادیو مهندسی نرم افزار با ریچ هیکی )

  • 1. مصاحبه ریچ هیکی سازنده کلوژر با رادیو مهندسی نرم افزار (jzinedine@gmail.com) ترجمه: جهانگیر زین الدین صحبت کنیم. مهمان ما آقای کلوژر، Clojure مارکوس: این بار ما می خواهیم در مورد ریچ هیکی است. لطفا قبل از صحبت در مورد آنچه که ساخته اید، در مورد خودتان حرف بزنید. ریچ: خوب من ریچ هیکی هستم و کلوژر را نوشته ام، یک زبان برنامه نویسی دینامیک که محیط اجرایی مربوط به دات نت) اجرا می شود، چهار ویژگی اصلی )CLR و JVM روی میزبانی VM دارد، یک زبان مبتنی بر لیسپ است و طوری طراحی شده که توسط یک .JVM شود، بنابراین رابطه نزدیکی با پلتفرم میزبان دارد مانند مبتنی بر توابع) است و روی تغییر ناپذیری و توابع محض و ) functional عمدتا ساختمان داده های تغییر ناپذیر تاکید دارد، همچنین روی همزمانی متمرکز است. تمام جنبه های زبان طوری طراحی شده اند که در متن یک برنامه همزمان درستی داشته باشند. (semantic) معنای مارکوس: بعدا در مورد آن بیشتر کنکاش خواهیم کرد. می خواهم خوانندگان بدانند که ما قبلا برنامه ای در مورد لیسپ داشته ایم، برنامه شماره ۸۴ با گابریل. همچنانکه ما ممکن است در مورد مقدمات لیسپ به صورت مختصر صحبت کنیم، اما به خاطر ضیق وقت بنا نداریم اینجا معرفی کاملی از لیسپ ارایه کنیم. اگر با لیسپ آشنا نیستید لااقل به صورت کلی می بایست به برنامه ۸۴ رجوع کنید. ریچ، علیرغم این به نظرم فکر خوبی است اگر لیسپ را به صورت اجمالی معرفی کنید. مبانی اصلی لیسپ چه هستند، چه تفاوتی با زبانهای برنامه نویسی دیگر دارد که به خاطر آن از نظر بسیاری افراد یک زبان خاص تلقی میشود.
  • 2. ریچ: خوب، سوال آخر احتمالا بهترین سوال است، بسیاری از چیزها که لیسپ ابداع کرده است در زبان های دیگر نیز به صورت گسترده وجود دارد. فکر می کنم آنچه که لیسپ را منحصر به فرد می کند، این است که برنامه به صورت ساختمان داده به کامپایلر عرضه می شود، پس کامپایلر لیسپ متن را کامپایل نمی کند بلکه ساختمان داده ها را کامپایل می کند، و زمانی که شما با لیسپ(کلوژر) برنامه ای می نویسید در واقع با ساختمان داده ها و از طریق آنها برنامه می نویسید. اگر شما متنی را در فایلی ذخیره می کنید در واقع داده های عینی را ذخیره می کنید. می سازند که AST پس تفاوت این با زبانهایی که برنامه را ترجمه می کنند و از روی آن به نوعی یک ساختمان داده است که به کامپایلر عرضه میشود، چیست؟ از چیزهایی ساخته شده که برنامه AST این موضوع خیلی مرتبط است با اینکه آیا آن شما معمولا با آن سر و کار دارد، در یک برنامه لیسپ و به طور خاص در کلوژر، داده های عینی چیزهایی هستند که شما به صورت روزمره از انها استفاده می کنید. پس کتابخانه بزرگی برای کار با آنها وجود دارد، آنها کتابخانه ،list و map ،vector نیستند بلکه کتابخانه های معمولی متعلق به زبان هستند، AST های خاصی برای کار با بنویسید. AST که بدین معنی است که لازم نیست برنامه خاص یا عجیبی برای دستکاری هر دو یک (meta programming) مارکوس: پس برنامه نویسی و فرا-برنامه نویسی چیز هستند! ریچ: دقیقا، تفاوتی وجود ندارد، و این بسیار مهم است، اگر شما قبلا با کتابخانه ای API کار کرده باشید که شی گرا بوده باشد، می فهمید که دارید یک AST مربوط به خاص را می خوانید، اما زمانی که کد مربوط به یک ماکرو را در لیسپ یا کلوژر می خوانید کدهای کاملا معمولی برای پردازش دادها هستند.
  • 3. مارکوس: خوب شما از چه ساختمان داده های دیگری استفاده کرده اید که پیشتر در مورد آنها صحبت کردید، چون لیسپ به نظر فقط لیست های تو در تو است، درست است؟ ریچ: این برای لیسپ به صورت سنتی درست است، اما در کلوژر چندین ساختمان داده دیگر وجود دارد که همگی در اولویت بالایی قرار دارند و مانند لیست درجه یک محسوب .(hash table) که شبیه جداول درهم سازی است map و vector ، می شوند در نحو زبان فرم هایی وجود دارند که بر مبنای همین ساختمان داده ها ساخته شده اند، ها. map ها و گاهی vector گاهی مبتنی بر مارکوس: شما می دانید و در برنامه ۸۴ هم آمده که لیسپ زبان جدیدی نیست و یک رویکرد قدیمی است و در زمینه های خاصی با موفقیت مورد استفاده قرار کرفته است اما هیچگاه یکی از زبانهای اصلی مورد استفاده عموم نبوده است. شما چه فکری می کنید، چرا این اتفاق نیافتاده است؟ و سوال بعدی اینکه چرا شما در سال ۲۰۰۹ یا ۲۰۱۰ لیسپ خودتان را ساختید؟ ریچ: هاها، اینها دو سوال مجزا هستند، من مطمئن نیستم که لیسپ برای استفاده عموم طراحی شده باشد، آن زمان که بوجود آمده برای کاربران ارشد طراحی شده مانند محققین و افراد بسیار باهوش که سعی می کردند مسایل بسیار سخت را حل کنند و لیسپ کاملا اهرم مناسبی برای تلاشهای آنها بود. به عنوان یک فرد شما قدرت باورنکردنی ای به واسطه لیسپ داشتید. ما همه می دانیم که برنامه نویسی در مقیاس بزرگ یک فعالیت اجتماعی است که افراد دیگری هم در آن درگیر هستند، کتابخانه های برنامه نویسی در آن دخیل هستند و به طور خاص بسیار مهم است که بتوانید با کتابخانه هایی که دیگران به همان زبان یا به زبان دیگری نوشته اند تعامل کنید. این یکی از زمینه هایی است که لیسپ به طور سنتی در آن خوب عمل نکرده است چون این محدوده ها و رویکردها بیشتر شبیه جزیره اند، جزیره هایی با درختها و مناظر زیبا،
  • 4. اما به خوبی به جاهای دیگر دنیا وصل نیستند. عوامل اجتماعی و تاریخی دیگری وجود دارند که مربوط به هوش مصنوعی هستند، مرگ آن در دهه ۸۰ و ۹۰ که با عدم اقبال به لیسپ همراه شد، اما لیسپ قدرتش را از دست نداد، برای اینکه به سوال دوم شما برسم، که چرا من امروز اینکار را کرده ام؟ ویژگی دومی که لیسپ دارد هنوز منحصر به فرد است چون برنامه ها همان ساختمان داده ها هستند شما می توانید برنامه هایی بنویسید که آن برنامه ها به نوبه خود برنامه بنویسند. و جنبه مهم دیگر لیسپ این است که وقتی کامپایلر لیسپ برنامه شما را ارزیابی می کند، به ماکروها که برنامه های کوچک دیگری هستند اجازه می دهد در حین کامپایل اجرا شوند که بدین معنی است که برنامه های شما که برنامه می نویسند، می توانند با کامپایلر یکپارچه شوند. مارکوس: فکر می کنم این یک خاصیت بسیار مهم است، چون چندان سخت نیست که استفاده کند که یک برنامه جاوا تولید کند، Eclipse AST API برنامه ای نوشت که از شاید به اندازه کلوژر راحت نباشد هر چند این موضوع سلیقه ای است، اما اینکه قادر باشید آنرا در فرآیند تبدیل یا کامپایل اضافه کنید باعث می شود این کار بسیار بی دردسر و یکپارچه باشد و این مهم است. ریچ: درست است، این ویژگی ای را مهیا میکند که موسوم به گسترش پذیری نحو است که چیز قدرتمندی است و برای برنامه ها مهم (syntactic extensibility) زبان است، همانطور که انتزاع تابع مهم است، ما نمی خواهیم یک چیز را چندین بار بنویسیم، می خواهیم یکبار بنویسیم و از آنها استفاده مجدد کنیم. الگوهای زیادی در نرم افزار وجود دارد که به درستی توسط آبجکت ها و متدها کپسوله نمی شود، مثال ساده در جاوا است، الگوهایی که شما مجبورید آنها را مدام تکرار کنید چون ابزاری برای try بلوک کد کپسوله کردن آن ندارید که از آن طریق تکرار را از بین ببرید. به نظر من این امکان چیز بسیار ارزشمندی است و هنوز ارزش دنبال کردن دارد. کاری که من می خواستم انجام دهم ساختن لیسپی بود که نکات قوتش پا بر جا باشد اما مشکل
  • 5. جزیره بودن آن را حل کند. کلوژر چون یک زبان میزبانی شده است و روی جزییات پیاده سازی نشده است مانند یک ویژگی است و در دسترس است بدین معنی است که به عنوان یک زبان جدید به تمام کتابخانه های جاوا دسترسی کامل دارد و توان بالایی برای تعامل با برنامه های جاوا دارد و شما بلافاصله از جزیره بودن رها شده اید. مارکوس: من بعدا به این موضوع بر میگردم اما الان می خواهم مختصر در مورد فرا- صحبت کنم. گسترش پذیری نحو خصیصه ی (meta programming) برنامه نویسی مهمی است و مقیاس شما برای سنجش قدرت زبانهایی مانند لیسپ بود. اما اگر من بخواهم نقش وکیل مدافع شیطان را بازی کنم خواهم گفت که اصلا لیسپ نحوی ندارد، اگر همه چیز در زبان لیست است پس نمایش هر چیزی به عنوان لیست کار ساده ای است، البته که من دارم اغراق می کنم اما آنچه که می خواهم بگویم این است که این واقعیت که لیسپ از نظر نحوی قابل گسترش است و رشد می کند با وجود اینکه بسیار قدیمی است، به این خاطر است که لیست نحو و دستور زبان جزیی دارد و شاید بتوان گفت اصلا نحوی ندارد. انجام این کارها در زبانهای دیگر مانند جاوا ممکن نیست به خاطر استقلال ابزار فرا- برنامه نویسی، حال این خاصیت چقدر مهم است اگر شما بخواهید آن را توضیح دهید. ریچ: این بحث بسیار مهم است، سیستم های فرا-برنامه نویسی زیادی وجود دارند که استفاده از آنها به اندازه لیسپ ساده است، این موضوع ربطی به این ندارد که در لیسپ همه چیز لیست است، در واقع در کلوژر همه چیز لیست نیست و این موضوع مهمی است چرا که اگر همه چیز لیست است باعث میشود همه چیز پیچیده تر شود و لیست دچار سربار اضافی شود. چون نحو زبان وجود دارد اما در نمایش کاراکتر ها نیست، کاراکتر ها برای نمایش ساختمان داده ها هستند، نحو در تعبیر آن ساختمان داده ها مستتر است.
  • 6. مارکوس: نحو در سطح کلمات است. ریچ: نه بالاتر در سطح لیست ها و بردارهای تو در تو. این واقعیت که نحو زبان، ساختمان داده است و زمانی که شما مبدلی می نویسید دوباره ساختمان داده های جدیدی می سازید و اینها همان ساختمان دادهای ساده موجود و تعبیه شده در سیستم هستند باعث می شود فرا-برنامه نویسی بی نهایت ساده شود. مارکوس: شما گفتید که مخاطب لیسپ دانشمندان بودند که روی هوش مصنوعی کار می کردند، مخاطبان کلوژر چه کسانی اند؟ برنامه نویسان جاوا، لیسپ؟ ریچ: فکر می کنم هر برنامه نویسی با ذهنی به اندازه کافی باز کار کردن با لیسپ را تجربه ای جالب و هیجان انگیز خواهد یافت، تجربه من اینگونه بوده است، من بیش از یک دهه با سی پلاس پلاس و جاوا و سی شارپ کار کرده ام، لیسپ به طرز باور نکردنی ای شما را تواناتر می کند و فکر می کنم برداشت اولیه اکثرا افراد در مورد لیسپ غیر واقعی است چرا که هسته اصلی کلوژر بسیار ساده تر از جاوا است. آنچه که مشاهده میکنید این است که زبان بسیار ساده و موجز است اما بالقوه بسیار قوی تر از جاوا است. مارکوس: این بحث به خاطر این پیش می آید که هر کسی برداشتی از سادگی دارد، شما ممکن است بگویید لیسپ ساده است چرا که نحو بسیار ساده و موجزی دارد و تنها (orthogonal) شامل چند انتزاع است که پیشتر در مورد آن گفتید، ساختاری متعامد دارد، می توانید برنامه هایی بنویسید که برنامه ای بنویسند که برنامه بنویسد، اما شخص دیگری می گوید جاوا ساده است چرا که راه مشخص است و ما اجزای برنامه نویسی مشخصی داریم و ما در برهوت رها نشده ایم و در یک مسیر از پیش تعیین شده
  • 7. قرار می گیریم که ممکن است تحت عنوان سادگی تعبیر شود، نمی دانم می خواستم چه بگویم! است، وقتی شما (familiarity) ریچ: من فکر میکنم منظور اکثر افراد در آنجا آشنایی در جاوا را به او نشان می Hello World دست یک نفر را در خیابان بگیرید و برنامه دهید اگر شما واقعا بخواهید هر خط آن برنامه را برای او توضیح دهید خواهید فهمید که جاوا چقدر پیچیده است. ما فقط با آن راحتیم اما اصلا ساده نیست. اما وقتی که من در مورد سادگی لیسپ و کلوژر به صورت صحبت می کنم، منظورم سادگی نحو زبان نیست هر چند نحو ساده ای دارد منظورم عدم وجود پیچیدگی های پنهان و ضمنی است که دقیقا چیزی که ما را اذیت می کند. مارکوس: من باید بگویم که من تجربه عملی با لیسپ ندارم اما می توانم انچه را که می گویید بفهمم. دوست دارم چهار هفته ای وقت بگذارم و کار معنا داری با لیسپ انجام دهم ها داشتیم و حدود ده DSL تا تجربه کسب کنم. دو هفته پیش ما کنفرانسی در مورد صحبت DSL نفری جمع شده بودیم که در مورد ابزار و امکانات و زبانها برای ساختن مارتین فاولر را نشان داد و کدها state machine کنیم، و یکی از جمع تعدادی مثال بسیار تمیز و زیبا بود. من می فهمم شما چه میگویید اما نمی توانم آنرا به واسطه فقدان تجربه کار با لیسپ تایید و تحسین کنم و به همین خاطر است که ممکن است کمی مردد و بد بین به نظر برسم اما قصدم این نیست. ریچ: من قطعا بحث آشنایی را تایید می کنم. این یک جنبه مهم و یک مانع است که افراد باید از آن رد شوند اگر می خواهند کشف کنند که آن طرف مانع چیست و چه امکاناتی مهیاست، اما این موضوع بیشتر به آشنایی مربوط است تا به سادگی.
  • 8. مارکوس: من از همین استدلال استفاده می کنم آنگاه که می خواهم افراد را قانع کنم که استفاده کنند، شما باید باور ASCII به جای MPS Projector از ویرایشگرهای کد کنید که چمن های آن طرف سبزترند و باید این سختی را تحمل کنید. خوب کلوژر چه تفاوتی با لیسپ کلاسیک یا نرمال دارد، شما قبلا گفتید که به خوبی با یکپارچه شده است که به آن هم می رسیم اما از نظر زبان چه تفاوتهایی وجود دارد؟ VM ریچ: دو تفاوت اصلی وجود دارد، یکی اینکه در لیسپ سنتی ساختمان داده های اصلی و دیگر ساختار داده hashtable ، را دارند که همان لیست است cons تغییرپذیرند، آنها های مدرن اما همه آنها تغییرپذیرند. چون من می خواستم همه ساختمان داده های اصلی در کلوژر تغییرناپذیر باشند، به همین خاطر نمی توانستم کلوژر را بر مبنای بسازم. common lisp یا scheme همینطور و در واقع scheme زمینه بعدی تفاوت این است که لیسپ بسیار قدیمی است و Polymorphic API و Interface آنها قبل از بوجود آمدن مفاهیم مدرنی مانند به وجود آمده اند، لیسپ زمانی ارایه شد که دستورات شرطی جزو ابداعات Design کلوژر مبتنی بر یک سری انتزاعات ساخته شده است API . جدید در برنامه نویسی بود در حالی که در لیسپ سنتی توابع کتابخانه ای برای کار کردن با لیست، به صورت جدایی vector و map ناپذیری به یک ساختمان داده متصل شده اند همچنانکه توابع مربوط به ها همینطور هستند، در حالی که در کلوژر انتزاعی برای همه ساختمان داده ها وجود دارد و تمام کدهای مربوط به کتابخانه ها با توجه به این موضوع نوشته شده اند، شما می توانید فکر کنید که شبیه اینترفیس های جاوا هستند، همچنانکه واقعا در لایه های زیرین ها با sequence اینترفیس های جاوا هستند. این بدین معنی است که کتابخانه مربوط به هستند یا اینکه می توانند به صورت سری remote همه داده هایی که به صورت سری نمایش داده شوند، کار می کند. این بسیار مهم است شما حالا می توانید از کد های کتابخانه، موثرتر استفاده کنید و شما را توانمندتر می سازد. اینها دو تفاوت اصلی هستند.
  • 9. مارکوس: خواص شی گرایی دارد هر چند که این شی گرایی با آنچه ما در common lisp زبانهای اصلی دیگر می شناسیم تفاوت دارد، آیا شما هم این را دارید، می توان کلاس تعریف کرد؟ و چه تفاوتهایی با کلاس های جاوا دارند یا شاید تفاوتی ندارند؟ ریچ: شما دو کار می توانید انجام دهید، می توانید اینترفیس و کلاسهایی تعریف کنید که در واقع همان اینترفیس و کلاس های جاوا هستند و برای تعامل با جاوا ساخته شده اند و همچنین به عنوان ابزاری برای انتزاع. در نسخه بعدی مفهومی به نام پروتکل وجود دارد که شبیه اینترفیس های جاوا هستند با این مزیت که می توانید کلاس های موجود را که کنترلی روی آنها ندارید، گسترش دهید و در یک پروتکل شرکت دهید، در حالی که در اینترفیس ها شما مجبورید که کلاسی مشتق کنید. این مکانیسم اصلی انتزاع است، هر چند این شی گرا نیست اگر بخواهید از دیدگاه شی گرایی سنتی به موضوع نگاه کنید، چون اکثر افراد به آبجکت به عنوان یک چیز قابل تغییر که حاوی وضعیت هایی است فکر می کنند، هر چند کلوژر همچنان این امکان را نیز از طریق تعامل با جاوا فراهم می کند. مارکوس: پس انتزاع اصلی که شما می خواهید در کلوژر بسازید ساختمان داده ها به همراه توابعی است که روی آنها کار میکنند. ریچ: درست است، در پروتکل ها شما همچنان قادر خواهید بود مجموعه ای از توابع با اسم را به عنوان انتزاع ها تعریف کنید و رفتار چند ریختی را داشته باشید. من چند ریختی را دوست دارم و فکر میکنم شما می توانید به شی گرایی افتخار کنید که توانسته آن را خوب ارائه کند.
  • 10. مارکوس: آیا پروتکل ها به عنوان آداپتوری برای سایر ساختمان داده هایی کار می کنند که هنوز این رفتارها را به صورت مستقیم پیاده سازی نکرده اند؟ ها نیست. wrapper ریچ: آنها شبیه آداپتور ها هستند با این تفاوت که نیازی به نیست. wrapper مارکوس: پس کامپایلر اینجا حرکتی انجام می دهد که نیازی به ریچ: بله. مارکوس: این مرا به سوالی رهمنون می کند که من آنرا قبلا جواب داده ام، این زبان کامپایل می شود نه تفسیر. هم REPL ریچ: درست است در کلوژر مفسری وجود ندارد. شما لود دینامیک دارید و دارید. فقط هر چیزی در زمان لود کامپایل می شود. مارکوس: است. read-eval-print-loop مخفف REPL ریچ: بله یک رابط تعاملی است که می توان همان لحظه کد نوشت و نتیجه آنرا دید.
  • 11. مارکوس: آیا شما در مورد سرعت عملکرد کلوژر نسبت به جاوا بررسی ای انجام داده اید؟ ریچ: بله، در مورد فراخوانی متدهای معمولی سرعت به همان اندازه جاوا است، چون است، تفاوت بزرگ با جاوا در این است که در کلوژر اعداد همیشه byte code همان استفاده می کنید و این BigLong و BigInteger شده اند، پس شما همیشه از box سربار خواهد داشت، و به وضوح پیداست که عملیات ریاضی با آنها کندتر است. اما و ،long و int شما در توابع می توانید انواع داده ابتدایی جاوا را تعریف کنید مانند عملیات ریاضی با آنها به همان سرعت جاوا است. البته که طبقات متفاوتی وجود دارد چون لیسپ به صورت پیش فرض اعداد صحیح بزرگ را به انواع داده ی بزرگتر برای نگهداری نتایج عملیات تبدیل میکند(به جای سرریز شدن)، کلوژر سه نوع عملیات ریاضی روی داده های ابتدایی native ارائه می کند، یکی این است که گفته شد، دیگری عملیات انجام می دهد و سرریزی را چک می کند که استفاده از آن امن است و نوع سوم اساسا بد است و آن همانی است که جاوا انجام می دهد، جاوا سرریزی پنهانی دارد، شما اگر این را می خواهید این سریعترین است و در کلوژر در دسترس است. مارکوس: حال بیاید در مورد رویکرد کلوژر به همزمانی حرف بزنیم، چرا که اولا این روزها همزمانی عموما موضوع جالبی است علاوه بر اینکه این موضوع یکی از انگیزه های شما و از ویژگی طراحی این زبان بوده است، یکی از دلایلی که کلوژر با همزمانی جفت و جور است این است که ساختمان داده ها تغییرناپذیرند، می توانید کمی در مورد آن صحبت کنید. ریچ: بله حتما، من می خواهم دقیقا از همینجا شروع کنم، به صورت کلی رویکرد کلوژر به ساختمان داده ها، شی گرایی و همزمانی به شدت به هم پیوسته اند، و اینها همه ناشی داشته ایم. (state) از دردسرهایی است که ما در رابطه با وضعیت
  • 12. مارکوس: من فکر می کنم سخنرانی شما در مورد زمان را دیده ام، یادم نیست دقیقا در بود یا جای دیگری. QCon بود. JVM Language Summit ریچ: بله در بله این دقیقا توجیه وجود کلوژر است، حتی اگر شما همزمانی نداشته باشید، برنامه های شی گرای بزرگ با پیچیدگی رو به افزایشی دست به گریبان خواهند بود وقتی که گراف بزرگی از آبجکت های تغییرپذیر را می سازند و تلاش برای فهمیدن و به خاطر سپردن اینکه وقتی یک متد را فراخوانی می کنید چه اتفاقی رخ می دهد و اثرات جانبی آن چه ها هستند و چه تاثیراتی در کجاها دارند، بسیار سخت خواهد بود. مارکوس: آیا این فقط به این خاطر است که اتفاقات داخل سیستم اثرات جانبی دارند؟ یا شما به چیز نامعلوم یا غریب دیگری اشاره دارید؟ ریچ: نه من دارم در مورد آبجکت های تغییرپذیر حرف می زنم با این سادگی که اگر به شما یک آبجکت تغییرپذیر بدهند می توانید به عنوان یک مقدار به آن رفرنس داشته باشید؟ آیا شما می توانید مطمئن باشید که اگر بعدا دوباره به آن مراجعه کنید همان است و کسی آنرا تغییر نداده است؟ این مفاهیم در برنامه نویسی شی گرا در هم آمیخته شده اند و از این دیدگاه این مشکل بزرگی است. که این JVM Language Summit مارکوس: من می توانم به خاطر بیاورم از کنفرانس است. (state and identity) تفاوت بین وضعیت و شناسه ریچ: بله درست است.
  • 13. مارکوس: شی در طول زمان بدون تغییر باقی می ماند اما مقدار و وضعیت آن تغییر می کند. ریچ: پس اگر شما قادر باشید که آن مقادیر را نگه دارید آنگاه بخش بسیار بزرگی از بخشی که تغییر می کند) خواهد بود. )(identity) برنامه اتان مستقل از شناسه ها مارکوس: به کلام دیگر شما مقادیر را نگهداری می کنید نه شناسه ها را. ریچ: بله می توانید مقادیر را به سادگی نگه دارید و بدون نگرانی روی آنها محاسبات انجام دهید. و ما باید بیشتر اینکار را انجام دهیم، فکر می کنم وقتی ما شروع به برنامه نویسی شی گرا کردیم و کلاس ها را ساختیم و تصمیم گرفتیم که اعضای کلاس را به صورت پیش فرض قابل تغییر قرار دهیم ما بسیار بیشتر از آنچه نیاز بود تغییر داشتیم و حذف این همه امکان تغییر کار سختی خواهد بود. کلوژر رویکردی برعکس دارد و می گوید بیایید با مقادیر برنامه نویسی را شروع کنیم که تغییر نمی کنند و تا آنجایی که ممکن است با آنها کار کنیم و تنها بعد از آنکه به شناسه ها نیاز داشتیم آنگاه با آنها به صورت مستقل برخورد خواهیم کرد و تلاش خواهیم کرد که تصمیمات متعامد و صحیحی درباره موضوعات اتخاذ کنیم. پس با برنامه نویسی از طریق مقادیر شروع می کنیم، که به سوال اول شما برمیگردد که چگونه می خواهید چیزهای بزرگتر از اعداد و رشته ها را به صورت مقدار نمایش دهید، شما به ساختمان داده های کارآمدی نیاز دارید که به ها را به صورت مقدار نمایش دهید یا حتی چیزهای کوچکتر مانند collection طور مثال آبجکت ها، برای همین کلوژر مجموعه ای از ساختمان داده ها دارد که موسوم به ساختمان داده های پایدار است، پایدار به معنی ذخیره شدن در دیسک نیست در این مورد پایداری به معنای ساختمان داده ای است که تغییرناپذیر است، و اگر بخواهید آنرا تغییر دهید یک نسخه جدید از آن را تولید خواهید کرد.
  • 14. مارکوس: یک کپی دیگر از آن! ریچ: نه چون ویژگی دیگر این ساختمان داده ها این است که آنها سرعت را برای شما خواهد بود. log(n) یعنی اضافه کردن با پیچیدگی ،O تضمین می کنند، ضمانت مارکوس: اجازه دهید اینطور بگویم که از نظر مفهومی به نظر میرسد که داده ها تماما کپی شده اند اما به روشی هوشمندانه تر این کار انجام میشود. ریچ: دقیقا و این همان نکته اصلی است، و لازم است اینها را بگوییم چون برداشت اولیه افراد این است که داده ها کپی میشوند و این نمی تواند کارآمد باشد اما این اتفاق نمی افتد. در ساختمان داده های پایدار شما یک نسخه جدید می سازید و این از نظر سرعت تضمین شده است، پس بنا نیست که داده ها کپی شوند چرا که اگر شما تعهد داده اید O(n) است و بخواهید دادها را کپی کنید این کار log(n) که پیچیدگی این عملیات خواهد بود. ویژگی های دیگر ساختمان داده ها این است که نسخه قبلی همچنان در دسترس است، و از بین نرفته است یا تنزلی پیدا نکرده است پس سرعت نسخه قبلی همان است که بود. چرا که الگوهایی برای پایداری وجود دارد که باعث میشود نسخه قدیمی به مرور تنزل پیدا کند، به واسطه روشی که این نسخه ها ساختارشان را به همدیگر به اشتراک گذاشته اند. پس همه نسخه ها به یک اندازه خوب هستند. زمانی که شما همه اینها را دارید، کلی ابزار متفاوت برای برنامه نوبسی دارید، نگهداری همه (stack) برگشت عملیات)، پشته ها )undo ، مقادیر ساده است، ذخیره سازی ارزان به دست می آیند، انجام طراحی عملیات به صورت بازگشتی ارزان است، و مواجهه با همزمانی راحت خواهد بود، چون همه مقادیر تغییرناپذیرند، آنها نیازی به قفل کردن یا چیز دیگری ندارند برای اینکه در یک محیط همزمان مورد استفاده قرار گیرند.
  • 15. مارکوس: به نظرم می ارزد که پنج دقیقه ای دیگر روی این ساختمان داده های پایدار زمان صرف کنیم، چرا که من آنها را فراموش کرده بودم و اگر یادتان باشد اصلا جزو موضوعاتی نبود که قرار بود در مورد آنها صحبت کنیم، اما خیلی نکات مهمی در مورد آنها وجود دارد. فرض کنید که من یک عبارت ساده دارم که یک عدد ضربدر حاصل جمع در عدد دیگر ۲ حالا ۴ را با ۵ عوض می *(۳+ میشود چیزی شبیه به یک ساختمان داده درختی، ( ۴ کنم، به صورت ساده انگارانه من باید کل درخت را کپی کنم و این اتفاق نمی افتد، لطفا بگویید چه اتفاقی می افتد که شما یک کپی دیگر دارید اما کپی ای انجام نمی دهید؟ ریچ: اگر ما ساده ترین ساختمان داده پایدار را در نظر بگیریم یک لیست پیوندی یک طرفه داشته باشیم و بخواهیم یک عضو به اول C و B ،A است، اگر ما یک لیست با اعضای شما یک گره جدید می سازید و آنرا به لیست من وصل می کنید با ،X آن اضافه کنیم مثلا مقدار دهی انتهای آن. مارکوس: در این مورد ساده است، موافقم. ریچ: اما نکته مهم اشتراک ساختار است، انتهای لیست شما با تمام لیست من ساختارشان را به اشتراک گذاشته اند. مارکوس: و چون من نمی توانم هیچ چیز را تغییر دهم، این نمی تواند باعث ایجاد مشکلی شود، مثلا این اتفاق که کسی یکی از داده های مرا تغییر دهد پیش نمی آید. ریچ: دقیقا و این نکته مهم بعدی است، چون من نمیتوانم لیست ام را تغییر دهم، پس نمی توانم لیست تو را هم دچار مشکل کنم. و برای اعمال این اصل به تمام ساختمان داده
  • 16. های دیگر، باید لیست را رها کرده و سراغ درخت بروید و این بدین معنی است که تمام همه درخت هستند. به همین vector یا hashmap ساختمان داده های کلوژر مانند خاطر برای این کار لازم است تنها مسیری را کپی کنید که شامل بخشی است که آن را تغییر داده اید، به جای کل درخت. را با آرایه نمایش دهید، چاره ای جز این نخواهید vector مثلا اگر شما بخواهید یک داشت که کل آرایه را کپی کنید. مارکوس: از دیدگاهی می توان درخت را به عنوان تعدای لیست پیوندی در نظر گرفت و هر گره به یک انتها چندین انتها دارد و این یک درخت می سازد. ریچ: بله می توانید، هر چند پیاده سازی آن اینطور نیست مارکوس: بله منظورم از نظر مفهمومی است. ریچ: بله و به همین خاطر بود که من با لیست شروع کردم، اساسا شما یک زنجیره از چیزها را دارید و با استفاده از درخت، تغییر هر برگی از این درخت تنها نیازمند تغییر یک مسیر به ریشه است و نه چیز دیگری، و نسخه جدید همه چیزش شبیه نسخه قبلی است به جز این مسیر جدید. پس ساختمان داده های کلوژر درختهایی از آرایه ها هستند، بنابراین ضریب شاخه شاخه شدن بالایی دارند و عمق بسیار کمی دارند، و به همین خاطر سرعت بالایی دارند. پس اینگونه کار می کنند.
  • 17. مارکوس: پس شما هیچ چیز را به اشتراک نمی گذارید و همه چیز تغییرناپذیر است پس نیازی به قفل کردن ندارید، و همه مشکلات مربوط به قفل گذاری بلافاصله حل می شود. اما مردم می پرسند اگر شما هیچ چیز را تغییر نمی دهید پس برنامه شما چگونه کار می کند، در یک زمان خاص شما لازم است که چیزی را تغییر دهید مانند یک پایگاه داده یا چیزی که باید تغییر کند. آیا شما با این موضوع مواجه میشوید، و اگر بلی، چگونه؟ ریچ: این یکی دیگر از نکات مهم در مورد کلوژر است، کلوژر تلاش نمی کند به شما بگوید که میتوانید تنها با توابع محض و ساختمان داده ای تغییرناپذیر برنامه بنویسد، چرا که برنامه های واقعی که در طول زمان مشغول ارائه سرویس هستند و با دنیای بیرون در ارتباط اند دارای وضعیت هستند، پس چگونه اینکار را انجام میدهید؟ نکته مهم فهم تفاوت بین مقادیر و شناسه ها است، که من در طول زمان در مورد آن صحبت خواهم کرد. مثالی که در اینجا می زنم این است که برنامه ای را در نظر بگیرید که مردم از طریق نام کاربری و رمز به آن وارد شده و خارج می شوند. مجموعه افرادی که وارد شده اند یک مجموعه است. در یک برنامه سنتی شما فرضتان این است که این مجموعه تغییرپذیر است، وقتی کسی وارد میشود شما آن مجموعه را تغییر میدهید، و این یک مشکل بزرگ دارد، اینکه کسی به می زند و بعد خطای تغییر foreach نسخه قدیمی آن نگاه می کند و روی آن می گیرد. (concurrent modification exception) همزمان اما آنچه که دقیقا اتفاق می افتد این است که شناسه ای وجود دارد چیزی که شما اسم روی آن میگذارید(مجموعه افرادی که وارد سیستم شده اند) که در هر لحظه ای از زمان ی تغییرناپذیر نمایش collection مقداری دارد، و شما هر کدام از آن مقادیر را به عنوان می دهید، پس تنها کاری که لازم است انجام دهید این است که مطمئن شوید که یک « مقدار خاص » از یک مجموعه و یک « مجموعه کاربران وارد شده » رابطه ترتیبی بین ایده
  • 18. وجود دارد و این تنها به یک ساختمان داده ی اتمیک نیاز دارد، که رفرنسی به آن مقدار است و آن رفرنس چیزی است که محتوایش عوض میشود. مارکوس: اجازه دهید سعی کنم که بازگو کنم، کلوژر چیزی به اسم اتم در اختیار ما قرار میدهد، درست است؟ ریچ: این یکی از انتخابهای ممکن است. دور یک مقدار است، مقداری که در اتم قرار دارد می تواند wrapper مارکوس: اتم یک در طول زمان عوض شود، یک شناسه در اختیار شما قرار می دهد و دسترسی سریالی و ترتیبی را به داده داخل خودش ضمانت می کند. ریچ: درست است و من آن را یک سطح بالاتر می برم، اتم یکی از نمونه های انواع رفرنس موجود در کلوژر است، و انواع رفرنسی، همه به خاطر یک مشکل است که وجود دارند و آن ابزاری برای نمایش شناسه است و ابزاری برای مدیریت زمان و ترتیب وضعیت هایی که همراه آن شناسه است. مارکوس: یک مثال برای ما بزنید، چگونه کار میکند؟ ریچ: شما می توانید آنها را جعبه های کوچکی در نظر آورید که در داخل آن جعبه مقداری وجود دارد و منظور از مقدار چیزی است که تغییر نمی کند، پس مجموعه افرادی که وارد سیستم شده اند یک جعبه است و در هر زمانی داخل جعبه یک ساختمان داده تغییرناپذیر وجود دارد و وقتی که میخواهید یک کاربر اضافه کنید، شما آن مقدار
  • 19. تغییرناپذیر را می گیرید و تابعی روی آن فراخوانی می کنید و یک مقدار تغییرناپذیر دیگر تولید میکند که همان مجموعه به اضافه کاربر جدید است و این مقدار جدید را داخل جعبه می گذارید. مارکوس: اگر دو نفر همزمان از دو نخ اجرایی اینکار را انجام دهند، مشکل همزمانی برای شما رخ خواهد داد! ریچ: مگر اینکه این انواع رفرنس معانی همزمانی را با خود داشته باشند. این کار آنهاست. نکته این است که شما دو مشکل را مجزا ببینید، ما دیگر در مورد مشکل تغییر و قرار دادن یک چیز جدید در آن صحبت نمی کنیم. اینها توابعی هستند collection یک که روی مقادیر کار می کنند، چیزی که باقی می ماند این است که ما چگونه از یک وضعیت به وضعیت بعدی میرویم (که هر وضعیت یک مقدار دارد) بدون اینکه با هم برخورد کنیم. این موضوع چگونه به نظر می رسد؟ API مارکوس: از نظر ریچ: همه انواع رفرنس یک شکل دارند، و یک مدل یکتا برای تغییر وضعیت وجود دارد. بدین شکل که شما یک رفرنس دارید که مقداری درخود دارد، شما برای آن رفرنس یک تابع میفرستید که تابع مربوط به آن مقداری است که داخل رفرنس است که ممکن است این تابع آرگومانهای دیگری هم داشته باشد، نوع رفرنس مسئول این است که تابع را بگیرد، آن را به مقدار داخلش اعمال کند و حاصل عملیات را به عنوان وضعیت بعدی خودش قرار دهد.
  • 20. مارکوس: رفرنس اطمینان میدهد که تنها یک نفر اینکار را در لحظه انجام می دهد ریچ: در نتیجه شما باید توابع درجه یک را در زبان داشته باشید تا بتوانید آن تابع را به متقاوتی برای این (semantic) عنوان آرگومان برای کس دیگری بفرستید، سپس معانی دارید که این تغییر کی و چگونه اتقاق می افتد. تغییر می تواند همزمان یا ناهمزمان باشد (همان لحظه اتفاق بیافتد یا بعدا)، شما می توانید بخواهید تابع اعمال شود و زمانی که انجام شد شما باخبر شوید یا اینکه می توانید بگویید اینکار را بعدا انجام بده و به کارتان ادامه دهید. تفاوتهایی اینجا وجود دارد، تفاوتهایی در این وجود دارد که آیا این تغییری که قصد انجام آن را دارید یک رفرنس را متاثر می کند یا شامل هماهنگی برای تغییر چند رفرنس است. دیگر هم دارید که اینکار هماهنگی را انجام می دهد! wrapper مارکوس: پس شما یک متفاوتی دارند ما در اینجا (semantic) ریچ: رفرنس های متفاوتی وجود دارد که معانی در مورد سه گونه از آنها صحبت خواهیم کرد، اتم ها ساده ترین شکل هستند، آنها هستند و اتمیک هستند یک واحد کاری می تواند تنها شامل یک اتم در synchronous ها، مانند اتم ها هستند، اتمیک هستند و یک واحد کاری می تواند agent ، آن واحد باشد هستند، زمانی که asynchronous در آن واحد باشد ولی آنها agent تنها شامل یک یک تابع را می فرستید، آن تابع در آینده اعمال خواهد شد و کنترل agent برای یک آن تابعی را که برای او فرستاده شده از agent بلافاصله به برنامه شما بر میگردد، و پردازش میکند اما ضمانت می کند که این عملیات (thread pool) طریق استخر نخ ها به ترتیب انجام خواهد شد. ها تنها در تراکنش ها تغییر می کنند و ref ، است ref و نهایتا پیچیده ترین نوع رفرنس هستند، پس شما می (coordinated) و هم هماهنگ شده synchronous آنها هم
  • 21. باشد، چیزی که مثلا زمانی به آن ref توانید یک واحد کاری داشته باشید که شامل چند نیاز دارید که بخواهید آیتمی را از یک دسته درآورده و به دسته دیگری اضافه کنید. را در آن تغییر می دهید. ref مارکوس: پس برای اینکار یک تراکنش باز می کنید و هر دو ریچ: این سیستم خوبی است چرا که شما همه عملیات را به توابع محض برده اید و اگر بخواهید تابعی را تست کنید که مثلا آیتمی را به دسته ای اضافه میکند شما نیازی به کردن چیزی ندارید، وضعیتی در آن تابع نخواهید داشت، و به آن نیازی ندارید، mock یک تابع محض دارید. پس تست این تابع بسیار ساده خواهد بود چون چیزی در مورد تغییر وضعیت در آن نیست. سپس شما مساله دیگری خواهید داشت و آن این است که فرستادم می خواهم مطمئن باشم که در محیط ref حالا که من یک تابع را برای یک همزمان به صورت امنی اجرا خواهد شد. این دو مساله از هم مجزا شده اند، می توانید همه این معانی متفاوت را شبیه هم کنید، مدل تغییر وضعیت، ارسال یک تابع به رفرنس ها همه یکی هستند. مارکوس: یکی از چیزهایی که این روز ها در مورد کلوژر صحبت می شود در مورد همین موضوع است: حافظه تراکنشی. ها از این طریق پیاده سازی شده اند، بله. ref ، ریچ: آخرین نوع انواع رفرنس ها
  • 22. مارکوس: ما قبلا در مورد حافظه تراکنشی برنامه ای داشته ایم هرچند شماره آن را به خاطر نمی آورم. ریچ: باید بگویم که رویکرد کلوژر به حافظه تراکنشی نرم افزاری بسیار متفاوت است از آنچه که در مقالات یا گفتگوها دیده اید، افراد زیادی روی این موضوع کار کرده اند با این هدف که به شما اجازه دهند کد موجودتان را نگه دارید (که آبجکت های تغییرپذیر را دستکاری می کند) اما آن عملیات را در یک تراکنش قرار دهید و نیازی به استفاده از قفل ها نداشته باشید. من شخصا طرفدار چنین رویکردی نیستم و فکر می کنم این روش نمی تواند کار را انجام نمی دهد، روش کلوژر بسیار متفاوت است، اینجا ما روی برنامه نویسی با مقادیر ها پس اندازه aggregate تاکید داریم، استفاده از توابع محض، استفاده از مقادیر برای و از روش کنترل (coarse granularity) ای که ما با آن کار می کنیم بزرگتر است همزمانی مبتنی بر چند نسخه ای بودن در لایه های زیرین استفاده می کند، پس کاملا متفاوت است. مارکوس: شما این واقعیت را آشکار کردید که می توان بعضی مقادیر را در داخل تراکنش ها تغییر داد، پس شما تلاشی برای شفاف کردن انجام نمی دهید. ریچ: نه، شفافیت در این مورد چیز خوبی نیست. مارکوس: موافقم.
  • 23. مارکوس: می خواهم حرف دهن شما بگذارم، با فرض اینکه پشتیبانی موجه از زمان، مقدار، شناسه و همزمانی دلایل اصلی برای ساختن کلوژر بوده اند. آیا اینکار با اضافه کردن یک کتابخانه یا فریم ورک به یک زبان موجود ممکن نبود؟ به عبارت دیگر چرا چنین چیزهایی نیاز به پشتیبانی شدن در سطح یک زبان نیاز دارند؟ ریچ: در واقع کلوژر یک کتابخانه است، یک کتابخانه است که به جاوا نوشته شده است و می توان از آن در جاوا استفاده کرد. و (idiomatic) موضوع زبان این است که باعث می شود استفاده از این مفاهیم طبیعی STM(Software راحت باشد، شما می توانید دقیقا از همین انواع رفرنس و و ساختمان داده های کلوژر در جاوا استفاده کنید. Transactional Memory) را در کلاس anonymous مارکوس: بله اما شما تلف می شوید اگر بخواهید این همه ها به عنوان تابع تعریف کنید. ریچ: در مورد توابع، عدم پشتیبانی کتابخانه هایی که به صورت طبیعی بتوان با استفاده از مقادیر برنامه نوشت، باید مقادیر بازگشتی را به متغییر دیگری انتساب دهید، این ها و پشتیبانی زبان بدین معنی idiom روش طبیعی انجام کار نیست، پس عدم وجود است که شما باید از همان کدهای زیربنایی جاوا استفاده کنید و این بسیار سخت خواهد بود در مقایسه با کلوژر، جایی که همه اینها عملکرد طبیعی سیستم است، و این کاری است که شما به صورت پیش فرض در کلوژر انجام میدهید، زمانی که شما برنامه کلوژر می نویسید و از این ساختمان داده ها استفاده می کنید همواره دارید به این روش برنامه می نویسید. این چیزی نیست که شما بعدها مجبور به انجام آن شوید، و این چیز خوبی است چرا که وقتی نیاز و علاقه به همزمانی را متوجه شوید لازم نیست چیزی را تغییر دهید، شما پیشتر کار درست را انجام داده اید.
  • 24. مارکوس: من تعریف شما از زبان را بسیار پسندیدم، چرا که من همواره با آن دست به ها کار میکنم و افراد همیشه از من می پرسند که تفاوت میان زبان و DSL گریبانم، من با چیست، چرا من به یک زبان نیاز دارم وقتی که می توانم همه چیز را با دستوراتی API و … بیان کنم. نکته این است که می خواهیم مفاهیم طبیعی باشند و بیان Insert مانند درست آنها ساده باشد، این یک تعریف بسیار خوب است. ریچ: بله و به همین دلیل است که همه این اجزای مستقل کلوژر با هم طراحی شده اند طوری که همه این جنبه ها با هم خوب کار کنند. مارکوس: آخرین سوال فنی قبل از اینکه بخواهیم در مورد استقبال از زبان و اجتماع کاربران کلوژر صحبت کنیم، یکی دیگر از روشهای مدیریت وضعیت در زبانهای تابعی در این باره حرف Eric Meyer با se-radio است، فکر می کنم قبلا در Monad دیگر زده ایم، آیا این موضوع در کلوژر نقشی دارد؟ مساله مربوط Monad ریچ: کتابخانه هایی برای اینکار وجود دارد، اما من فکر می کنم برای مساله Monad به شناسه ها را به صورت مبنایی حل نمی کند، شما نمیتوانید از مجموعه کابران وارد شده به سیستم استفاده کنید (برنامه ای که در طول زمان زیادی در Haskell حال اجرا بوده و اجزای مختلف برنامه درگیر بوده است)، و به همین خاطر است. اینها را دارد چون این روشی است که می توانید چند نخ MVar و STM دارای برای حالتی است که تنها یک نخ کنترل Monad ، کنترل مستقل را با هم هماهنگ کنید دارید. ربطی به همزمانی ندارد. Monad مارکوس: بله
  • 25. نمی توانید از یک ساختار مشابه برای هر دو کار استفاده Haskell ریچ: پس شما در کنید، مطمئن نیستم که آیا همیشه این ساختار صحیحی خواهد بود. به علاوه با وجود بسیار Haskell اینکه کتابخانه هایی برای کلوژر برای اینکار وجود دارد، این مفهوم در که دارد. (type system) قوی تر است به خاطر سیستم انواعی آگاه است، پس Monad مارکوس: شاید این سوال من باشد، آیا سیستم انواع شما از پاسخ خیر است و استفاده از آن طبیعی به نظر نمی رسد! ریچ: بله همینطور است، اما با ماکروها مشکل حل میشود، نکته اصلی این است که قابلیت استنتاج انواع روی انواع برگشتی توابع را دارد و این یک ویژگی Haskell است. Monad بسیار مهم برای مارکوس: کلوژر دارای انواع دینامیک است، درست است؟ پس شما نمی توانید استنتاج را انجام دهید، درست است؟ Monad نوع ریچ: خوب، کلوژر استنتاج محلی انجام می دهد، برای مثال برای اینکه کد جاوا را بدون فراخوانی کرد، ما نیاز داریم که انواع را بدانیم. (reflection) استفاده از بازتاب اما در کلوژر (به نسبت جاوا) شما خیلی کمتر به انواع نیاز دارید، چرا که اگر کمی اطلاعات پیدا کند، قادر خواهد بود انواع حاصله این عبارت و فراخوانی را استنتاج کند که خود می تواند ورودی یک فراخوانی دیگر باشد و در نتیجه انواع ورودی آن فراخوانی را نیز استنتاج کرده است. (-: ؟(duck typing) مارکوس: پس آیا دارای سیستم انواع ایستا است یا مرغابی گونه ریچ: اینها انتخاب های صفر و یکی نیستند.
  • 26. مارکوس: اگر استنتاج انواع توسط کامپایلر انجام میشود پس مرغابی گونه نیست. این سیستم، ایستا است که استنتاج انواع هم به آن تزریق شده است. ریچ: تفاوت اینها به اجبار کردن این قواعد برمی گردد، اگر بتوانم انواع را استنتاج کنم از آن برای تولید کد بهتر استفاده می کنم در غیر اینصورت آن را غیر مجاز نمی دانم که بدین معنی است که شما کد بازتابی خواهید داشت که در زمان اجرا ممکن است متوجه شود که اصلا متدی با آن اسم وجود ندارد. مارکوس: آهان! پس بدین معنی است که می توانید اطلاعات مربوط به انواع را در کلوژر تعیین کنید و اگر این اطلاعات موجود باشد آن کد کامپایل می شود برخلاف حالتی که کد بازتابی تولید میشود. ریچ: شما باید خیلی دقیق باشید چرا که این کد کامپایل میشود و دقیقا عین جاوا اجرا می شود. در مقابل کد شما مجاز به پذیرفتن انواع مختلف نخواهد بود، این تنها مکانیسمی برای بهینه سازی است نه برای رد کردن برخی عبارات اجرایی. این کار بررسی و اطمینان از صحت انواع نیست. مارکوس: ولی اگر این اطلاعات را فراهم کنید کد بهتری تولید خواهد شد. ریچ: و به درد تعامل با جاوا هم می خورد. مارکوس: آیا موضوع فنی ای در مورد زبان وجود دارد که من فراموش کرده باشم بپرسم و شما دوست داشته باشید در مورد آن صحبت کنید؟
  • 27. ریچ: فنی؟ مارکوس: بله مثلا یک ویژگی جالب زبان یا … ریچ: نه، در درون کلوژر بسیار بسیار ساده است، و در واقع این یکی از چیزهایی است که من می خواهم افراد در مورد کلوژر بدانند که از نظر فرم محاسباتی بی نهایت ساده است، قواعد زیادی وجود ندارد، قواعد نحوی زیادی وجود ندارد، مخصوصا در مورد نحو، زبان فوق العاده ساده است. مارکوس: خوب، بیاید در مورد موضوعات نرم صحبت کنیم، استقبال و پذیرش کلوژر در در طول دو سه سال اخیر آمده اند، چگونه JVM زبانهایی که روی (zoo بازار(به جای بوده است؟ ریچ: به صورت قابل توجه ای خوب عمل کرده است با توجه به اینکه جدیدترین زبانی است که به این مجموعه اضافه شده است، لیست ایمیل گوگل دارای ۳۳۰۰ عضو است، این خیلی چشمگیر است، پذیرش و استفاده از زبان، افراد شغل هایی تحت این عنوان پیدا می کنند، شرکت ها از آن استفاده می کنند، با شرکت های نوپا شروع شد اما الان کاربردهایی در زمینه های دیگر مانند تحلیل و دیگر جاهای متفاوت می بینیم. مارکوس: آیا سناریوی استفاده معمولی و عمومی ای دارد؟ جایی که استفاده از کلوژر واقعا مناسب است؟ ریچ: می دانید، یکی از بزرگترین چیزها برای من این بوده که زبان طوری طراحی شده که همه کاره باشد و در زمینه های بسیار گوناگونی موارد استفاده ی مختلفی داشته است.
  • 28. یکی از زمینه هایی که اگر بخواهم به عنوان یک زمینه داغ و پرطرفدار نام ببرم، استفاده برای کار یادگیری ماشین بوده است که روی خوشه ای از FlightCaster شرکت اجرا می شود، و کتابخانه هایی وجود دارد برای یکپارچه شدن با دیگر Hadoop این زمینه الان داغ است جایی که اکثرا ،encounter کتابخانه های آماری کلوژر به اسم استفاده می شده است که آن را به برنامه نویس می داده اند تا آن R به صورت سنتی از را به محیط عملیاتی ببرد، حال می توانند از کلوژر استفاده کنند برای اینکه با داده های حجیم کار کنند و مدلی را که بدست می آورند می توانند مستقیما در محیط عملیاتی مورد استفاده قرار دهند. این زمینه ای است که ترکانده است (-: اما برای برنامه نویسی وب و پایگاه داده ها و سیستم های انتقال پیغام نیز به کار می رود. مارکوس: اما می توان گفت که توان خود را جایی نشان می دهد که نیاز باشد الگوریتم های غیر جزیی و سنگینی به صورت همزمان اجرا شود. ریچ: می تواند اینطور باشد اما شاید بتوانید متوجه شوید که امکانات مربوط به برنامه نویسی همزمان کلوژر کمتر از آنچه فکر می کنید به کار گرفته شده است، نمی خواهم بگویم که این امکانات صرفا فوت و فن هستند، این زبان بسیار بیان راحتی دارد و با اکو سازگاری دارد پس حجم عظیمی از کتابخانه ها وجود دارد که می توانید JVM سیستم از آنها بهره ببرید و افراد بدین واسطه بسیار سریعتر و کارآمدتر برنامه می نویسند، و این مهم است. است. Stuart Halloway مارکوس: کتاب هم دارد که نویسنده آن ریچ: بله.
  • 29. Manning دو کتاب دیگر هم در راه است، می توانید دسترسی زودهنگام آنها را از است. Joy of Clojure است و دیگری Clojure in Action دریافت کنید، یکی مارکوس: آیا شما در آنها دخیل بوده اید؟ ریچ: نه. مارکوس: تعجب کردم. ریچ: من مشغول کلوژر هستم. شاید یک وقتی اینکار را بکنم اما الان خیلی مشغله دارم. مارکوس: به نظرم این نشانه خوبی است. ریچ: اجتماع برنامه نویسان عالی است، لیست ایمیل بزرگ است و بگذارید نگاه کنم ۲۳۰ حضور دارند، اینها همه معیارهایی هستند، کمک گرفتن از دیگران کار IRC نفر در راحتی است، افراد عمدتا دوستانه برخورد می کنند، شروع آسان است. مارکوس: خیلی خوب است. پس تنها مشکل پیدا کردن مشتری است لااقل برای من اینطور است. که بخواهد از کلوژر استفاده کند به جای زبانهای اصلی. که به نظرم در بعضی محیط ها همچنان یک چالش است که افراد را قانع کرد.
  • 30. ریچ: فقط به آنها بگویید که تنها می خواهیم از یک کتابخانه جاوا استفاده کنیم که نام آن است. jar کلوژر است، مانند همه کتابخانه های دیگر یک فایل پذیرش سطوح مختلفی در صنایع مختلف دارد، بستگی به سطح محافظه کاری دارد و اینکه دارند چه کار می کنند، اما جالب است که می بینیم به صورت گسترده ای به کار گرفته میشود. ها، برجسته کننده نحو زبان و … IDE ، مارکوس: ابزار برنامه نویسی آن چطور است اگر که آن را می پسندید، به صورت Emacs ، ریچ: قطعا. در واقع بسیار خوب است های سنتی خوشتان IDE سنتی جای مناسبی برای برنامه نویسی لیسپ است، اگر از Enclosure بسیار خوب پشتیبانی می کند، پروژه ای که نام آن Netbeans ، می آید است، کامل کردن کد برای کلوژر و جاوا را دارد، یکپارچگی بسیار خوبی با جاوا دارد، Intellij قرار گرفته است، به همین شکل IDE آن در REPL ، برجسته کننده نحو دارد آن را Intellij خوب از کلوژر پشتیبانی می کند، نوع پروژه کلوژر وجود دارد، بچه های هم به تازگی از Eclipse ، درست کرده اند، و کارشان را بسیار خوب انجام داده اند کلوژر حمایت می کند، خلاصه کلی انتخاب وجود دارد. مارکوس: شما اگر این سه تا را داشته باشید پس دیگر مشکلی وجود ندارد. مشترک است پس همه ابزار های JVM ریچ: بله و البته کلوژر در زیرساخت بایت کد با رفع خطا و بررسی عملکرد جاوا برای کلوژر هم کار خواهند کرد. مارکوس: در سطح سورس کد؟ ریچ: بله.
  • 31. مارکوس: خوب این همه چیزی بود که من آماده کرده بودم، چیزی برای اضافه کردن دارید؟ اگر IRC ریچ: نه فقط می خواهم که افراد آن را امتحان کنند، و به گروه گوگل بپیوندند و کمک می خواهید. مارکوس: خوب از اینکه در این برنامه حضور یافتید متشکرم. ریچ: از دعوت شما ممنونم.