pg.gimran.org

Ботаникларның үч алуы

Пол Грэмның «Ботаникларның үч алуы» эссесы тәрҗемәсе. Төп нөсхә: https://paulgraham.com/icad.html. Машина тәрҗемәсе (Gemini).

Translation of Paul Graham's essay 'Revenge of the Nerds'. Original: https://paulgraham.com/icad.html. Machine translation (Gemini).

Программа тәэминаты тармагында очлы башлы галимнәр белән алардан бер дә калышмый торган башка бер көч — очлы чәчле босслар арасында туктаусыз көрәш бара. Очлы чәчле боссның кем икәнен барыгыз да беләсездер инде? Минемчә, технология дөньясындагы күпчелек кеше бу мультфильм персонажын танып кына калмый, ә үз компанияләрендә аның прототибы булган чын кешене дә белә.

Очлы чәчле босс үз эчендә гадәттә аерым очрый торган, ләкин бергә бик сирәк күзәтелә торган ике сыйфатны могҗизалы рәвештә берләштерә: (а) ул технологияләр турында берни дә белми, һәм (б) аның бу хакта бик нык фикере бар.

Әйтик, сезгә берәр программа тәэминаты язарга кирәк ди. Очлы чәчле босс бу программаның ничек эшләргә тиешлеге турында һич белми, бер программалаштыру телен икенчесеннән аера алмый, әмма сезнең аны кайсы телдә язарга тиешлегегезне төгәл белә. Нәкъ шулай. Ул аны Java телендә язарга тиешсез дип саный.

Ни өчен ул алай уйлый? Әйдәгез, очлы чәчле боссның миенә күз салыйк. Ул якынча болайрак фикер йөртә: Java — стандарт. Мин моны төгәл беләм, чөнки матбугатта гел шул хакта укыйм. Ул стандарт булгач, аны кулланганым өчен башым бәлагә тарымас. Димәк, Java программачылары да һәрвакыт күп булачак, шуңа күрә әгәр хәзер миндә эшләүче программачылар, ниндидер серле сәбәпләр аркасында гел эштән китеп барган кебек, эштән китсәләр, мин аларны җиңел генә алмаштыра алам.

Ярар, бу артык акылсыз да яңгырамый төсле. Ләкин моның барысы да әйтелмәгән бер гөманга нигезләнгән, ә ул гөман ялган булып чыга. Очлы чәчле босс барлык программалаштыру телләре дә якынча тигез дип саный. Әгәр бу дөрес булса, ул тулысынча хаклы булыр иде. Әгәр телләр барысы да тигез икән, әлбәттә, башкалар нинди тел кулланса, шуны куллан инде.

Ләкин барлык телләр дә бертигез түгел, һәм мин сезгә моны хәтта алар арасындагы аермаларга да кермичә исбат итә алам дип уйлыйм. Әгәр сез 1992 елда очлы чәчле босстан программаны кайсы телдә язарга кирәк дип сораган булсагыз, ул бүгенге кебек үк бернинди икеләнүсез җавап бирер иде: программа тәэминатын C++ телендә язарга кирәк. Ләкин телләр барысы да бертигез икән, ни өчен очлы чәчле боссның фикере үзгәрергә тиеш? Хәтта ни өчен Java телен уйлап табучылар яңа тел булдырырга бөтенләй мәшәкатьләнергә тиеш булган?

Күрәсең, әгәр сез яңа тел тудырасыз икән, димәк, сез аны кешеләрдә булган нәрсәгә караганда ниндидер яктан яхшырак дип уйлыйсыз. Һәм чыннан да, Гослинг Java турындагы беренче ак кәгазендә ачык аңлата: Java теле C++ теленең кайбер проблемаларын хәл итү өчен эшләнгән. Менә күрәсез: телләр барысы да бертигез түгел. Әгәр сез очлы чәчле боссның башыннан чыгып Java-га таба, аннары Java тарихы аша аның тамырларына таба юл тотсагыз, сез үзегез башлаган гөманга капма-каршы булган фикергә килеп җитәсез.

Соң, кем хаклы? Джеймс Гослингмы, әллә очлы чәчле боссмы? Һич гаҗәп түгел, Гослинг хаклы. Кайбер мәсьәләләр өчен кайбер телләр башкаларга караганда чыннан да яхшырак. Һәм беләсезме, бу бик кызыклы сораулар тудыра. Java теле C++ теленә караганда кайбер мәсьәләләрдә яхшырак булсын өчен эшләнгән. Нинди мәсьәләләрдә? Кайчан Java яхшырак, ә кайчан C++? Башка телләр икесеннән дә яхшырак булган очраклар бармы?

Сез бу сорау өстендә уйлана башлауга, чын мәгънәсендә кыен хәлгә тарыйсыз. Әгәр очлы чәчле босс бу мәсьәләне бөтен катлаулылыгы белән уйларга мәҗбүр булса, аның мие шартлар иде. Барлык телләрне тигез дип санганда, аңа бары тик иң танылган һәм көчле булып күренгәнен сайларга гына кала; ә бу технологиягә караганда күбрәк мода соравы булганлыктан, хәтта ул да дөрес җавап таба аладыр. Ләкин телләр төрлечә икән, аңа кинәт ике тигезләмәне бергә чишәргә туры килә: ул үзе берни аңламаган ике нәрсә арасында — үз мәсьәләсен чишү өчен әйдәп баручы егермеләп телнең чагыштырмача яраклылыгы һәм аларның һәрберсе өчен программачылар, китапханәләр һ.б. табу ихтималы арасында — оптималь баланс табарга тырышырга тиеш була. Әгәр ишекнең аргы ягында менә шул торса, очлы чәчле боссның аны ачарга теләмәвенә бернинди дә гаҗәпләнәсе юк.

Барлык программалаштыру телләре дә тигез дип ышануның начар ягы шул: бу дөрес түгел. Ләкин уңай ягы шунда: ул сезнең тормышыгызны күпкә гадиләштерә. Һәм минемчә, бу идеянең шулай киң таралуының төп сәбәбе дә нәкъ менә шунда. Бу бик уңайлы уй.

