PDA

View Full Version : گفتگو: گفتگویی با الکس استپانوف 1997



rahnema1
چهارشنبه 05 خرداد 1395, 10:34 صبح
قبلا در این تاپیک (http://barnamenevis.org/showthread.php?523811) مصاحبه ای از الکس استپانوف گذاشتم. این هم یک مصاحبه دیگه که مربوط به سال 1997 هست که با یک شخص ایتالیایی به نام Graziano Lo Russo صورت گرفته. بعضی مطالب فکر کنم نیاز به توضیحات داشت که حوصله نکردم توضیحاتی بنویسم حالا اگه کسی سوال یا بحثی داره می تونه توی اینجا یا تاپیک دیگه مطرح کنه. باز هم مطالب خوبی توی این مصاحبه پیدا می شه از تعریف برنامه نویسی عام و حمله به شیء گرایی و جاوا و ... . اصل این مصاحبه (http://www.stepanovpapers.com/LoRusso_Interview.htm) با تمام مصاحبه های دیگه در سایت استپانوف (http://www.stepanovpapers.com) قرار داره به همراه لیست مقالات و جزوه های درسی و سخنرانی ها و ... . امیدوارم بتونم باز مطالبی از این ایشون منتشر کنم ...

-سوال: لطفا خودتان را معرفی کنید.
-جواب: من در ۱۶ نوامبر 1950 در مسکو متولد شدم و در دانشگاه Moscow State رشته ریاضی خواندم. اما هرگز ریاضیدان نشدم. چیزهایی مثل اعداد Tamagawa ، گروههای Coxeter و ... که به نظر می رسد در آنها متخصص باشم مرا شگفت زده نکرده اند. آرزوی هاردی که ریاضیات او هیچ گاه کاربردی نخواهد شددر مورد من صدق نمی کند. من به یک چیز واقعی تری نیاز داشتم. البته خوش شانس بودم که در کارم ریاضیدانان بزرگی را دیدم تا نسبت به سخت گیری شبه ریاضی که متاسفانه در علوم کامپیوتر رایج است ایمن شوم. در نتیجه برنامه نویس شدن برای من چیز خوبی بوده است. در سال 1972 عضو تیمی شدم که یک مینی کامپیوتر جدید را برای کنترل ایستگاههای انتقال نیروی برق آبی طراحی می کرد. من در تمام مراحل طراحی، از تست معماری و سخت افزار تا سیستم عامل (اولین مقاله چاپ شده من در مورد سیستم عاملهای زمان واقعی بود) و ابزارهای برنامه نویسی مشارکت داشتم. من به طور عملی در مورد قابلیت اطمینان (ایستگاههای نیرو به سختی reboot می شوند) و کارایی (آب لحظه به لحظه پایین می ریزد) نرم افزار یاد گرفتم.
در همان زمان کتابهای دو دانشمند کامپیوتر را دیدم که از آنها اساس و پایه علمی کار من شکل گرفت: Donald Knuth و Edsger Dijkstra. که Knuth پاسخها را به من آموخت و Dijkstra هم سوال را به من آموخت. در مواقع مختلف باز به آثار این دو مراجعه می کنم تا به بینشهای جدید دست پیدا کنم. مسیر بعدی زندگی من این بود که 5 سال در بخش علوم کامپیوتر مرکز تحقیقات جنرال الکتریک، سپری کردم. من روی یک زبان بسیار سطح بالا به نام Tecton کار کردم و خیلی مطالعه کردم: از تعداد زیادی مقاله در مورد طراحی زبان برنامه نویسی بگیرید تا کتاب جمع منطق از ویلیام اکام- ارسطو .منطقیان قرون وسطی در مورد انواع مختلف ساختارهای منطقی که در زبانهای طبیعی وجود دارد و خصوصیات رسمی آنها دانش زیادی داشتند. همان موقع من به همراه Dave Musser یک تحقیق مثمر ثمر انجام دادم که هنوز تمرات آن را مشاهده می کنم. در سال 1984 من استادیار دانشگاه پلی تکنیک در بروکلین شدم. تدریس علوم کامپیوتر نتایج خیلی خوب برای من داشت- برنامه ریختم که انواع درسهای دوره تحصیلات تکمیلی را تدریس کنم که باعث می شد مطالب زیاد در مورد مسائل روز یاد بگیرم. همچنین کتابخانه بزرگی از الگوریتم و ساختمان داده به زبان Scheme ایجاد کردم. که (به همراه Dave Musser) منجر به ایجاد کتابخانه عام Ada شد. بعد از مدت کوتاه که در آزمایشگاههای Bell بودم ـ که روی کتابخانه ای از الگوریتمه به زبان ++C کار کردم ـ در 1988 به آزمایشگاه HP رفتم. ۴ سال بعد را صرف کار بر روی سیستمهای ذخیره کردم: مجبور شدم برنامه نویسی کنترلر دیسک را یاد بگیرم. در سال 1993 فرصت کوتاهی پیدا کردم تا به مطالعه ام روی برنامه نویسی عام بازگردم. که نتیجه آن STL شد. در 1995 به Silicon Graphics رفتم که در پی تشکیل گروهی جهت کار بیشتر روی توسعه STL بودم.
-سوال: شما از ویلیام اکام نام بردید. وی می گوید Entia non sunt multiplicanda . می تونم این جمله به این صورت ترجمه کنم که نیازی به اشیاء [انتزاعی] نیست. به نظر می رسد که این تیغ اکام را به برنامه نویسی شیء گرا OOP اعمال کردید. اینکه از به جای اشیاء از الگوریتم ها شروع کنیم به نوعی «مساله کلیات» مربوط به قرون وسطی را به ذهن متبادر می کند. درسته؟
-جواب: شباهت خوبی وجود دارد ولی فکر نمی کنم درست باشد. من فکر نمی کنم که شیء گرایی ربطی به فلسفه رئالیسم داشته باشد من به هیچ وجه «نام گرا» (nomilalist) نیستم. در واقع مکتب فرانسیسکن ـ با متفکرانی مثل Alexander of Hales و Bonaventure و Scotus ـ به سنت آگوستین/افلاطون نزدیکتر است. در هر صورت اکام آدم عجیبی بود. به طوری که Gideon Gal ویرایشگر مجموعه کامل او می گوید: اما آدم دیوانه ای بود!
-سوال: برای بسیاری از مخاطبان ایتالیایی اسم "Stepanov" با STL همراه است. آیا STL به معنای Standard Template Library است یا STepanov and Lee؟ و در تاریخچه STL نقش D.Musser و A.Koenig چه بوده است؟
-جواب: بله معنای درستش همان Standard Template Library است. من در مصاحبه با مجله Dr. Dobb در خصوص STL یک شوخی کردم که STL به معنای STepanov and Lee است اما این یک شوخی بود. من به مدت تقریبا ۲۰ سال با Dave Musser همکار بودم. همکاریمان آنقدر نزدیک بود که سخت است که سهم هر کدام از ما در نوشتن STL مشخص بشود. او در لیست رسمی مولفان STL قرار ندارد چونکه در مدت کوتاهی که پروپوزال کتابخانه برای استاندارد تهیه می شد مشغول کار دیگری بود. نقش Andy Koenig هم این بود که ماشین انتزاعی C را برای من تشریح کرد. STL به نوعی کاربرد تکنیکهای برنامه نویسی عام (generic programming) بود که Dave Musser و من برای یک مدل ماشین C توسعه داده بودیم. اگر Andy نبود من با اشیاء بسته بندی شده (boxed) و در heap قرار گرفته کارم را انجام می دادم و به خاطر جمع آوری زباله (garbage collection) تحلیل می رفتم. و مطمئنا Andy و Bjarne Stroustrup نقششان جا انداختن STL در استاندارد بود. وقتی که در مرحله ای لازم شد از ایده های زیبا به سمت پیاده سازی کامل برویم خانم Meng Lee به عنوان یک همکار کامل نقش ایفا کرد. او به من کمک می کرد تمرکز داشته باشم ـ من معمولا وقتی مساله ای حل شد علاقه ام را از دست می دهم ـ اگ جواب مساله را بدانم چه لزومی دارد که جوابش را به بقیه بگویم. او زمانهای خسته کننده ای را صرف کد و مستندات کرد. به نوعی او تنها فردی بود که از این کار یک چیز عملی بیرون خواهد آمد. فکر کنم در آن زمان، هم Dave Musser و هم من از اینکه کارهای طولانی مدتمان را به بقیه توضیح بدهیم واقعا نا امید شده بودیم.
-سوال: ریشه STL چیست؟ آیا STL از همان اول همان کتابخانه استاندارد ++C بوده یا از پروژه دیگری آمده؟ لطفا تاریخچه STL را شرح دهید. در سال 1976 ـ که در شوروی بودم ـ به خاطر خوردن ماهی خام دچار مسمومیت شدید غذایی شدم. در بیمارستان در حالت هذیان یکدفعه فهمیدم که اینکه می شود اعداد را به صورت موزی جمع کرد به این مربوط است که «جمع» یک عملیات شرکت پذیر (associative) است. ( پس به زبان ساده، STL نتیجه یک عفونت باکتریایی است). به عبارت دیگر فهمیدم که الگوریت تقلیل (reduction) موازی با یک نوع ساختار جبری نیم-گروه (semigroup) مرتبط است. نکته اساسی این است: الگوریتمها بر پایه ساختارهای جبری تعریف می شوند. چندین سال دیگر هم طول کشید تا بفهمم که لازم است مفهوم ساختار را گسترش بدهیم که این گسترش به این صورت انجام می شود که بیاییم به اصول موضوعه معمولی، شرط پیچیدگی زمانی را هم اضافه کنیم. بعد، 15 سال طول کشید که این فکر عملی بشود. (هنوز هم مطمئن نیستم که توانسته باشم این نکات را به جز حلقه دوستان نزدیکم به کس دیگری توضیح بدهم ). من بر این باورم که همان طور که نظریه حلقه ها یا فضای باناخ در کانون ریاضیات قرار دارند به همان میزان هم نظریه تکرارگرها (iterator) در کانون علوم کامپیوتر قرار دارد. هر وقت به یک الگوریتم نگاه می کنم سعی می کنم ساختمانی که الگوریتم برپایه آن تعریف شده را پیدا کنم. بنابراین آنچه که می خواستم انجام دهم عبارت بود از تشریح الگوریتمها به صورت عام. این چیزی است که دوست دارم. من می توانم یک ماه بر روی یک الگوریتم کاملا شناخته شده کار کنم تا بتوانم نمایش عام آن را پیدا کنم. خب من برای اینکه به دیگران توضیح بدهم که این یک کار مهم است ناموفق بودم. در عین حال نتایج این کار یعنی STL کاملا موفق شد.
-سوال: من اینطور فکر می کردم که شما ملزومات و شرایط پیچیدگی زمانی که در STL قرار دادید برای این بوده که محدودیت و شروطی را برای کارایی کتابخانه پیاده سازی شده گذاشته باشید. ام به نظر می رسد شما منظورتان این است که پیچیدگی از ملزومات کارکردی است. این درست است؟
-جواب: ما الگوریتم های مختلف را با توجه به عملیات های اساسی که ساختمان داده ارائه می کند انتخاب می کنیم. دیسک و نوار از نظر کارکردی مثل ادوات ذخیره SCSI هستند اما برای طراح نرم افزاری که بخواهد از نوار به منزله دیسک استفاده کند دردسرساز می شود. از نظر STL همیشه می شود تکرارگر جلو رونده (forward iterators) را با پیچیدگی p + n پیاده سازی کرد اما چرا تکرارگر با دسترسی تصادفی (random access iterator) استفاده نشود؟
-سوال: در مورد برنامه نویسی عام صحبت کنیم. من در مورد برنامه نویسی عام فقط ستونی نوشته A.Koenig در مجله JOOP یافتم. برنامه نویسی عام در بیشتر کتابهای برنامه نویسی ++C مثل کتابهای Coplien و Meyer و Stroustrup و Lippman و ... وجود ندارد. به نظرم STL را به این شکل تعریف کنیم : «برنامه نویسی ++C به روشی که شما هرگز فکر نمی کردید امکان پذیر باشد». آیا با این نظر موافقید؟
حداقل از نظر من STL تنها روش ممکن برای برنامه نویسی است. در نتیجه با برنامه نویسی ++C که تا به حال در کتابها شرح داده می شده و می شود کاملا متفاوت است. من مدت طولانی در جستجوی زبانی بوده ام که با آن بتوانم آن چیزی را که خواسته من است بیان کنم. به عبارت دیگر من می دانم که چه می خواهم بیان کنم. من می توانم بگویم آن چیز در ++C است یا در Ada یا در Scheme. من خودم را بازبان تطبیق می دهم. اما اساس آن چیزی که می خواهم بگویم مستقل از زبان است. تا کنون ++C بهترین زبانی بوده که جهت بیان خواسته هایم یافته ام. این زبان یک رسانه ایده آل نیست اما در آن می توانم نسبت به تمام زبانهایی که امتحان کرده ام کارهای بیشتری انجام دهم. و واقعا امیدوارم روزی برسد که زبانی صرفا جهت برنامه نویسی عام طراحی شود.
-سوال: آیا ممکن است برای یک برنامه نویس ++C مبتدی توضیح دهید که برنامه نویسی عام چیست؟ ارتباط بین برنامه نویسی عام با ++C و STL چیست و چگونه شد که شما برنامه نویسی عام را در چارچوب ++C مورد استفاده قرار دادید.
-جواب: برنامه نویسس عام یک روش برنامه نویسی است که برپایه یافتن انتزاعی ترین شکل الگوریتم های با کارایی بالا می باشد. یعنی شما یک الگوریتم دارید و سپس کلی ترین مجموعه ملزومات را پیدا می کنید تا الگوریتم به وسیله آن اجرا شود و اجرای آن با کارایی بالا باشد. نکته جالب این است که بسیاری از الگوریتمهای متفاوت به ملزومات یکسانی نیاز دارند و برای این ملزومات، چندین پیاده سازی وجود دارد. مشابه همین موضوع در ریاضیات این است که بسیاری از قضایای متفاوت، به اصول موضوعه یکسانی وابسته هستند و برای هر کدام از این اصول، مدلهای مختلف زیادی وجود دارد. انتزاع، کار می کند! برنامه نویسی عام، فرض می گیرد که تعدادی قانون اصلی وجود دارد که بر رفتار کامپوننتهای نرم افزاری حاکم هستند و می توان بر اسا اسن قوانین، ماژولهای مرتبط با هم طراحی کرد. همچنین می توان از این قوانین، برای جهت دهی طراحی نرم افزار استفاده کرد. STL نمونه ای از برنامه نویسی عام است. ++C زبانی است که در آن توانستم یک مثال متقاعدکننده [STL] ارائه کنم.
-سوال: من فکر می کنم که STL و برنامه نویسی عام، نشانه یک گردش از سبک رایج برنامه نویسی ++C ـ که فکر کنم به طور کامل برگرفته از SmallTalk است ـ می باشد. آیا موافقید؟
-جواب: درسته. STL شیء گرا نیست. من فکر می کنم شیء گرایی مثل هوش مصنوعی (AI) یک خالی بندی است. من هنوز یک تکه کد به درد بخور از افراد شیء گرا ندیدم. من چیزهای زیادی از اعضای MIT AI Lab دیدم، آنها تعدادی کار واقعااساسی انجام داده اند. Hakmem که کار Bill Gosper است یکی از بهترین چیزهاست که برنامه نویسان می توانند مطالعه کنند. AI ممکنه که اساس جدی نداشته باشد اما چیزهایی مثل اینها را ایجاد کرده است: Emacs اثر Gosper و Stallman یا Macsyma اثر Moses یا Scheme اثر Sussman و Guy Steele. به نظر من برنامه نویسی شیء گرا (OOP) از لحاظ تکنیکی بی اساس است. این روش سعی می کند جهان را تجزیه کند به رابط های مختلف برای یک نوع. برای مسائل واقعی نیاز به جبر با چندین نوع (multisorted algebras) ـ خانواده ای از رابط ها چندین نوع را بسط می دهند ـ می باشد. من OOP را از نظر فلسفی بی اساس می دانم. در آن ادعا می شود هر چیزی یک Object است. حتی اگر این حرف درست باشد خیلی جالب نیست. اینکه بگوییم هرچیزی یک Object است مثل این است که اصلا چیزی نگوییم . به نظر من OOP از لحاظ روش شناسی اشتباه است. در این روش از کلاسها آغاز می کنیم. مثل این است که ریاضیدانان با اصول موضوعه شروع کنند. ما با اصول موضوعه شروع نمی کنیم بلکه با اثبات شروع می کنیم. تنها زمانی که ما تعدادی اثبات مرتبط را یافتیم می توانیم اصول موضوعه را بیاوریم. ما با اصول موضوعه، تمام می کنیم. همین موضوع در مورد برنامه نویسی هم صدق می کند: ما باید با الگوریتم مورد نظر آغاز کنیم. وفقط زمانی که الگوریتم را خوب فهمیدیم، می توانیم رابطهایی را بیاوریم که با آن الگوریتم به کار بیفتد.
-سوال: این برداشت من از افکار شما درست است؟ «یافتن ساختمان داده [عام] در یک الگوریتم» به جای «یافتن الگوریتم ها [ی مجازی] داخل یک Object».
-جواب: درسته. همیشه با الگوریتم شروع می کنیم.
-سوال: این به تغییر جدی تفکر از دو نوع فکر دستوری (imperative) و شیء گرا می باشد. مزایای و معایب این روش نسبت به روش «استاندارد» برنامه نویسی شیء گرا که در SmallTalk یا Java انجام می شود چیست؟
-جواب: روش من کار می کند ولی این روشها کار نمی کند. مثلا یک چیز ساده مثل max را می خواهیم با روش شیء گرا پیاده سازی کنیم که من این کار را بلد نیستم اما با روش برنامه نویسی عام می توانم بنویسم:

template <class StrictWeakOrdered>
inline StrictWeakOrdered& max(StrictWeakOrdered& x,
StrictWeakOrdered& y) {
return x < y ? y : x;
}

و

template <class StrictWeakOrdered>
inline const StrictWeakOrdered& max(const StrictWeakOrdered& x,
const StrictWeakOrdered& y) {
return x < y ? y : x;
}

(که البته نیازی به & یا &const نیست). و مثلا بعدا StrictWeakOrdered را تعریف می کنیم. حالا این را بخواهیم در Java انجام بدهیم. در Java نمی شود یک max عام نوشت که دو آرگومان از یک نوع دریافت کند و مقدار بازگشتی آن هم از همان نوع باشد. وراثت و interface ها کمکی نمی کنند. حالا اگر نشود max یا swap یا جستجوی خطی را پیاده سازی کرد چه شانسی وجود دارد که بشود مسائل واقعا پیچیده را پیاده سازی کرد؟ من آزمایش لیتموس را به این صورت انجام می دهم: اگر زبانی امکان پیاده سازی max و swap و جستجوی خطی را به من بدهد پس قابلیت هایی دارد.
-سوال: Java یک زبان خیلی نو است که هنوز template را ندارد که مانع از برنامه نویسی عام می شود. هر چیزی باید کلاس باشد. نظر شما درباره Java چیست؟
-جواب: من چندین ماه را صرف برنامه نویسی Java کرده ام. بر خلاف پیش بینی مولفان آن، من را رشد نداد. من بینش جدیدی نیافتم ـ در تمام دوران برنامه نویسی خودم برای اولین بار بود که یک زبان جدید (Java) بینش جدیدی برایم حاصل نکرد. این زبان تمام چیزهایی که در ++C استفاده نمی کنم نگه داشته ـ مثل وراثت، چیزهای مجازی (یعنی چیزهای مربوط به شیء گرایی)ـ و چیزهایی که برای من مفید بود را حذف کرده. ممکن است موفق بوده باشد ـ همان طور که MS DOS موفق بود ـ و ممکن است برای تمام مخاطبان شما یاد گرفتن Java منفعت داشته باشد اما ارزش فکری ندارد. به پیاده سازی hash table آن نگاهی بیندازید. به روالهای مرتب سازی آن که با اپلت cool" sorting" آن آمده نگاهی بیندازید. سعی کنید از AWT استفاده کنید. بهترین روش برای قضاوت درمورد یک زبان این است که به کدهایی که توسط طرفداران آن نوشته شده نگاه بیندازید. "Radix enim omnium malorum est cupiditas" (طمع [پول] سرمنشا تمام شرها است) و Java نمونه ای از برنامه نویسی پول گرا است (money oriented programming MOP). به طوری که طرفدار اصلی Java در شرکت SGI به من گفت: الکس شما باید هر جا پول باشد همان جا بروی. ولی من نمی خواهم هر جا پول باشد آنجا بروم ـ معمولا آنجا بوی خوشی نمی آید.

rahnema1
چهارشنبه 05 خرداد 1395, 10:35 صبح
-سوال: به نظر شما آیا برنامه نویسی مبتنی بر template و برنامه نویسی عام توسط بیشتر برنامه نویسان مد نظر قرار خواهد گرفت؟ یا اینکه این روش به STL محدود خواهد شد ـ مثل manipulator ها که به جز کتابخانه iostream در جای دیگری استفاده نشده اند.
-جواب: نمیدانم. قبل از اینکه ایده های پشت STL وارد جریان عمومی شود زمان زیادی طول خواهد کشید.اگه چیزی ازش بیرون بیاید تقریبا ۱۰ تا ۱۵ سال طول می کشد.
-سوال: چیزی که من را همیشه متعجب کرده این است که چه طور STL به این سرعت توسط کمیته استانداردسازی ++C پذیرفته شد. یعنی این کمیته ها بسیار محتاط و محافظه کار هستند. توضیح شما چیست؟
-جواب: حمایت Bjarne Stroustrup حیاتی بود. Bjarne واقعا می خواست STL در استاندارد باشد و اگر Bjarne چیزی را بخواهد، آن را به دست خواهد آورد. او خیلی یکدنده است. حتی مرا مجبور کرد در STL تغییراتی بدهم که به جز او برای کس دیگری انجام نمی دادم ـ البته من هم یکدنده هستم اما او با اراده ترین شخصی است که می شناسم. او چیزها را ممکن می کند. من مدتی را صرف فهماندن اینکه STL درمورد چیست به او کردم، اما وقتی که آن را گرفت برای جا انداختن آن آماده شد. او همچنین در STL سهم داشت از این جهت که با این عقیده که برای برنامه نویسی چندین روش معتبر وجود دارد حدود یک دهه علیه هجمه های بی پایان و تبلیغات دروغین ایستادگی کرد و ترکیبی از انعطاف، کارایی، سربارگذاری و ایمنی نوع (type safety) را در template قرار داد که موجب شد STL امکان پذیر شود. تمایل دارم که به روشنی اعلام کنم که Bjarne طراح زبان شاخص نسل من است.
-سوال: STL پر از استفاده خلاقانه از template است مثل نوع های سمبلیک که از کلاسها صادر می شود یا تطبیق الگوی الگوریتمهای سربارگذاری شده با برچسب تکرارگرها. در واقع هیچ کتاب استاندارد برنامه نویسی ++C درباره این اصطلاحات صحبت نکرده. چه طور شد که شما به این اصطلاحات در کدهای ++C رسیدید؟
-جواب: من دقیقا می دانستم به چه چیزی می خواهم برسم. پس با زبان آنقدر ور رفتم تا به چیزی که بخواهم برسم. اما چندین سال طول کشید تا تمام تکنیک ها را کشف کنم. و من بسیاری شروع های اشتباه هم داشته ام. مثلا من سالها صرف کردم که برای وراثت و [چیزهای] مجازی، کاربردهایی پیدا کنم که بعد فهمیدم این سازوکارها اساسا ناقص هستند و نباید استفاده شوند. بسیار خوشحالم که کسی نمی تواند مراحل میانه راه را مشاهده کند ـ چون بسیاری از آنها خیلی احمقانه بود. سالها طول کشید که همه چیز نسبتا مناسب شود. همچنین اینکه Bjarne می خواست بعضی خواص را به زبان اضافه کند تا بعضی اصطلاحات من امکان پذیر شود هم کمک کننده بود. او یکبار به این کار گفت «طراحی زبان فی البداهه».
-سوال: به نظر شما بهترین روش آموزش برنامه نویسی عام و STL به برنامه نویسان ++C چیست؟ به نظر شما تکنیک های برنامه نویسی شیء گرا باید قبل، بعد یا همزمان با STL آموخته شود؟
-جواب: من در نظر دارم یک درس برنامه نویسی عام در SGI ارائه کنم. امیدوارم که این موجب ایجاد یک کتاب شود. البته معلوم شده که من یک نویسنده تنبل هستم. من هرگز مقاله ای را به پایان نمی رسانم مگر همکاری داشته باشم که انجامش دهد.
-سوال: من در Lycos جستجو کردم تا مقالات شما را بیابم که فقط دو عنوان پیدا شد: دستورالعمل STL و رزومه ای از شما جهت ارائه STL به کمیته استانداردسازی.
-جواب: درسته من تنبلم البته نه به این حد. من تقریبا 20 مقاله و یک کتاب منتشر کرده ام. بسیاری از آنها در سایت های مختلف STL قرار دارند. (احتمالا در سایت Dave Musser تعدادی قرار داشته باشد).
-سوال: کدام کتاب؟
-جواب: کتاب زیر
"The Ada Generic Library: Linear List Processing Packages", by David R. Musser and Alexander A. Stepanov, Compass Series, Springer-Verlag, 1989
که البته خیلی خواندنی نیست.
-سوال: STL محدودیت کامپایلرهای ++C را نشان می دهد. کامپایلرهای کنونی ++C هم هنوز قادر نیستند بعضی کدهای STL را کامپایل کنند. شما چه طور توانستید STL را توسعه بدهید و تست کنید؟
من بر سر کامپایل STL مقدار زیادی از موهایم سفید شد. حقیقت تاسف بار این است که بسیاری از پیاده سازی های کنونی STL بهینه نیست چون هنگام توسعه STL مجبور بودم از کامپایلرهایی استفاده کنم که محدودیت و باگ داشت. خوشبختانه Bjarne به من کمک کرد که در مورد خاصیتهای پیاده سازی نشده تصوری از نحوه کارشان داشته باشم. وقتی شما بتوانید از طراح زبان بپرسید این خاصیت زبان دقیقا چه کاری انجام می دهد بسیار کمک کننده است.
-سوال: تخصیص دهنده ها (allocator) چگونه به STL اضافه شدند. چه اندیشه ای در مورد آن داشتید؟
-جواب: من تخصیص دهنده را در مواجهه با معماری اینتل ابداع کردم. از نظر تئوری، ایده بدی نیست یعنی لایه ای که تمام چیزهای حافظه را داخل خود کپسوله کند: اشاره گرها، ارجاع ها، ptrdiff_t و size_t. اما در عمل کارایی ندارند. در مثال زیر:

vector<int, alloc1> a(...);
vector<int, alloc2> b(...);

نمی شود به این صورت نوشت:

find(a.begin(), a.end(), b[1]);

چون [b[1 یک alloc2::reference را برمی گرداند نه &int . که عدم تطابق نوع می تواند رخ دهد. لازم است روشی که هسته زبان با ارجاع ها دارد تغییر کند تا تخصیص دهنده ها مفید واقع شوند.
-سوال: آیا این می تواند یک ایراد جدی برای template های ++C باشد؟ می شه یک کلاس را با یک آرگومان template تعریف کرد اما تخصصی کردن های مختلف از نظر نوع، سازگار نیستند. در عوض زیرکلاسهای مختلف (از نظر شیء گرایی) از یک کلاس با کلاس ریشه از نظر نوع، سازگار هستند.
-جواب: فکر کنم مساله عمیقتر از این باشد. *T در این زبان حک شده. به طور کلی معتقدم که لازم است زبان برنامه نویسی از پایه طراحی شود که بشود با آن به شکلی استوار برنامه نویسی عام انجام داد. انتظار می کشم کسی مرا برای فقط انجام این کار استخدام کند.
-سوال: من در سایت D.Musser دو پیاده سازی از hash table پیدا کردم که هر دو کار می کردند و کاملا هوشمند بودند ـ خیلی هوشمندتر از hash table هایی که در کتابخانه ها یافت می شوند. چرا hash table در STL قرار داده نشد؟
-جواب: سیاست. باید در STL باشند. پیاده سازی جدید STL که انجام دادیم اینها را در بر گرفته. در کل لازم است ما سازوکاری جهت اضافه کردن چیزهای مختلف به STL ایجاد کنیم. در عین حال، STL یک چارچوب قابل توسعه است یعنی قابلیت توسعه آن زیاد است. ساختمان های داده زیادی هستند که در STL نیستند مثل لیست پیوندی یک طرفه، ماتریسها و گراف. SGI می خواهد توسعه STL را رهبری کند.
-سوال: آیا شما هنوز دارید روی STL کار می کنید؟ چه کاری انجام می دهید؟
گروه من در SGI شامل Matt Austern و Hans Boehm و من یک نسخه جدید از STL را به اتمام رسانده. که شامل محتوی های (container) هش، تخصیص حافظه ایمن از نخ (thread safe)و مستندات شکیل تحت وب است. SGI آن را به طور عمومی عرضه کرده است http://www.sgi.com/Technology/STL . ما امیدواریم که STL را در حال رشد نگه داریم. ساختمانهای داده چندبعدی، مانایی و چندنخی در بین چیزهایی است که برنامه داریم آنها را اضافه کنیم. البته معلوم نیست چه قدر طول می کشد که اینها را انجام بدهیم. مدیران من از فعالیتهای مربوط به برنامه نویسی عام و STL حمایت نمی کنند. سخت است که به آنها توضیح بدهم که چرا SGI باید جهت توسعه کتابخانه هزینه بدهد. (همچنین توضیح دادن این مساله به مدیریت HP هم سخت بود. آنها ۵ ماه بعد از پذیرفته شدن STL در استاندارد، پروژه من را لغو کردند).
-سوال: به نظر می رسد STL هنوز کاستی هایی دارد.مورد اول HP STL هنوز ازنظر نخ ها ایمن نیست. مورد بعد، template ها موجب شده اند مقدار زیادی کد در فایلهای سرآیند قرار بگیرند. ما نمی توانیم کتابخانه های واقعی از template ها یا کتابخانه های مشترک (shared library) یا dll ی از template های نمونه سازی نشده داشته باشیم: به عبارت دیگر STL بیشتر یک کتابخانه زمان کامپایل است. آخرین کاستی هم این است که تقریبا هیچ ابزار CASE یا روش OOD از برنامه نویسی عام پشتیبانی نمی کند. مثلا هیچ کدام از ابزارهای CASE اجازه تعریف تابعهای عام را نمی دهند. همچنین با روش Booch می توان template را نشان داد اما دیاگرامهای ایجاد شده (حداقل برای من) حس ایجاد نمی کنند.
-جواب: SGI STL از نظر نخ ها ایمن است. مساله دوم را می توان با کامپایل جداگانه (در صورتی که توسط استاندارد پذیرفته شود) حل کرد. ایده کامپایل جداگانه توسط John Wilkinson و Jim Dehnert و Matt Austern که در شرکت SGI هستند طراحی شده. البته این پیشنهاد در استاندارد رای آورد اما تا کامپایلرها قادر شوند کامپایل جداگانه انجام دهند مدتی طول می کشد. بر این باورم که کامپایل جداگانه نهایتا مستلزم این است که کتابخانه های مشترک از template ها هم با کد جابجا شوند. طراحی ابزارهایی جهت کار با برنامه نویسی عام، سخت نیست. و کاملا مطمئنم اگر بازاری برای آن وجود داشته باشد، Grady Booch هم روش خودش را تغییر می دهد که بتوان با برنامه نویسی عام کار کرد.
-سوال: یک چیز زجرآور برای برنامه نویس ++C این است که کمیته های استاندارد شناختی از همدیگر ندارند. OMG استانداردی برای برنامه نویسی توزیع شده (CORBA) تعریف کرده اما پیاده سازی CORBA در ++C بدون توجه به STL صورت گرفته. آنها کلاسهای مختص خودشان را تعریف کرده اند مثل <Sequence<T و CORBA::String. همین مساله در مورد ODMG و استاندارد ODMG-93 برای پایگاه داده شیء گرا رخ داده است. چرا این طور شده است؟ آیا قرار است چیزی تغییر کند؟
-جواب: من آنقدر پیر شده ام که نمی توانم تمام استانداردهای شبکه که در دهه ۷۰ آمدند را به خاطر بیاورم. الان چه کسی آنها را به خاطر می آورد؟
-سوال: برنامه نویسی عام در یک محیط توزیع شده به چه صورت خواهد بود؟ برنامه نویسی عام بر این ایده مبتنی است که کامپایلر در زمان کامپایل، تمام نوع ها را می شناسد. که این در محیط توزیع شده صدق نمی کند. راه حل آن آیا یکپارچه شدن نوعی ORB با کامپایار هست؟ یا برنامه نویسی عام به طور ساده برای برنامه نویسی توزیع شده مناسب نیست ـ به عبارتی در این مورد از Java باید استفاده کرد؟
-جواب: برنامه نویسیس عام کاری به زمان کامپایل یا زمان اجرا ندارد. مشکلی که من در OOP دیدم این است که نه تنها کند است بلکه امکان بیان ساده ترین الگوریتم ممکن در آن وجود ندارد. ببینید طرح max به این صورت است:
max: T x T -> T
این طرح را نمی توان در Java بیان کرد چونکه ارث بردن از کلاس یا اینترفیس T باعث می شود طرح max به صورت زیر در بیاید:
max: T' x T -> T
که لازم است بین دو طرح، تبدیل هم وردا (covariant transformation) صورت بگیرد. و همچنین [در مورد برنامه نویسی توزیع شده] باید بتوان یک نوع را از نوع دیگر استخراج کرد. یعنی مفهوم نوع مجازی که یک جدول-م (v-table) باشد که در آن خصوصیات نوع وجود داشته باشد.
-سوال: تکرارگر (iterator) چیست؟
تکرارگرها از ادغام دو نظریه به وجود آمده اند. اولین نظریه، نظریه نام است (handle, cookie, address). نام، چیزی است که به چیز دیگر اشاره می کند (*operator). که ما به این، نظریه ی تکرارگر بدیهی می گوییم. علاوه بر اینکه می توان به جایی که به آن اشاره شده دست یافت ، برای یک نام، تساوی منطبق با اصل زیر تعریف می شود:
i == j iff &*i == &*j
یعنی دو تکرارگر مساوی هستند اگر و تنها اگر آنها به یک شیء اشاره کنند. ( البته، تساوی، باید با تمام اصول موضوعه استاندارد منطبق باشد). نظریه دوم نظریه عملیات خَلَف (successor operation) یا (i++) می باشد که با اصلاح آن داریم : خَلَف - سَلَف (++ و --) و جمع ( ++ و -- و + و -‌) منطبق با اصول موضوعه استاندارد. و در واقع اشاره گر، مدلی از تکرارگر با دسترسی تصادفی (random access iterator) می باشد.
-سوال: بعضی بحث می کنند که اشاره گر، روشی برای جا انداختن هر چیز عجیب و غریب و ناگوار داخل حافظه است. Java و Delphi با ممنوع کردن اشاره گر کار درستی انجام دادند.
-جواب: اگر اشاره گر از این جهت ممنوع شود که از محاسبه با اشاره گر ها جلوگیری شود کار خوبی است. محاسبه با اشاره گر فقط باید در جایی که در C و ++C اجازه داده شده مورد استفاده قرار گیرد یعنی برای استفاده از اشاره گر به عنوان آرایه. اما ممنوع کردن اشاره گر به طور کلی حماقت است. اگر در یک زبان، اشاره گر یا ارجاع نباشد به عنوان یک مثال ساده نمی توانیم یک تابع swap عام ایجاد کنیم.
-سوال: واژه رسته (category) در بین جامعه ++C کاربردهای مختلفی دارد. بر چه اساس شما از اصطلاح رسته های تکرارگرها استفاده می کنید؟
-جواب: به معمولا برای این جور چیز ها از واژه مفهوم (concept) استفاده می کنم.
-سوال: من قبلا سعی کرده ام یک لیست پیوندی یک طرفه به سبک STL درست کنم. اما تصمیم گرفتم تابع عضو ()size را پیاده سازی نکنم. چون با این کار مجبور بودم یک متغیر اضافی داخل لیست پیوندی داشته باشم [که باعث مصرف حافظه می شد] که سایز لیست را در خودش ذخیره کند تا من با پیچیدگی زمانی ثابت بتوانم سایز لیست را به دست بیاورم. که این را بر اساس سی دی ++C انجام دادم. تصمیم درست چیست؟
-جواب: در لیستهای STL تابع ()size پیچیدگی زمانی خطی دارد. و تصمیم درستی هم بوده چون اگر کاربری هم بخواهد تعداد عناصر لیست را ذخیره داشته باشد کار ساده ای است، اما معمولا ما نیازی به آن نداریم در نتیجه با زمان خطی آن را به دست می آوریم(چون به ندرت استفاده می شود می توانیم به نوعی بگوییم زمان ثابت دارد). اما کمیته استاندارد اصرار کرد من آن را به زمان ثابت تغییر بدهم. من اختیاری نداشتم. نهایتا مجبور خواهیم شد این ملزومات را تغییر دهیم.
-سوال: من بررسی می کردم که چه طور می توانم یک درخت را به سبک STL ایجاد کنم که به چند مشکل برخوردم: هر گره یک پدر و دو فرزند دارد. حرکت به سمت پدر را با عملگر -- می شود نشان داد، اما برای حرکت به سمت فرزندان به دو عملگر ++ نیاز داشتم. تکرارگرها را چه طور می توانیم برای ساختمان های غیر خطی مثل درخت و گراف مورد استفاده قرار دهیم؟
-جواب: حتی روی یک ساختمان متوالی ما تکرارگرهای مختلفی می توانیم داشته باشیم. به عنوان مثال می توانم از تکرارگر معکوس (Reverse) نام ببرم. تکرارگرهای جهنده (Stride) هم خیلی مهم هستند و نهایتا داخل STL قرار خواهند گرفت.
-سوال: اعتراف می کنم که چیزی نمی دانم. تکرارگر جهنده چیست؟
-جواب: از i به سمت i+5 و سپس i+10 رفتن.
-سوال: چه تفاوتی با تکرارگر تصادفی دارد؟
-جواب: تکرارگر جهنده یک اداپتور تکرارگر است که محدوده (ابتدا و انتها) یک تکرارگر با دسترسی تصادفی را می گیرد و یک تکرارگر با دسترسی تصادفی را اراپه می کند که با اعمال ++ روی آن یک جهش انجام می شود ( توالی تکرارگر که n قدم بعد قرار دارد).
-سوال: این از چه نظر با مساله پیمایش درخت مرتبط می شود؟
-جواب: منظورم این نیست که تکرارگر جهنده یا تکرارگر معکوس ارتباطی با پیمایش درخت دارند بلکه منظورم این است که می توان برای هر ساختمان داده بر اساس جهت پیمایش، انواع مختلف تکرارگر داشت. مثلا در مورد درخت می توان پیمایش رو به عقب یا رو به جلو داشت.
-سوال: معمولا به این مشکل بر می خورم: آیا من این تابع را باید به صورت تابع عضو تعریف کنم یا یک تابع عام (سراسری)؟ در STL چه دیدگاهی پشت این تصمیم بوده؟
-جواب: تا جای ممکن تابع سراسری داشته باشید. اگر دو تابع begin و end سراسری بودند خیلی جالب تر می بود که باعث می شد آن را برای آرایه های C تعریف کنیم. خیلی جالب تر می بود اگر *operator سراسری می بود با تعریف پیش فرض زیر:

template <class T>
T& operator*(T& x) { return x;}

template <class T>
const T& operator*(const T& x) { return x;}

که به ما این امکان را می داد که به شکل زیر عمل کنیم:
copy(0, 25, ostream_iterator<int>("\n"));
در کل برای اشیایی که تکرارگر نباشند، *operator باید خود شیء را برگرداند. معنای یک چیز که نام [یا اشاره گر] نباشد عبارت است از خود همان چیز. حتی من عاشق این هستم که سازنده ها و مخرب را به شکل سراسری بنویسم. اگر زبان این اجازه را می داد می شد کارهای عجیبی انجام داد.
-سوال: اگر به شکلی که شما گفتید یک *operator عام ایجاد کنم و در برنامه ام تعریف زیر را داشته باشم:

template <class T> class SmartPtr {
T* ptr;
public:
SmartPtr(T* _ptr = 0) : ptr(_ptr){}
T* operator*() const {return ptr;}
// ...
};

با این حساب در کد زیر ابهام ایجاد نمی شود؟

int i=0;
SmartPtr<int> sp(&i);
int j= *i; // apply SmartPtr<int>::operator* or
// operator<SmartPtr<int>? both are user defined

-جواب: خیر ابهامی به وجود نمی آید. در مقابل تعریف سراسری، تعریف شما توسط کامپایلر انتخاب می شود. که این به علت تخصصی کردن جزئی (partial specialization) رخ می دهد.
-سوال: کنجکاو شدم که چرا در STL یک اداپتور «محتوی مرتب شده» sorted container وجود ندارد؟
-جواب: set یک محتوی مرتب شده است.
-سوال: set اداپتور نیست. جدای از محتوی هایی که از تکرارگر با دسترسی تصادفی پشتیبانی می کنند ، چرا می شود که ساختمان heap باشد اما محتوی مرتب شده نباشد؟
-جواب: در نظر داشته باشید که به علت اندازه STL مشکل یود که همه اینها را در آن بگذاریم. من مجبور شدم تعداد زیادی کامپوننت مفید را دور بریزم. (مثلا ببینید که بر سر hash table چه آمد).
-سوال: چرامستنداتی برا تابع adjust_heapــ در سرایند <heap.h> وجود ندارد. این تابع جهت استفاده از heap در الگوریتم Dijkstra لازم است.
-جواب: من دشواری های زیادی برای قرار دادن تابع های heap در استاندارد داشتم. در اصل می خواستم تمام تابعهای کمکی در STL کاملا در رویت باشد. اما سیاست اجازه نداد.
-سوال: پذیرش این که سیاستی در مورد تابعهای heap صورت گرفته برای من کمی سخت است.
-جواب: این در مورد یک تابع خاص نیست بلکه در مورد تعدادی از آنها است. شخص Bjarne مسوول این است که تعداد کامپوننت های STL را به نصف آن کاهش داده است. سعی او بر این بود که برای کم کردن انتقاد ها، حجم STL را تا جای ممکن کوچک کند.
-سوال: آیا تا به حال در ایتالیا برای کار یا تفریح آمده اید؟
-جواب: بله من ۱۰ روز در پیتزا بودم و از فلورانس و لوکا بازدید کردم. رویای من رفتن به آسیزی است. من قلبا فرانسیسکن هستم. من در پرده دوم اپرای توسکا و پرده سوم اپرای لاتراویاتا گریه کردم. من دانته (به زبان ایتالیایی!) را در بسترم مطالعه می کنم. من عاشق پاستا، پروسیوتو و کیانتی هستم. با اینکه من یک سنت گرا هستم، بیشتر شبیه پاپ ژان بیست و سوم هستم تا پاپ پیوس دوزادهم.
-سوال: اگر شما دانته نسخه اصلی را می توانید بخوانید باید خیلی خوب ایتالیایی بلد باشید. چون تعداد کمی ایتالیایی ها این توانایی را دارند!
-جواب: ایتالیایی من خیلی ضعیف است. من دانته ایتالیایی را به این صورت می خوانم که ترجمه آن در جلو من است. یک قطعه از متن را با صدای بلند به زبان ایتالیایی می خوانم سپس به ترجمه اش نگاه می کنم.
-سوال: الکس از شما خیلی ممنونم. امیدوارم به ایتالیا بیایید و آسیزی را ببینید و در شهر قدیمی آسیزی ـ شاید جذاب ترین شهر قرون وسطی ایتالیا ـ دانته را بخوانید.