Без Java-ның бик әйбәт булырга тиешлеген беләбез, чөнки ул бит шәп, яңа программалаштыру теле. Әллә алай түгелме? Программалаштыру телләре дөньясына читтән карасагыз, Java иң соңгы яңалык кебек тоела. (Бик ерактан караганда, Sun компаниясе түләгән зур, ялтыравыклы билбордтан башка берни күренми.) Ләкин бу дөньяга якыннанрак күз салсагыз, шәплекнең төрле дәрәҗәләре барлыгын күрерсез. Хакерлар субкультурасында Perl исемле башка бер тел бар, һәм ул Java-га караганда күпкә шәбрәк санала. Мәсәлән, Slashdot сәхифәсе Perl ярдәмендә ясалган. Ул егетләрнең Java Server Pages кулланганын күрмәссез, мөгаен. Ләкин Perl-га бераз өстәнрәк карарга яратучы Python дигән тагын бер яңарак тел бар, һәм чиратта торучы башкалар да җитәрлек.

Әгәр сез бу телләргә тәртип буенча карасагыз — Java, Perl, Python — бер кызыклы закончалык күрерсез. Дөресрәге, әгәр сез Lisp хакеры булсагыз, моны күрерсез. Аларның һәрберсе барган саен күбрәк Lisp-ка охшый бара. Хәтта Lisp хакерлары ялгыш дип санаган үзенчәлекләрне дә Python үзенә күчерә. Гади Lisp программаларын сез сүзгә-сүз диярлек юл саен Python-га тәрҗемә итә аласыз. Хәзер 2002 ел, һәм программалаштыру телләре ниһаять 1958 елга куып җитеп килә диярлек.

Математиканы куып җитү

Мин шуны әйтмәкче булам: Lisp телен Джон Маккарти 1958 елда ачкан, һәм популяр программалаштыру телләре ул вакытта ул уйлап тапкан фикерләрне хәзер генә куып җитеп килә.

Бу ничек дөрес булырга мөмкин? Компьютер технологияләре бик тиз үзгәрә торган нәрсә түгелмени? Ягъни, 1958 елда санак дигәнең суыткыч зурлыгындагы алпавыт булып, исәпләү егәрлеге кул сәгатеннән дә ким булган бит. Шулхәтле иске технология ничек актуаль була алсын, ә иң соңгы яңалыклардан өстен тору турында сүз дә була алмый бит инде?

Мин сезгә ничек икәнен сөйлим. Чөнки Lisp, асылда, программалаштыру теле булсын өчен эшләнмәгән иде, ким дигәндә, без бүген күздә тоткан мәгънәдә түгел. Программалаштыру теле дигәндә без санатка нәрсә эшләргә кирәклеген аңлату коралын күз алдында тотабыз. Ахыр чиктә Маккарти бу мәгънәдә тел булдырырга ниятләгән, ләкин безнең кулга килеп җиткән чын Lisp аның теоретик күнегү сыйфатында эшләгән аерым бер әйберенә нигезләнгән иде — Тьюринг машинасына караганда уңайлырак альтернатива табу омтылышы.

Lisp-ның Тьюринг машиналарына караганда җыйнаграк булуын күрсәтүнең тагын бер юлы — универсаль Lisp функциясен язу һәм аның универсаль Тьюринг машинасы тасвирламасына караганда кыскарак һәм аңлаешлырак булуын күрсәтү иде. Бу eval дигән Lisp функциясе иде..., ул Lisp аңлатмасының кыйммәтен исәпли.... eval-ны язу өчен Lisp функцияләрен Lisp мәгълүматлары буларак чагылдыручы тамгалау системасын уйлап табу таләп ителде, һәм бу тамгалау фәнни мәкалә максатлары өчен генә уйланылган иде, аны гамәлдә Lisp программаларын белдерү өчен кулланырлар дигән уй бөтенләй юк иде.

Шуннан соң нәрсә булды дисәгез, 1958 елның ахырында Маккартиның аспирантларыннан берсе булган Стив Рассел eval төшенчәсенең бу билгеләмәсенә караган да, әгәр аны машина теленә тәрҗемә итсә, килеп чыккан нәрсәнең Lisp интерпретаторы булачагын аңлаган.

Ул вакытта бу зур көтелмәгән хәл булган. Менә соңрак бер интервьюсында Маккарти бу хакта нәрсә дигән:

Стив Рассел: «Тыңла әле, нигә миңа бу eval-ны программалаштырмаска?..» — диде, ә мин аңа: «Һо-һо, син теория белән практиканы бутыйсың, бу eval санау өчен түгел, уку өчен каралган», — дидем. Ләкин ул барыбер эшләде. Ягъни, минем мәкаләдәге eval-ны, хаталарын төзәтеп, [IBM] 704 машина кодына компиляцияләде һәм шуннан соң моны Lisp интерпретаторы дип игълан итте, һәм ул чыннан да шулай иде. Менә шул мизгелдә Lisp асылда бүгенге төсен алды....

Кинәт, нибары берничә атна эчендә, минемчә, Маккарти үзенең теоретик язмасының реаль программалаштыру теленә әверелгәнен күрде — өстәвенә, ул уйлаганнан күпкә көчлерәк телгә.

Димәк, 1950 еллардагы бу телнең искермәвенең кыскача аңлатмасы шул: ул гади технология түгел, ә математика иде, ә математика искерми. Lisp-ны 1950 еллар аппаратурасы белән түгел, ә, әйтик, 1960 елда ачылган һәм бүген дә иң тиз универсаль сортлау алгоритмы булып кала бирүче Quicksort алгоритмы белән чагыштырырга кирәк.

1950 еллардан исән калган тагын бер тел бар, ул — Fortran, һәм ул тел дизайнына капма-каршы якын килүне күрсәтә. Lisp көтмәгәндә программалаштыру теленә әйләнгән теория кисәге иде. Fortran исә махсус программалаштыру теле буларак эшләнде, әмма хәзерге караш белән караганда бик түбән дәрәҗәдәге тел иде.

1956 елда эшләнгән тел, Fortran I, бүгенге Fortran-нан бөтенләй башка нәрсә иде. Fortran I асылда математика өстәлгән ассемблер теле иде. Кайбер яклары буенча ул хәтта соңрак чыккан ассемблер телләреннән дә көчсезрәк иде; анда, мәсәлән, аспрограммалар бөтенләй юк иде, бары тармакланулар гына бар иде. Бүгенге Fortran, мөгаен, Fortran I-гә караганда Lisp-ка якынрактыр инде.

Lisp һәм Fortran ике аерым эволюцион агачның кәүсәләре иде: берсенең тамырлары математикада, икенчесенең санак архитектурасында иде. Шул вакыттан бирле бу ике агач бер-берсенә якыная бара. Lisp көчле булып башланды һәм киләсе егерме ел эчендә тиз эшләргә өйрәнде. Мейнстрим телләр дип аталганнары тиз булып башланды һәм киләсе кырык ел эчендә әкренләп көчәя барды, һәм хәзер аларның иң алдынгылары Lisp-ка шактый якынлашты. Якын, ләкин аларга барыбер берничә нәрсә җитми әле....

Lisp-ны нәрсә аерып торган

Уйлап табылгач, Lisp тугыз яңа идеяне үз эченә алган иде. Аларның кайберләрен без хәзер гадәти дип кабул итәбез, кайберләре алдынгырак телләрдә генә очрый, ә икесе әле дә тик Lisp-ка гына хас. Бу тугыз идея, аларның мейнстримга үтеп керү тәртибендә, түбәндәгеләр: Шартлы конструкцияләр. Шарт — ул if-then-else структурасы. Хәзер без моны табигый дип күрәбез, ләкин Fortran I-дә алар бөтенләй юк иде. Анда бары тик машина инструкциясенә нык бәйләнгән шартлы goto гына бар иде.

Функция тибы. Lisp-та функцияләр бөтен саннар яки юллар кебек үк гади мәгълүмат тибы булып тора. Аларның литерал тасвирламасы бар, аларны үзгәрешлеләрдә сакларга, аргумент буларак тапшырырга һәм башкаларны эшләргә була.

Рекурсия. Lisp аны хуплаган беренче программалаштыру теле булды.

Динамик типлаштыру. Lisp-та барлык үзгәрешлеләр дә, асылда, күрсәткечләр (указательләр) булып тора. Типка үзгәрешлеләр түгел, кыйммәтләр ия, һәм үзгәрешлеләргә кыйммәт бирү яки бәйләү күрсәткечләрнең үзләрен күчерүне аңлата, алар күрсәткән нәрсәне түгел.

Чүп җыю (Garbage collection).

Аңлатмалардан торган программалар. Lisp программалары — һәрберсе кыйммәт кайтара торган аңлатмалар агачы. Бу аңлатмалар (expressions) белән операторларны (statements) аера торган Fortran һәм аннан соңгы күпчелек телләргә капма-каршы килә.

Fortran I-дә бу аерма булу бик табигый иде, чөнки сез бер операторны икенчесе эченә кертә алмый идегез. Шуңа күрә математика эшләсен өчен аңлатмалар кирәк булса да, башка берәр нәрсәнең кыйммәт кайтаруында бернинди мәгънә юк иде, чөнки ул кыйммәтне көтеп торучы берни булмаган.

Блоклы структуралы телләр барлыкка килү белән бу чикләү бетте, ләкин инде соң иде. Аңлатмалар белән операторлар арасындагы аерма тамыр җәйгән иде. Ул Fortran-нан Algol-га, аннары аларның икесенең дә варисларына күчте.

Символ тибы. Символлар — асылда хэш-таблицада сакланган юлларга күрсәткечләр. Шуңа күрә тигезлекне һәр символны чагыштырып түгел, ә күрсәткечне чагыштырып тикшерергә була.

Символлар һәм константалар агачын кулланып кодны язу ысулы.

Бөтен тел һәрвакыт кулланылышта. Уку вакыты (read-time), компиляция вакыты (compile-time) һәм эшләү вакыты (runtime) арасында реаль аерма юк. Сез уку вакытында кодны компиляцияли яки эшләтә аласыз, компиляция вакытында укый яки эшләтә аласыз, ә эшләү вакытында укый яки компиляцияли аласыз.

Уку вакытында кодны эшләтү кулланучыларга Lisp синтаксисын яңадан көйләү мөмкинлеге бирә; компиляция вакытында кодны эшләтү — макросларның нигезе; эшләү вакытында компиляция ясау Lisp-ның Emacs кебек программаларда киңәйтү теле буларак кулланылуына юл ача; ә эшләү вакытында уку программаларга s-аңлатмалар ярдәмендә аралашырга мөмкинлек бирә (бу идея күптән түгел XML буларак яңадан уйлап табылды). Lisp беренче тапкыр барлыкка килгәндә, бу идеяләр 1950 еллар ахырындагы җиһазлар белән билгеләнгән гадәти программалаштыру практикасыннан бик ерак иде. Вакыт узу белән, популяр телләр чылбырында гәүдәләнгән төп тел акрынлап Lisp юнәлешендә үсә барды. 1-5 нче идеяләр хәзер киң таралган. 6 нчысы мейнстримда күренә башлады. Python-да 7 нченең бер төре бар, гәрчә моның өчен махсус синтаксис күренмәсә дә.

8 нче төргә килгәндә, бу бәлки иң кызыклысыдыр. 8 һәм 9 нчы идеяләр Lisp-ка очраклы рәвештә генә кергән, чөнки Стив Рассел Маккарти тормышка ашырырга бөтенләй ниятләмәгән нәрсәне тормышка ашырган. Ләкин нәкъ менә шушы идеяләр Lisp-ның сәер кыяфәте өчен дә, аның иң үзенчәлекле яклары өчен дә җаваплы булып чыккан. Lisp аның сәер синтаксисы булганга түгел, ә гомумән бернинди синтаксисы булмаганга сәер күренә; сез программаларны башка телләрнең синтаксик анализы вакытында пәрдә артында төзелә торган агачлар аша турыдан-туры белдерәсез, ә бу агачлар Lisp-ның мәгълүмат структуралары булган исемлекләрдән тора.

Телне үз мәгълүмат структуралары аша белдерү бик көчле мөмкинлек булып чыга. 8 һәм 9 нчы идеяләр бергәләп сезгә программалар яза торган программалар ясау мөмкинлеге бирә. Бу бик сәер уй кебек яңгырарга мөмкин, ләкин Lisp-та бу — көндәлек гадәти нәрсә. Моны эшләүнең иң таралган юлы — макрос дип аталган нәрсә ярдәмендә.

«Макрос» термины Lisp-та башка телләрдәге мәгънәне аңлатмый. Lisp макросы кыскартмадан алып яңа тел өчен компиляторга кадәр теләсә нәрсә булырга мөмкин. Әгәр сез Lisp-ны чынлап аңларга яки үз программалаштыру офыкларыгызны киңәйтергә теләсәгез, мин макрослар турында күбрәк белергә киңәш итәр идем.

Макрослар (Lisp мәгънәсендә), минем белүемчә, әле дә Lisp-ка гына хас. Моның сәбәбе бер яктан шул: макросларга ия булу өчен сезгә телегезне Lisp кебек сәер итәргә туры киләчәктер. Икенче яктан, бәлки, сез шул соңгы көч өстәмәсен кушсагыз, сез инде үзегезне яңа тел уйлап таптым дип атый алмаячаксыз, бары тик Lisp-ның яңа диалектын гына ясаган буласыз.

Мин моны шаяртып кына әйтәм, ләкин бу бик дөрес. Әгәр сез үзегезгә car, cdr, cons, quote, cond, atom, eq булган һәм функцияләр исемлек рәвешендә бирелә торган тел билгеләсәгез, сез аңардан калган бөтен Lisp-ны төзи аласыз. Бу чынлыкта Lisp-ның төп сыйфаты: Маккарти Lisp-ка бүгенге формасын нәкъ менә шулай булсын өчен биргән.

Телләрнең әһәмияте кайда

Алайса, әйтик, Lisp чыннан да киң таралган телләр асимптотик якынлаша торган чик булып тора ди — бу сезгә программа тәэминаты язу өчен нәкъ менә аны кулланырга кирәк дигәнне аңлатамы? Көчсезрәк тел кулланып сез күпме югалтасыз? Кайвакыт инновацияләрнең иң кырыенда йөрмәү акыллырак түгелмени? Һәм популярлык ниндидер дәрәҗәдә үзеннән-үзе акланмыймыни? Мәсәлән, очлы чәчле боссның программачыларны табу җиңел булган телне сайларга теләве дөрес түгелмени?

Әлбәттә, программалаштыру телен сайлау артык мөһим булмаган проектлар бар. Гадәттә, кушымта никадәр катлаулырак һәм таләпчәнрәк булса, көчле тел кулланудан шулкадәр күбрәк файда аласыз. Ләкин бик күп проектлар бөтенләй таләпчән түгел. Күпчелек программалаштыру кечкенә бәйләүче программалар (ябыштыргычлар) язудан торадыр, ә андый кечкенә программалар өчен сез үзегез белгән һәм сезгә кирәкле эш өчен яхшы китапханәләре булган теләсә нинди телне куллана аласыз. Әгәр бер Windows кушымтасыннан икенчесенә мәгълүмат күчерергә генә кирәк булса, һичшиксез, Visual Basic кулланыгыз.

Lisp телендә дә кечкенә ябыштыргыч программалар язарга була (мин аны өстәл калькуляторы урынына кулланам), ләкин Lisp кебек телләрнең иң зур өстенлеге спектрның икенче ягында — кырыс көндәшлек шартларында авыр мәсьәләләрне чишү өчен катлаулы программалар язарга кирәк булган җирдә күренә. Моңа яхшы мисал — ITA Software ширкәтенең Orbitz өчен лицензияләгән авиабилетлар бәясен эзләү программасы. Бу егетләр Travelocity һәм Expedia кебек ике зур, тамыр җәйгән көндәш өстенлек иткән базарга кереп, аларны технологик яктан тулысынча тар-мар иткән кебек булдылар.

ITA кушымтасының үзәгендә 200 000 юллык Common Lisp программасы тора, ул көндәшләренә караганда берничә мәртәбә күбрәк вариантларны тикшерә, ә теге көндәшләре исә, күрәсең, һаман да мейнфрейм заманындагы программалаштыру алымнарын куллана. (Гәрчә ITA да, ниндидер мәгънәдә, мейнфрейм чорындагы телне кулланса да.) Мин ITA кодларын беркайчан да күргәнем булмады, ләкин аларның иң алдынгы хакерларының берсе әйтүенчә, алар макросларны бик күп кулланалар, һәм мин моңа һич гаҗәпләнмим.

Үзәккә омтылу көчләре

Мин сирәк технологияләрне куллануның бернинди дә зыяны юк димим. Очлы чәчле боссның моның турында борчылуы бөтенләй үк нигезсез түгел. Ләкин ул куркынычларны аңламагач, аларны чиктән тыш арттырып күрсәтергә омтыла.

Мин киң таралмаган телләрне кулланудан туа торган өч проблеманы күзаллый алам. Сезнең программалар башка телләрдә язылган программалар белән начар эшләргә мөмкин. Сезнең карамакта китапханәләр азрак булырга мөмкин. Һәм программачылар яллау кыен булырга мөмкин.

Бу проблемаларның һәрберсе никадәр җитди? Беренчесенең мөһимлеге бөтен система өстеннән сезнең контролегез булу-булмауга бәйле. Әгәр сез ерактагы кулланучының компьютерында хаталы, ябык операцион система өстендә (исемнәрне атамыйм) эшләргә тиешле программа язасыз икән, кушымтаны шул ОС телендә язуның өстенлекләре булырга мөмкин. Ләкин әгәр бөтен система сезнең контролдә булса һәм сездә барлык өлешләрнең башлангыч кодлары булса, ITA-да кебек, сез теләгән телне куллана аласыз. Берәр туры килмәү килеп чыкса, аны үзегез төзәтә аласыз.

Серверларга нигезләнгән кушымталарда сез иң алдынгы технологияләрне иркен куллана аласыз, һәм бу Джонатан Эриксон «программалаштыру телләренең яңарышы» дип атаган күренешнең төп сәбәбедер. Менә ни өчен без хәтта Perl һәм Python кебек яңа телләр турында ишетәбез. Без бу телләр турында кешеләр алар ярдәмендә Windows кушымталары язган өчен түгел, ә серверларда кулланган өчен ишетәбез. Һәм программа тәэминаты өстәл санакларыннан китеп серверларга күчкән саен (хәтта Microsoft та бу киләчәк белән килешкән кебек), уртача технологияләрне куллану буенча басым да кимегәннән-кими барачак.

Китапханәләргә килгәндә, аларның әһәмияте дә кушымтага бәйле. Артык катлаулы булмаган мәсьәләләр өчен китапханәләрнең булуы телнең үз көченнән өстенрәк булырга мөмкин. Үз-үзен аклау ноктасы кайда соң? Төгәл генә әйтүе кыен, ләкин ул кайда гына булса да, сез «җитди кушымта» дип атарлык әйберләрдән түбәнрәк тора. Әгәр берәр ширкәт үзен программа тәэминаты бизнесында дип саный икән һәм үз продукцияләренең берсе булачак кушымта яза икән, моңа берничә хакер җәлеп ителәчәк һәм язу кимендә алты ай вакытны алачак. Андый зурлыктагы проектта көчле телләр әзер китапханәләрнең уңайлыгыннан өстен чыга башлый, мөгаен.

Очлы чәчле боссның өченче борчуы — программачылар яллау кыенлыгы — минемчә, ялган куркыныч (юри чыгарылган сылтау). Чынлыкта сезгә ничә хакер ялларга кирәк соң? Хәзер барыбыз да беләбез инде: программа тәэминатын уннан азрак кешедән торган төркемнәр иң яхшы эшләп чыгара. Ә сез кеше ишеткән теләсә нинди тел өчен андый күләмдә хакерлар табуда бернинди дә авырлык кичермәскә тиешсез. Әгәр сез ун Lisp хакеры таба алмыйсыз икән, димәк, сезнең компания программа ясау өчен туры килми торган шәһәрдә урнашкан.

Чынлыкта, көчлерәк тел сайлау сезгә кирәк булган төркемнең күләмен киметә генә, чөнки (а) көчлерәк тел куллансагыз, сезгә хакерлар күп кирәк булмаячак, һәм (б) алдынгырак телләрдә эшләүче хакерлар акыллырак булырга охшаган.

Мин сезгә «стандарт» саналган технологияләрне кулланырга дип зур басым ясалмаячак дип әйтмим. Viaweb-та (хәзерге Yahoo Store) без Lisp кулланганга күрә венчур инвесторлар һәм потенциаль сатып алучылар арасында аптырау уяттык. Ләкин без Sun кебек «сәнәгать куәтендәге» серверлар урынына гади Intel тартмаларын кулланган өчен, Windows NT кебек чын коммерцияле ОС урынына FreeBSD дип аталган, ул вакытта әле аз билгеле ачык кодлы Unix вариантын сайлаган өчен, хәзер беркем дә хәтерләми торган SET дигән электрон сәүдә стандартына кул селтәгән өчен һ.б. аркасында да гаҗәпләнү уяткан идек.

Костюм кигән түрәләрнең сезнең өчен техник карарлар кабул итүенә юл куярга ярамый. Безнең Lisp куллануыбыз кайбер потенциаль сатып алучыларны сагайтырга мәҗбүр иттеме? Кайберләрен, бераз гына, ләкин әгәр без Lisp кулланмаган булсак, аларны безне сатып алырга теләрлек программаны гомумән яза алмас идек. Аларга аномалия булып күренгән нәрсә чынлыкта сәбәп һәм нәтиҗә иде.

Әгәр стартап башлыйсыз икән, үз продуктыгызны венчур инвесторларга яки потенциаль сатып алучыларга ярар өчен эшләмәгез. Үз продуктыгызны кулланучыларга ошарлык итеп эшләгез. Әгәр кулланучыларны яулап алсагыз, калган барысы да үзеннән-үзе киләчәк. Ә яулый алмасагыз, сезнең технология сайлавыгызның ни дәрәҗәдә тынычландыргыч ортодоксаль булуы беркемне дә кызыксындырмаячак.

Уртача булуның бәясе

Көчсезрәк тел кулланып сез күпме югалтасыз? Бу хакта чынлыкта кайбер мәгълүматлар бар.

Көчнең иң уңайлы үлчәме, мөгаен, кодның күләмедер. Югары дәрәҗәдәге телләрнең мәгънәсе — сезгә зуррак абстракцияләр бирүдә, ягъни билгеле бер зурлыктагы диварны өю өчен кирпечләрне азрак таләп итә торган зуррак кирпечләр бирүдә. Димәк, тел никадәр көчлерәк булса, программа шулкадәр кыскарак була (билгеле, символлар саны буенча гына түгел, ә аерым элементлар ягыннан).

Көчлерәк тел кыскарак программалар язарга ничек ярдәм итә? Тел мөмкинлек бирсә, сез куллана ала торган бер ысул — астан өскә программалаштыру (bottom-up programming). Сез кушымтагызны төп телдә генә язу урынына, төп тел өстенә сезнеке кебек программалар язу өчен тел корасыз, аннары үз программагызны шунда язасыз. Берләштерелгән код бөтен программаны төп телдә язганга караганда күпкә кыскарак булырга мөмкин — чынлыкта, күпчелек кысу алгоритмнары шулай эшли. Астан өскә язылган программаны үзгәртү дә җиңелрәк булырга тиеш, чөнки күп очракта тел катламын бөтенләй үзгәртәсе булмый.

Код күләме бик мөһим, чөнки программаны язу өчен кирәк булган вакыт күбесенчә аның озынлыгына бәйле. Әгәр программагыз икенче бер телдә өч тапкыр озынрак булса, аны язу өч тапкыр күбрәк вакыт алачак — һәм сез моны күбрәк кеше яллап чишә алмыйсыз, чөнки билгеле бер зурлыктан соң яңа эшчеләр бары тик зыянга гына эшли башлый. Фред Брукс бу күренешне үзенең танылган The Mythical Man-Month китабында тасвирлаган иде, һәм мин күргән бөтен нәрсә аның сүзләрен раслап кына килде.

Соң, әгәр сез программаларыгызны Lisp-та язсагыз, алар күпмегә кыскарак була? Мәсәлән, Lisp һәм C телләрен чагыштырганда мин ишеткән саннарның күбесе 7-10 тапкыр тирәсендә иде. Ләкин New Architect журналында ITA турында чыккан соңгы мәкаләдә: «Lisp-ның бер юлы C теленең 20 юлын алмаштыра ала», — диелгән иде, һәм бу мәкаләдә ITA президентыннан күп өзекләр китерелгәнгә күрә, алар бу санны ITA-дан алган дип уйлыйм. Әгәр шулай булса, без аңа ышана алабыз; ITA программа тәэминаты Lisp белән беррәттән бик күп C һәм C++ телләрен дә үз эченә ала, шуңа күрә алар тәҗрибәгә таянып сөйлиләр.

Минем уйлавымча, бу тапкырлаучылар хәтта даими дә түгел. Авыррак мәсьәләләргә очраганда һәм акыллырак программачыларыгыз булганда, алар тагын да арта дип саныйм. Чыннан да яхшы хакер яхшырак кораллардан күбрәк нәтиҗә сыгып чыгара ала.

Ничек кенә булмасын, шул кәкредәге бер нокта буларак караганда: әгәр сез ITA белән көндәшлек итә башласагыз һәм үз программагызны C телендә язарга карар кылсагыз, алар программа тәэминатын сезгә караганда егерме тапкыр тизрәк ясый алачак. Әгәр сез бер яңа үзенчәлеккә бер ел сарыф итсәгез, алар аны өч атнадан да азрак вакыт эчендә кабатлый алачак. Ә әгәр алар яңа нәрсәне эшләүгә нибары өч ай сарыф итсә, сездә дә шул нәрсәнең барлыкка килүенә кадәр биш ел вакыт узачак.

Һәм беләсезме нәрсә? Бу әле иң яхшы сценарий. Сез код күләме нисбәтләре турында сөйләгәндә, сез программаны чыннан да зәгыйфьрәк телдә язып була дип күздә тотасыз. Ләкин чынлыкта программистларның мөмкинлекләре чикле. Әгәр сез катлаулы мәсьәләне артык түбән дәрәҗәле тел ярдәмендә чишәргә тырышсагыз, берьюлы башыгызда тотарга кирәк булган мәгълүмат күләме чиктән ашкан ноктага җитәсез.

Шуңа күрә мин, ITA-ның уйдырма көндәшенә ITA Lisp телендә өч ай эчендә яза алган нәрсәне кабатлау өчен биш ел кирәк булыр иде, дигәндә, барысы да яхшы барган очракта биш ел кирәк булуын күздә тотам. Чынлыкта, күпчелек компанияләрдә эшләр барышын исәпкә алганда, биш ел таләп итә торган теләсә кайсы эшкәртү проекты, мөгаен, беркайчан да тәмамланмаячак.

Бу бик үзенчәлекле очрак икәнен таныйм. ITA-ның хакерлары гадәттән тыш акыллы кебек, ә C — шактый түбән дәрәҗәле тел. Ләкин көндәшлек базарда ике яки өчкә бер чагыштырма да сезнең һәрвакыт артта калуыгызны гарантияләү өчен җитәрлек булыр иде.

Рецепт

Бу — очлы чәчле җитәкче хәтта уйларга да теләми торган мөмкинлекләрнең берсе. Һәм шуңа күрә аларның күбесе уйламый да. Чөнки, беләсезме, эшкә килеп җиткәндә, очлы чәчле җитәкче, моның аның гаебе булуын беркем дә исбатлый алмаса, үз компаниясенең җиңелүенә каршы түгел. Шәхсән аның өчен иң хәвефсез план — көтүнең үзәгенә якынрак тору.

Зур оешмаларда бу карашны тасвирлау өчен кулланыла торган гыйбарә — «индустриянең алдынгы тәҗрибәсе» (industry best practice). Аның максаты — очлы чәчле җитәкчене җаваплылыктан яклау: әгәр ул «индустриянең алдынгы тәҗрибәсе» саналган нәрсәне сайласа, һәм компания оттырса, аны гаепләп булмый. Ул түгел, ә индустрия сайлаган.

Минемчә, бу термин башта бухгалтерия методларын һәм шуңа охшаш нәрсәләрне тасвирлау өчен кулланылган. Аның мәгънәсе якынча шул: сәер бернәрсә дә эшләмәгез. Һәм бухгалтериядә бу, мөгаен, яхшы идеядыр. «Алдынгы» һәм «бухгалтерия» терминнары бергә яхшы яңгырамый. Ләкин сез бу критерийны технология турындагы карарларга күчергәндә, сез ялгыш җаваплар ала башлыйсыз.

Технология еш кына алдынгы булырга тиеш. Программалаштыру телләрендә, Эранн Гат билгеләп үткәнчә, «индустриянең алдынгы тәҗрибәсе» сезгә иң яхшысын түгел, ә уртачасын гына бирә. Карар сезне агрессиврак көндәшләр тизлегенең бер өлеше белән генә программа белән тәэмин ителеш ясауга китергәндә, «алдынгы тәҗрибә» — дөрес булмаган атама.

Шулай итеп, бездә бик кыйммәтле дип санаган ике мәгълүмат бар. Чынлыкта, мин моны үз тәҗрибәмнән беләм. 1 нче номер: телләр үз көче буенча аерыла. 2 нче номер: күпчелек менеджерлар моны аңлы рәвештә игътибарсыз калдыра. Бергәләп, бу ике факт туры мәгънәсендә акча эшләү рецепты булып тора. ITA — бу рецептның эш итү мисалы. Әгәр сез программа тәэминаты бизнесында җиңәргә теләсәгез, сез таба алган иң катлаулы проблеманы чишәргә тотыныгыз, сез таба алган иң көчле телне кулланыгыз һәм көндәшләрегезнең очлы чәчле җитәкчеләре уртачалыкка кайтканын көтегез.

Кушымта: Көч

Программалаштыру телләренең чагыштырма көче турында нәрсә әйтергә теләгәнемне күрсәтү өчен, түбәндәге мәсьәләне карагыз. Без аккумуляторлар тудыручы функция язарга телибез — бу n санын алучы һәм икенче бер i санын алучы һәм i белән арттырылган n-ны кайтаручы функцияне кайтаручы функция.

(Бу — белән арттырылган, плюс кына түгел. Аккумулятор тупларга тиеш.)

Common Lisp-та бу түбәндәгечә булыр иде: (defun foo (n) (lambda (i) (incf n i))), ә Perl 5-тә: sub foo { my ($n) = @_; sub {$n += shift} }, монда элементлар Lisp версиясенә караганда күбрәк, чөнки Perl-да параметрларны кулдан чыгарырга туры килә.

Smalltalk-та код Lisp-ка караганда бераз озынрак: foo: n |s| s := n. ^[:i| s := s+i. ], чөнки гомумән лексик үзгәрешлеләр эшләсә дә, сез параметрга кыйммәт бирә алмыйсыз, шуңа күрә сезгә яңа s үзгәрешлесен булдырырга кирәк.

Javascript-та бу мисал тагын да бераз озынрак, чөнки Javascript инструкцияләр һәм аңлатмалар арасындагы аерманы саклый, шуңа күрә кыйммәтләрне кайтару өчен сезгә ачык return инструкцияләре кирәк: function foo(n) { return function (i) { return n += i } } (Гаделлек өчен әйткәндә, Perl да бу аерманы саклый, ләкин return-нарны калдырып китәргә рөхсәт итеп, моны үзенә хас Perl рәвешендә хәл итә.)

Әгәр сез Lisp/Perl/Smalltalk/Javascript кодын Python-га тәрҗемә итәргә тырышсагыз, сез кайбер чикләүләргә очрыйсыз. Python лексик үзгәрешлеләрне тулысынча хупламаганга күрә, сезгә n кыйммәтен саклау өчен мәгълүмат структурасы булдырырга туры килә. Һәм Python-да функция мәгълүмат тибы булса да, аның өчен литерал күренеш юк (тәне бердәнбер аңлатмадан гыйбарәт булмаса), шуңа күрә кайтару өчен исемле функция булдырырга кирәк. Менә нәрсә килеп чыга: def foo(n): s = [n] def bar(i): s[0] += i return s[0] return bar Python кулланучылары ни өчен def foo(n): return lambda i: return n += i яки хәтта def foo(n): lambda i: n += i дип яза алмыйбыз дип тулы хокук белән сорарга мөмкин, һәм минем уйлавымча, кайчан да булса алар шулай эшли алырлар. (Ләкин алар Python-ның калган юлны Lisp-ка әверелеп бетүен көтәргә теләмәсәләр, алар һәрвакытта да бары тик...)

ОО-телләрендә сез ябылуны (closure — тышкы өлкәләрдә билгеләнгән үзгәрешлеләргә мөрәҗәгать итүче функция) бер метод һәм тышкы өлкәдән һәр үзгәрешлене алмаштыру өчен кыры булган классны билгеләп билгеле бер дәрәҗәдә симуляцияли аласыз. Бу программистны лексик яктырту өлкәсен тулысынча хуплаган телдә компилятор башкарачак код анализын эшләргә мәҗбүр итә, һәм бу бердән артык функция бер үк үзгәрешлегә мөрәҗәгать итсә эшләмәячәк, ләкин моның кебек гади очракларда бу җитәрлек.

Python белгечләре бу мәсьәләне Python-да чишүнең иң кулай юлы шушы дип килешәләр кебек: def foo(n): class acc: def __init__(self, s): self.s = s def inc(self, i): self.s += i return self.s return acc(n).inc яки class foo: def __init__(self, n): self.n = n def __call__(self, i): self.n += i return self.n Мин боларны Python тарафдарлары телне дөрес күрсәтмәдем дип әйтмәсен өчен керттем, ләкин икесе дә миңа беренче версиягә караганда катлаулырак тоела. Сез шул ук нәрсәне эшлисез — аккумуляторны тоту өчен аерым урын булдырасыз; бу исемлекнең башы урынына объекттагы бер кыр гына. Һәм бу махсус, сакланган кыр исемнәрен, аеруча __call__ куллану бераз «хак» (җайлашу) кебек тоела.

Perl һәм Python көндәшлегендә Python хакерларының дәгъвасы шул: Python — Perl-га караганда нәфисрәк альтернатива. Әмма бу очрак шуны күрсәтә: көч — иң югары нәфислек ул: Perl программасы гадирәк (элементлары азрак), синтаксисы бераз ямьсезрәк булса да.

Ә башка телләр турында нәрсә әйтеп була? Бу чыгышта телгә алынган башка телләрдә — Fortran, C, C++, Java һәм Visual Basic — бу проблеманы чыннан да хәл итеп буламы-юкмы икәне аңлашылмый. Кен Андерсон Java-да түбәндәге код мөмкин кадәр иң якыны дип әйтә: public interface Inttoint { public int call(int i); } public static Inttoint foo(final int n) { return new Inttoint() { int s = n; public int call(int i) { s = s + i; return s; }}; } Бу спецификациягә туры килми, чөнки ул бары тик бөтен саннар өчен генә эшли. Java хакерлары белән күп тапкырлар хат алышканнан соң, алдагы мисаллар кебек эш итә торган тиешле полиморф версияне язу үтә дә уңайсыз һәм мөмкин булмаган арасында дип әйтер идем. Әгәр кем дә булса берне язарга теләсә, мин аны бик кызыксынып карар идем, ләкин минем шәхси вакытым бетте.

Әлбәттә, сез бу мәсьәләне башка телләрдә хәл итә алмыйсыз дигән сүз туры мәгънәдә дөрес түгел. Бу телләрнең барысы да Тьюринг-эквивалентлы булуы, катгый әйткәндә, сез аларның теләсә кайсында теләсә нинди программа яза аласыз дигәнне аңлата. Алайса сез моны ничек эшләр идегез? Чик очракта — көчсезрәк телдә Lisp интерпретаторын язып.

Бу шаярту кебек яңгырый, ләкин бу зур программалаштыру проектларында төрле дәрәҗәдә шулкадәр еш була ки, бу күренешнең хәтта үз исеме бар — Гринспенның унынчы кагыйдәсе:

Теләсә кайсы җитәрлек дәрәҗәдә катлаулы C яки Fortran программасында Common Lisp-ның яртысының махсус, формальләштерелмәгән, хаталар белән тулы, әкрен тормышка ашырылышы бар.

Әгәр сез катлаулы мәсьәләне чишәргә тырышсагыз, сорау сезнең җитәрлек дәрәҗәдә көчле тел куллануыгызда түгел, ә сезнең (а) көчле тел куллануыгызда, (b) шундый тел өчен факттагы интерпретатор язуыгызда яки (c) үзегез үк кеше-компиляторга әйләнүегездә. Без моның Python мисалында инде башлануын күрәбез, анда без, асылда, компилятор лексик үзгәрешлене гамәлгә ашыру өчен ясаячак кодны симуляциялибез.

Бу гамәл киң таралган гына түгел, ә институциональләштерелгән дә. Мәсәлән, ОО дөньясында сез «паттерннар» турында күп ишетәсез. Бу паттерннар кайвакыт эш өстендәге (c) очрагының, ягъни кеше-компиляторның дәлиле түгелме икән дип уйланам. Программаларымда паттерннар күргәч, мин моны проблема билгесе дип саныйм. Программаның формасы ул чишәргә тиешле мәсьәләне генә чагылдырырга тиеш. Кодтагы теләсә кайсы башка кабатланучанлык — минем өчен, ким дигәндә, мин җитәрлек дәрәҗәдә көчле булмаган абстракцияләр куллануымның билгесе, еш кына мин язарга тиеш булган ниндидер макросның ачылышларын кулдан булдыруымны аңлата.

Искәрмәләр

IBM 704 процессоры якынча суыткыч зурлыгында иде, ләкин күпкә авыррак. Үзәк процессор 3150 фунт тарткан, ә 4K оператив хәтер тагын 4000 фунт тарткан аерым тартмада булган. Иң зур көнкүреш суыткычларының берсе булган Sub-Zero 690-ның авырлыгы 656 фунт тәшкил итә.

Стив Рассел шулай ук 1962 елда беренче (санлы) санак уены Spacewar-ны язган.

Әгәр сез очлы чәчле җитәкчене Lisp-та программа язарга рөхсәт итсен өчен алдарга теләсәгез, сез аңа моны XML дип әйтеп карый аласыз.

Менә аккумулятор генераторы башка Lisp диалектларында: Scheme: (define (foo n) (lambda (i) (set! n (+ n i)) n)) Goo: (df foo (n) (op incf n _))) Arc: (def foo (n) [++ n _]) Эранн Гатның JPL-дагы «индустриянең алдынгы тәҗрибәсе» турындагы моңсу хикәясе мине гадәттә урынсыз кулланыла торган бу гыйбарәгә игътибар итәргә илһамландырды.

Питер Норвиг Design Patterns китабындагы 23 паттернның 16-сы Lisp-та «күренми торган яки гадирәк» булуын ачыклады.

Төрле телләр турындагы сорауларыма җавап биргән һәм/яки моның караламаларын укыган күп кешеләргә, шул исәптән Кен Андерсон, Тревор Блэквелл, Эранн Гат, Дэн Гиффин, Сара Харлин, Джереми Хилтон, Роберт Моррис, Питер Норвиг, Гай Стил һәм Антон ван Стратенга рәхмәт. Алар белдерелгән фикерләр өчен җаваплы түгел.

Бәйләнешле:

Бу чыгышка күп кеше җавап бирде, шуңа күрә алар күтәргән сорауларны карап чыгу өчен мин өстәмә бит ясадым: Re: Revenge of the Nerds.

Бу шулай ук LL1 тарату исемлегендә киң һәм еш кына файдалы фикер алышуга этәргеч бирде. Аеруча Антон ван Стратенның семантик кысу турындагы хатын карагыз.

LL1-дәге хатларның кайберләре мине Succinctness is Power мәкаләсендә тел көче темасына тирәнрәк керергә этәрде.

Аккумулятор генераторы бенчмаркының каноник тормышка ашырылышларының зуррак җыентыгы үзләренең аерым битендә җыелган.

Японча тәрҗемә, Испанча тәрҗемә, Кытайча тәрҗемә