1 Star 0 Fork 0

jacklisp/Learning-SICP

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
lec7b.srt 100.87 KB
一键复制 编辑 原始数据 按行查看 历史
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876
1
00:00:00,010 --> 00:00:01,632
Learning-SICP学习小组
倾情制作
2
00:00:01,630 --> 00:00:04,336
翻译&&时间轴:邓雄飞、张大伟
压制&&特效:邓雄飞(Dysprosium)
校对:邓雄飞(Dysprosium)
3
00:00:04,384 --> 00:00:07,344
特别感谢:裘宗燕教授
4
00:00:07,360 --> 00:00:09,488
计算机程序的构造和解释
5
00:00:09,520 --> 00:00:13,664
元循环求值器 II
Metacircular Evaluator II
6
00:00:17,216 --> 00:00:17,968
教授:目前为止
PROFESSOR: Well, let's see.
7
00:00:19,520 --> 00:00:21,296
我们学的东西都非常有趣
What we did so far was a lot of fun,
8
00:00:21,520 --> 00:00:23,050
但它有什么实际的用途吗?
was it useful for anything?
9
00:00:26,330 --> 00:00:27,968
我想答案是“是的”
I suppose the answer is going to be yes.
10
00:00:29,380 --> 00:00:31,920
这些元循环解释器
If these metacircular interpreters
11
00:00:32,960 --> 00:00:34,608
非常值得琢磨
are a valuable thing to play with.
12
00:00:34,624 --> 00:00:36,176
我花了大概
I spend, say
13
00:00:38,050 --> 00:00:41,856
曾几何时 我花了半年的功夫
there have been times I spend 50% of my time, over a year,
14
00:00:42,864 --> 00:00:45,264
用上节课讲的那种
trying various design alternatives
15
00:00:45,760 --> 00:00:48,192
元循环解释器来试验
by experimenting with them with metacircular interpreters--
16
00:00:49,472 --> 00:00:52,016
各种各样的设计变种
metacircular interpreters like the sort you just saw.
17
00:00:52,570 --> 00:00:54,112
用元循环解释器是因为
Metacircular is because
18
00:00:54,720 --> 00:00:56,944
它们通过自己定义自己
they are defined in terms of themselves in such a way
19
00:00:56,976 --> 00:00:59,712
因此被解释的语言也包含了自己
that the language they interpret contains itself.
20
00:01:01,270 --> 00:01:03,872
这样的解释器是一种的媒介
Such interpreters are a convenient medium
21
00:01:03,888 --> 00:01:05,584
方便我们探索语言问题
for exploring language issues.
22
00:01:06,800 --> 00:01:09,440
如果你想添加一个新的FEATURE
If you want to try adding a new feature,
23
00:01:10,512 --> 00:01:12,384
这就是小菜一碟
it's sort of a snap, it's easy,
24
00:01:12,736 --> 00:01:15,104
你只需要稍作修改 然后观察结果
you just do it and see what happens.
25
00:01:15,490 --> 00:01:17,200
在尝试了一会儿新语言后
You play with that language for a while you say,
26
00:01:17,240 --> 00:01:18,240
你可能觉得它不好
gee, I'm didn't like that,
27
00:01:18,528 --> 00:01:19,470
就把它扔到一边去了
you throw it away.
28
00:01:20,960 --> 00:01:23,552
或者你也想研究
Or you might want to see what
29
00:01:23,648 --> 00:01:27,376
不同绑定策略的差异
the difference is if you'd make a slight difference in the binding strategy,
30
00:01:28,816 --> 00:01:31,904
或者是一些更复杂的东西
or some more complicated things that might occur.
31
00:01:33,720 --> 00:01:35,488
事实上 这些元循环解释器
In fact, these metacircular interpreters
32
00:01:36,170 --> 00:01:37,888
非常适合作为交换媒介
are an excellent medium for people
33
00:01:38,208 --> 00:01:42,560
用于承载人们关于语言设计想法
exchanging ideas about language design,
34
00:01:43,984 --> 00:01:45,744
因为它们易于理解
because they're pretty easy to understand,
35
00:01:46,288 --> 00:01:48,464
它们短小、紧凑而且简洁
and they're short, and compact, and simple.
36
00:01:49,328 --> 00:01:50,800
如果我有一些点子
If I have some idea
37
00:01:51,536 --> 00:01:53,776
想让其它人评论一下
that I want somebody to criticize
38
00:01:54,256 --> 00:01:58,320
比如Indiana大学的Dan Friedman教授
like say, Dan Friedman at Indiana,
39
00:01:59,050 --> 00:02:02,000
我就编写一个小型元循环解释器
I'd write a little metacircular interpreter
40
00:02:02,560 --> 00:02:03,792
然后给他发一封电子邮件
send him some network mail
41
00:02:04,656 --> 00:02:05,450
并附上解释器
with this interpreter in it.
42
00:02:05,450 --> 00:02:07,904
他就可以在计算机上安装并运行
He could whip it up on his machine and play with it
43
00:02:07,920 --> 00:02:09,824
可能他会觉得这个设计并不好
and say, that's no good.
44
00:02:11,940 --> 00:02:13,104
然后他会给我回一封邮件
And then send it back to me and say,
45
00:02:13,136 --> 00:02:14,830
“为什么不试试这个 这个更好一点”
well, why don't you try this one, it's a little better.
46
00:02:16,880 --> 00:02:19,360
所以我将会讲一些这方面的技术
So I want to show you some of that technology.
47
00:02:20,160 --> 00:02:24,208
因为在设计你自己的特定用途语言时
See, because, really, it's the essential, simple technology
48
00:02:24,720 --> 00:02:28,688
这种简单的技术非常重要
for getting started in designing your own languages for particular purposes.
49
00:02:30,790 --> 00:02:32,080
我们试着先在Lisp中
Let's start by adding
50
00:02:32,512 --> 00:02:34,210
添加一个非常简单的FEATURE
a very simple feature to a Lisp.
51
00:02:40,640 --> 00:02:44,370
在这之前 我先来谈谈FEATURE吧
Now, one thing I want to tell you about is features, before I start.
52
00:02:49,560 --> 00:02:52,176
很多语言添加了大量的FEATURE
There are many languages that have made a mess of themselves
53
00:02:53,056 --> 00:02:54,912
把它们本身搞得混乱不堪
by adding huge numbers of features.
54
00:02:56,864 --> 00:02:58,384
计算机科学家有一个笑话
Computer scientists have a joke
55
00:02:59,280 --> 00:03:02,520
“这不是BUG 这是FEATURE”
about bugs that transform it to features all the time.
56
00:03:05,030 --> 00:03:06,464
而我宁愿认为
But I like to think of it is that
57
00:03:08,912 --> 00:03:11,440
很多系统都在遭受着“功能蔓延”的影响
many systems suffer from what's called creeping featurism.
58
00:03:12,820 --> 00:03:13,440
比方说
Which is that
59
00:03:14,944 --> 00:03:18,160
George希望系统中有某个FEATURE
George has a pet feature he'd like in the system,
60
00:03:18,720 --> 00:03:19,360
他就加了进来
so he adds it.
61
00:03:20,170 --> 00:03:22,144
Harry也想着
And then Harry says, go says
62
00:03:22,176 --> 00:03:24,208
这个系统现在也不是我喜欢的那个了
gee, this system is no longer what exactly I like,
63
00:03:24,240 --> 00:03:25,920
然后加入了自己最喜欢的FEATURE
so I'm going to add my favorite feature.
64
00:03:26,640 --> 00:03:30,240
Jim也这样做
And then Jim adds his favorite feature.
65
00:03:30,832 --> 00:03:31,792
一段时间过后
And, after a while,
66
00:03:31,808 --> 00:03:34,816
操作手册就多达500页
the thing has a manual 500 pages long
67
00:03:35,152 --> 00:03:36,512
以至于没人能看得懂
that no one can understand.
68
00:03:37,790 --> 00:03:39,328
有时候也可能只是
And sometimes it's the same person
69
00:03:39,904 --> 00:03:41,376
同一个人在添加FEATURE
who writes all of these features
70
00:03:41,392 --> 00:03:43,232
也会导致同样糟糕的结果
and produces this terribly complicated thing.
71
00:03:44,140 --> 00:03:46,096
很多情况下 比如编辑器
In some cases, like editors,
72
00:03:47,376 --> 00:03:49,120
具有很多FEATURE就很合理
it's sort of reasonable to have lots of features,
73
00:03:50,920 --> 00:03:52,656
因为你想要能够完成
because there are a lot of things you want to be able to do
74
00:03:52,688 --> 00:03:53,760
各种不同的事情
and many of them arbitrary.
75
00:03:56,112 --> 00:03:57,296
但对计算机语言来说
But in computer languages,
76
00:03:57,850 --> 00:03:58,912
我认为太多的FEATURE
I think it's a disaster
77
00:04:00,016 --> 00:04:01,290
是一个灾难
to have too much stuff in them.
78
00:04:04,032 --> 00:04:08,000
另外 系统也可能变成某种“尖叫的怪物”
The other alternative you get into is something called feeping creaturism,
79
00:04:09,520 --> 00:04:11,392
假设你有一个盒子
which is where you have a box
80
00:04:11,808 --> 00:04:15,290
它有一个鼠标和花哨的显示器
which has a display, a fancy display, and a mouse,
81
00:04:15,952 --> 00:04:20,048
这些花哨的IO带来了各种各样的复杂性
and there is all sorts of complexity associated with all this fancy IO.
82
00:04:21,010 --> 00:04:22,800
你的程序语言就变成了
And your computer language becomes
83
00:04:23,344 --> 00:04:25,376
阴暗无用的小玩意儿
a dismal, little, tiny thing that barely works
84
00:04:25,408 --> 00:04:27,904
这是由计算机上的视窗系统进行的
because of all the swapping, and disk twitching, and so on,
85
00:04:28,096 --> 00:04:29,360
内存换页和磁盘抖动所导致的
caused by your Window system.
86
00:04:30,080 --> 00:04:31,824
每当你使用计算机的时候
And every time you go near the computer,
87
00:04:31,936 --> 00:04:33,456
鼠标处理进程就会唤醒
the mouse process wakes up and says,
88
00:04:33,850 --> 00:04:35,950
你有什么事情要我做的吗?
gee do you have something for me to do,
89
00:04:36,144 --> 00:04:37,232
然后又回去休眠
and then it goes back to sleep.
90
00:04:37,440 --> 00:04:39,440
如果你的胳膊肘不小心碰到了鼠标
And if you accidentally push mouse with you elbow,
91
00:04:39,616 --> 00:04:42,320
一大堆烟雾就会从你的电脑出来 类似于这样
a big puff of smoke comes out of your computer and things like that.
92
00:04:42,940 --> 00:04:45,296
这就是由于添加FEATURE
So two ways to disastrously
93
00:04:45,552 --> 00:04:47,216
导致系统不能用的两种典型情况
destroy a system by adding features.
94
00:04:47,500 --> 00:04:49,730
现在我们要添加的是 一个非常简单的FEATURE
But try right now to add a little, simple feature.
95
00:04:52,608 --> 00:04:53,776
这个FEATURE非常好
This actually is a good one,
96
00:04:53,856 --> 00:04:56,176
事实上 Lisp中就有这个FEATURE
and in fact, real Lisps have it.
97
00:04:57,250 --> 00:04:58,176
我们都知道
As you've seen,
98
00:04:59,296 --> 00:05:03,136
像+、*这样的过程
there are procedures like plus and times
99
00:05:03,376 --> 00:05:04,896
可以接受不定数目的参数
that take any number of arguments.
100
00:05:05,430 --> 00:05:06,448
因此我们就可以写
So we can write things
101
00:05:06,576 --> 00:05:10,944
(+ (* A X X)
like the sum of the product of a and x and x,
102
00:05:12,096 --> 00:05:16,992
(* B X) C)
and the product of b and x and c.
103
00:05:17,540 --> 00:05:18,688
这里可以看到
As you can see here,
104
00:05:18,928 --> 00:05:21,760
+有两到三个参数
addition takes three arguments or two arguments,
105
00:05:22,304 --> 00:05:24,816
*也有两到三个参数
multiplication takes two arguments or three arguments,
106
00:05:25,080 --> 00:05:26,768
不管多少个参数
taking numbers of arguments
107
00:05:26,784 --> 00:05:28,490
都应该用同样的方式对待
all of which are to be treated in the same way.
108
00:05:30,000 --> 00:05:32,176
支持不定数目的参数
This is a valuable thing,
109
00:05:32,288 --> 00:05:34,010
这一点非常有用
indefinite numbers of arguments.
110
00:05:34,960 --> 00:05:38,416
而我上节课所讲的Lisp求值器
Yet the particular Lisp system that I show you
111
00:05:39,232 --> 00:05:41,856
只能处理固定数目的参数
is one where the numbers of arguments is fixed,
112
00:05:42,620 --> 00:05:45,280
因为我要用BIND过程中的PAIR-UP过程
because I had to match the arguments against the formal parameters
113
00:05:45,632 --> 00:05:47,920
让形式参数与实际参数一一对应
in the binder, where there's a pairup.
114
00:05:50,810 --> 00:05:53,808
假如我想能够定义像这样的过程
Well, I'd like to be able to define new procedures like this
115
00:05:54,896 --> 00:05:57,328
它们可以接收任意个数的参数
that can have any number of arguments.
116
00:05:58,752 --> 00:06:00,400
这个问题有好几部分
Well there's several parts to this problem.
117
00:06:01,344 --> 00:06:04,816
首先是挑选合适的语法描述
The first part is coming up with the syntactic specification,
118
00:06:05,720 --> 00:06:11,216
我们需要能够标注额外的参数
some way of notating the additional arguments,
119
00:06:12,176 --> 00:06:13,632
标注那些不知道个数的参数
of which you don't know how many there are.
120
00:06:15,480 --> 00:06:16,624
另外就是
And then there's the other thing,
121
00:06:17,104 --> 00:06:18,704
一旦我们标注出来后
which is once we've notated it,
122
00:06:19,072 --> 00:06:20,784
我们怎样解释这些个记号
how are we going to interpret that notation
123
00:06:21,740 --> 00:06:23,100
才能得到
so as to do the right thing,
124
00:06:23,856 --> 00:06:25,376
正确的结果呢?
whatever the right thing is?
125
00:06:26,980 --> 00:06:28,800
让我们来考虑一种
So let's consider an example of a sort of thing
126
00:06:28,848 --> 00:06:30,272
我们可能会遇到的情况
we might want to be able to do.
127
00:06:33,070 --> 00:06:34,512
比如说
So an example might be,
128
00:06:35,424 --> 00:06:37,344
我想要定义这样的一个过程
that I might want to be able to define a procedure
129
00:06:37,952 --> 00:06:41,360
它有一个必选参数X
which is a procedure of one required argument x
130
00:06:42,200 --> 00:06:45,264
还有个可选参数 -- 或者说一堆参数
and a non-required -- bunch of arguments,
131
00:06:45,280 --> 00:06:47,230
我不知道它们的数目 就记作Y吧
I don't know how many there are, called y.
132
00:06:49,090 --> 00:06:50,368
X是必选的
So x is required,
133
00:06:55,888 --> 00:06:57,440
然而有很多参数Y
and there are many y's,
134
00:06:59,536 --> 00:07:05,990
这些参数形成的表 -- 我就记作Y
many arguments-- y will be the list of them.
135
00:07:14,480 --> 00:07:16,064
写好了参数表
Now, with such a thing,
136
00:07:16,096 --> 00:07:17,680
我现在要这样定义过程体
we might be able to say something like,
137
00:07:19,024 --> 00:07:21,984
我要对每一个元素都做同样的处理
map-- I'm going to do something to every one--
138
00:07:22,520 --> 00:07:25,760
(MAP (LAMBDA (U)
of that procedure of one argument u,
139
00:07:27,000 --> 00:07:34,544
(* X U)) Y)
which multiplies x by u, and we'll apply that to y.
140
00:07:36,890 --> 00:07:38,048
这里 我用了一个“点号”
I've used a dot here
141
00:07:38,592 --> 00:07:41,312
来表明点号后面的东西
to indicate that the thing after this
142
00:07:42,192 --> 00:07:44,304
是剩下的所有参数构成的表
is a list of all the rest of the arguments.
143
00:07:46,300 --> 00:07:48,128
这就是一个语法规范
I'm making a syntactic specification.
144
00:07:53,320 --> 00:07:54,640
为什么这样来写呢?
Now, what this depends upon,
145
00:07:55,712 --> 00:07:58,064
这种语法规范之所以合理
the reason why this is sort of a reasonable thing to do,
146
00:07:59,776 --> 00:08:01,968
是因为Lisp的源码读取器
is because this happens to be a syntax
147
00:08:02,000 --> 00:08:03,600
刚好使用这种语法
that's used in the Lisp reader
148
00:08:04,416 --> 00:08:07,152
来表示序对
for representing conses.
149
00:08:08,944 --> 00:08:11,080
我们之前没有介绍过
We've never introduced that before.You never see.
150
00:08:11,080 --> 00:08:12,784
你在自己尝试的时候可能遇到过
You may have seen when playing with the system
151
00:08:13,040 --> 00:08:14,624
当你调用(CONS X Y)时
if you cons two things together, you get the
152
00:08:14,896 --> 00:08:18,128
你会得到 X . Y
first, space, dot, the second, space--
153
00:08:19,790 --> 00:08:22,832
准确来说是(X . Y)
the first, space, dot, space, the second
154
00:08:23,088 --> 00:08:24,640
两边还有括号
with parentheses around the whole thing.
155
00:08:26,980 --> 00:08:28,160
举例来说吧
So that, for example,
156
00:08:28,970 --> 00:08:35,040
这里的(X . Y)对应着一个序对
this x dot y corresponds to a pair,
157
00:08:36,336 --> 00:08:39,296
X是CAR部分 Y是CDR部分
which has got an x in it and a y in it.
158
00:08:41,488 --> 00:08:43,984
你们目前为止见过的其它记号
The other notations that you've seen so far
159
00:08:44,944 --> 00:08:46,672
是像
are things like, like
160
00:08:46,920 --> 00:08:55,248
(LAMBDA (X Y Z) ...)这样的
a procedure of arguments x and y and z which do things
161
00:08:55,710 --> 00:08:57,630
它们则是像这样的
and that looks like--
162
00:09:02,000 --> 00:09:03,616
就拿形式参数表来说
Just looking at the bound variable list,
163
00:09:04,224 --> 00:09:05,296
它实际上是这样
it looks like this,
164
00:09:09,936 --> 00:09:17,328
这里分别是 X、Y、Z和空表
x, y, z, and the empty thing.
165
00:09:18,280 --> 00:09:21,088
如果我有一个想要与之匹配的参数表的话
If I have a list of arguments I wish to match this against,
166
00:09:22,608 --> 00:09:25,600
假设实际参数表是'(1 2 3)
I have a list of arguments one, two, three,
167
00:09:25,872 --> 00:09:27,264
我想把它们和形参相匹配
I want to match these against.
168
00:09:28,384 --> 00:09:37,104
所以这里 可能有个三个元素的表
OK? So I might have here a list of three things,
169
00:09:42,448 --> 00:09:46,944
分别是1、2、3
one, two, three.
170
00:09:48,990 --> 00:09:53,168
用'(1 2 3)来匹配'(X Y Z)
And I want to match x, y, z against one, two, three.
171
00:09:54,220 --> 00:09:56,288
很显然1和X相匹配
Well, it's clear that the one matches the x,
172
00:09:56,320 --> 00:09:58,016
因为我可以顺着这个结构来
because I can just sort of follow the structure,
173
00:09:58,864 --> 00:10:01,568
2和Y相匹配
and the two matches the y,
174
00:10:02,464 --> 00:10:04,048
3和Z相匹配
and the three matches the z.
175
00:10:05,480 --> 00:10:09,536
假设我现在要把这个(X . Y)
But now, supposing I were to compare this x dot y.
176
00:10:09,552 --> 00:10:11,840
这个是(X . Y)
this is x dot y--
177
00:10:12,512 --> 00:10:16,912
如果我想把它跟'(1 2 3)相匹配的话
supposing I compare that with a list of three arguments, one, two, three.
178
00:10:19,088 --> 00:10:20,000
我们再来看
Let's look at that again.
179
00:10:28,000 --> 00:10:30,320
这里是1、2、3
One, two, three--
180
00:10:30,864 --> 00:10:32,880
我可以沿着这里遍历
Well, I can walk along here
181
00:10:32,992 --> 00:10:35,504
会发现 1和X相匹配
and say, oh yes, x matches the one,
182
00:10:37,568 --> 00:10:41,840
而Y和表'(2 3)相匹配
Ah, the y matches the list, which is two and three.
183
00:10:43,740 --> 00:10:46,224
所以这里选用的表示法
So the notation I'm choosing here
184
00:10:46,416 --> 00:10:50,160
对于Lisp来说是非常自然的
is one that's very natural for Lisp system.
185
00:10:52,660 --> 00:10:54,144
所以我就选择用这个记号
But I'm going to choose this as a notation
186
00:10:54,176 --> 00:10:55,808
来表示数目不定的参数
for representing a bunch of arguments.
187
00:10:58,290 --> 00:11:00,096
还有一种可能性
Now, there's an alternative possibility.
188
00:11:00,592 --> 00:11:02,784
如果我不是特别想命名某个参数
If I don't want to take one special out,
189
00:11:03,008 --> 00:11:05,008
或者是命名某两个参数之类的
or two special ones out or something like that,
190
00:11:06,544 --> 00:11:07,568
如果我不想那样的话
if I don't want to do that,
191
00:11:08,780 --> 00:11:10,448
如果我想像+那样
if I want to talk about
192
00:11:10,528 --> 00:11:12,520
一下子引用所有的参数
just the list of all the arguments like in addition,
193
00:11:13,880 --> 00:11:17,960
那么我就应该把参数表写成
well then the argument list I'm going to choose to be
194
00:11:18,200 --> 00:11:23,456
(LAMBDA X ...)
that procedure of all the arguments x, which does something with x
195
00:11:25,140 --> 00:11:26,304
举例来说
And which, for example,
196
00:11:26,816 --> 00:11:27,968
如果我定义一个过程
if I take the procedure,
197
00:11:28,064 --> 00:11:30,448
它把接收所有的参数
which takes all the arguments x
198
00:11:31,120 --> 00:11:32,704
然后返回一个由它们组成的表X
and returned the list of them,
199
00:11:34,810 --> 00:11:38,672
返回的结果就是过程的参数表 明白吗?
OK? That's list. That's the procedure list.
200
00:11:45,850 --> 00:11:46,672
这又是怎么回事呢?
How does this work?
201
00:11:46,840 --> 00:11:50,064
实际上 无论我们的参数表是何种形式
Well, indeed what I had as the bound variable list in this case,
202
00:11:50,600 --> 00:11:51,456
无论是何种形式
whatever it is,
203
00:11:51,616 --> 00:11:53,680
都要与实际参数表相匹配
is being matched against a list of arguments.
204
00:11:55,140 --> 00:11:57,145
现在 这个符号就是所有的实际参数了
This symbol now is all of the arguments.
205
00:12:01,490 --> 00:12:05,136
所以 我选择使用这个特定的语法规范
And so this is the choice I'm making for a particular syntactic specification,
206
00:12:05,648 --> 00:12:07,632
来描述那些
for the description of procedures
207
00:12:08,048 --> 00:12:10,560
接收不定数目参数的过程
which take indefinite numbers of arguments.
208
00:12:13,456 --> 00:12:14,608
一共有两种情况
There are two cases of it,
209
00:12:15,400 --> 00:12:16,350
上面这种和下面这种
this one and this one.
210
00:12:17,440 --> 00:12:18,368
这两种都 --
And none of this.
211
00:12:18,420 --> 00:12:20,112
当你们在制定语法规范时
When you make syntactic specifications,
212
00:12:20,448 --> 00:12:22,544
千万注意不要有歧义
it's important that it's unambiguous,
213
00:12:23,568 --> 00:12:27,360
就比如说这里的两种情况
that neither of these can be confused with
214
00:12:27,664 --> 00:12:31,200
就不要与这里我们已有的这种混淆了
a representation we already have, this one.
215
00:12:33,610 --> 00:12:35,824
我总是可以区分出
I can always tell whether I have
216
00:12:36,544 --> 00:12:39,808
过程的形式参数
a fixed number of explicitly named arguments
217
00:12:40,288 --> 00:12:41,760
是数目固定的具名参数
made by these formal parameters,
218
00:12:42,640 --> 00:12:43,130
还是
or
219
00:12:43,280 --> 00:12:45,360
既有数目固定的具名参数
a fixed number of named formal parameters
220
00:12:45,440 --> 00:12:48,016
又跟着数目可变的参数
followed by a thing which picks up all the rest of them,
221
00:12:49,424 --> 00:12:53,520
又或者是所有参数组成的表
or a list of all the arguments
222
00:12:53,680 --> 00:12:56,528
这个表会和这里的形式参数X相匹配
which will be matched against this particular formal parameter called x,
223
00:12:56,992 --> 00:12:58,848
我都是可以从语法上区分它们
because these are syntactically distinguishable.
224
00:13:02,250 --> 00:13:04,624
由于语言中存在语法歧义
Many languages make terrible errors in that form
225
00:13:05,040 --> 00:13:08,032
整个待解释的程序被错误地分段
where whole segments of interpretation are cut off,
226
00:13:08,640 --> 00:13:13,920
从而导致了可怕的错误
because there are syntactic ambiguities in the language.
227
00:13:14,560 --> 00:13:16,672
类Algol语言中就有些传统问题
They are the traditional problems with ALGOL like languages
228
00:13:16,672 --> 00:13:23,472
就跟谓词部分的嵌套IF语句有关
having to do with the nesting of ifs in the predicate part.
229
00:13:25,060 --> 00:13:25,936
总之
In any case,
230
00:13:27,520 --> 00:13:29,440
我现在已经把语法告诉你们了
now, so I've told you about the syntax,
231
00:13:30,272 --> 00:13:34,832
我们要怎么来处理它的语义呢?
now, what are we going to do about the semantics of this?
232
00:13:35,250 --> 00:13:36,112
我们如何来解释它?
How do we interpret it?
233
00:13:36,590 --> 00:13:37,968
其实很简单
Well this is just super easy.
234
00:13:38,440 --> 00:13:42,576
我修改一下元循环解释器就行
I'm going to modify the metacircular interpreter to do it.
235
00:13:43,712 --> 00:13:44,768
只需修改一行
And that's a one liner.
236
00:13:45,984 --> 00:13:46,576
在这里
There it is.
237
00:13:47,536 --> 00:13:49,560
我修改一下PAIR-UP过程
I'm changing the way you pair things up.
238
00:13:50,816 --> 00:13:54,192
这里的PAIR-UP过程把
OK? Here we have procedure that pairs --
239
00:13:56,760 --> 00:14:02,032
这是从上节课的元循环求值器中
Here's the procedure that pairs the
240
00:14:04,810 --> 00:14:09,568
摘录过来的PAIR-UP过程
the variables, the formal parameters, with the arguments that were passed
241
00:14:12,160 --> 00:14:16,688
它把形式参数与传递过来的实际参数匹配起来
from the last description of the metacircular interpreter.
242
00:14:18,960 --> 00:14:21,936
大部分地方都和以前一样
And here's some things that are the same as they were before.
243
00:14:22,670 --> 00:14:23,232
也就是说
In other words,
244
00:14:23,312 --> 00:14:25,072
如果变量表为空
if the list of variables is empty,
245
00:14:25,520 --> 00:14:27,312
并且值表也为空
then if the list of values is empty,
246
00:14:27,456 --> 00:14:29,616
就返回空表
then I have an empty list.
247
00:14:31,050 --> 00:14:33,008
否则就是参数过多
Otherwise, I have too many arguments,
248
00:14:33,980 --> 00:14:40,192
如果变量表为空 但值表非空
If I have, that is if I have empty variables but not empty values.
249
00:14:41,580 --> 00:14:44,000
如果值表为空
If I have empty values,
250
00:14:44,960 --> 00:14:47,472
但是变量表又非空
OK? But the variables are not empty,
251
00:14:47,488 --> 00:14:48,560
那就是实际参数少了
that I have too few arguments.
252
00:14:48,944 --> 00:14:51,312
然而如果我有一个变量是符号的话
However if I have a variable -- the variables are a symbol--
253
00:14:55,536 --> 00:14:56,496
这就有意思了
interesting case--
254
00:14:58,300 --> 00:15:04,400
那么 我就认为遇到了特殊情况
then, what I should do is say, oh yes, this is the special case
255
00:15:04,592 --> 00:15:06,510
也就是尾部分为符号的情况
that I have a symbolic tail.
256
00:15:08,350 --> 00:15:14,112
情况就像这里的一样
OK. I have here a thing just like we looked over here.
257
00:15:14,900 --> 00:15:17,872
这个尾部分就是一个符号Y
This is a tail which is a symbol, y.
258
00:15:18,630 --> 00:15:19,392
它不是NIL
It's not a nil.
259
00:15:20,730 --> 00:15:21,728
不是个空表
It's not the empty list.
260
00:15:23,264 --> 00:15:25,600
而这个一开始就是个符号
Here's a symbolic tail that is just the very beginning of the tail.
261
00:15:25,984 --> 00:15:26,816
就没有别的东西了
There is nothing else.
262
00:15:27,790 --> 00:15:28,720
这种情况下
In that case,
263
00:15:29,960 --> 00:15:37,200
我就用这个符号去匹配所有的值
I wish to match that variable with all the values
264
00:15:38,032 --> 00:15:42,520
并把它们添加到要返回的结果中
and add that to the pairing that I'm making.
265
00:15:44,500 --> 00:15:46,912
否则的话 我就像正常情况那样
Otherwise, I go through the normal arrangement
266
00:15:47,152 --> 00:15:48,528
来创建所有的配对
of making up the whole pairing.
267
00:15:52,020 --> 00:15:53,824
我认为这很容易理解
I suppose that's very simple.
268
00:15:54,510 --> 00:15:55,840
就是这些
And that's all there is to it.
269
00:15:57,080 --> 00:15:58,330
现在 答疑时间
And now I'll answer some questions.
270
00:16:02,620 --> 00:16:05,056
有什么问题吗?
The first one-- Are there any questions?
271
00:16:06,600 --> 00:16:06,944
你说
Yes?
272
00:16:07,376 --> 00:16:09,920
学生:你能再解释一下第三种形式吗?
AUDIENCE: Could you explain that third form?
273
00:16:09,980 --> 00:16:12,128
教授:第三种?这个?
PROFESSOR: Third form. This one? OK.
274
00:16:12,590 --> 00:16:14,272
或许你用表结构来思考
Well, maybe we should look at the thing
275
00:16:14,300 --> 00:16:16,240
会更容易理解一些
as a piece of list structure.
276
00:16:18,570 --> 00:16:22,736
这是一个过程 包含一个LAMBDA
This is a procedure which contains a lambda.
277
00:16:25,856 --> 00:16:29,616
我画出来的这个表结构就代表上面的这个
I'm just looking at the list structure which represents this.
278
00:16:31,264 --> 00:16:32,448
这里是X
Here's x.
279
00:16:32,730 --> 00:16:33,980
这些是我们的符号
These are our symbols.
280
00:16:37,410 --> 00:16:39,580
过程体就是X而已
And then the body is nothing but x.
281
00:16:44,840 --> 00:16:48,752
如果我需要这个过程的形式参数表
If I were looking for the bound variable list part of this procedure,
282
00:16:50,096 --> 00:16:51,584
我就取它的CADR部分
I would go looking at the CADR,
283
00:16:52,144 --> 00:16:53,168
我会得到一个符号
and I'd find a symbol.
284
00:16:54,010 --> 00:16:57,168
所以我们的匹配器 -- 也就是我给你们展示的PAIR-UP过程
So the, matcher, which is this pairup thing I just showed you,
285
00:16:58,240 --> 00:17:00,448
就会把这个符号对象
is going to be matching a symbolic object
286
00:17:01,568 --> 00:17:04,400
跟我们传递的实际参数表相匹配了
against a list of arguments that were passed.
287
00:17:05,760 --> 00:17:09,559
这个符号与实际参数表相绑定
And it will bind that symbol to the list of arguments.
288
00:17:11,376 --> 00:17:16,480
而在这个例子中 如果我去取它的话
The -- In this case, if I'm looking for it,
289
00:17:16,928 --> 00:17:20,976
匹配器就会把它与变量表的这个部分相匹配
the match will be against this in the bound variable list position.
290
00:17:24,140 --> 00:17:26,144
如果一个过程只是
Now, if what this does is
291
00:17:26,170 --> 00:17:29,130
直接返回得到的参数表的话 返回的就是一个表
it gets a list of arguments and returns it, that's list
292
00:17:30,400 --> 00:17:31,392
这个过程就是这样的
That's the procedure is.
293
00:17:34,510 --> 00:17:35,488
好吧 谢谢大家
Oh well, thank you.
294
00:17:36,140 --> 00:17:37,280
大家休息一下吧
Let's take a break.
295
00:17:37,830 --> 00:17:55,360
[音乐]
[JESU, JOY OF MAN'S DESIRING]
296
00:17:55,360 --> 00:17:59,024
《计算机程序的构造和解释》
297
00:18:03,530 --> 00:18:07,568
讲师:哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授
298
00:18:07,560 --> 00:18:11,696
《计算机程序的构造和解释》
299
00:18:12,256 --> 00:18:16,110
元循环求值器 II
300
00:18:20,864 --> 00:18:21,616
教授:我们接着来看
PROFESSOR: Well let's see.
301
00:18:23,260 --> 00:18:26,320
现在 我将介绍一种相当重要的变种
Now, I'm going to tell you about a rather more substantial variation
302
00:18:27,456 --> 00:18:31,040
这种变体非常有名
one that's a famous variation
303
00:18:31,600 --> 00:18:36,800
早期的很多Lisp都支持它
hat many early Lisps had.
304
00:18:38,256 --> 00:18:40,064
它被称为变量的动态绑定
It's called dynamic binding of variables.
305
00:18:41,770 --> 00:18:44,680
我们现在来研究一下它
And we'll investigate a little bit about that right now.
306
00:18:47,620 --> 00:18:50,160
我先来介绍一下是什么导致
I'm going to first introduce this by showing you the sort of thing
307
00:18:50,352 --> 00:18:52,368
人们产生这样的想法
that would make someone want this idea.
308
00:18:53,740 --> 00:18:55,232
然而我并不会直接点明原因
I'm not going to tell what it is yet,
309
00:18:55,408 --> 00:18:57,600
我来举一个例子 你们来感受一下
I'm going to show you why you might want it.
310
00:18:58,640 --> 00:18:59,936
假设
Suppose, for example,
311
00:19:00,750 --> 00:19:02,592
我们再来考察一下
we looked at the sum procedure again
312
00:19:05,024 --> 00:19:06,430
计算一系列数之和的SUM过程
for summing up a bunch of things.
313
00:19:08,140 --> 00:19:09,472
它的参数为
To be that procedure,
314
00:19:09,600 --> 00:19:10,784
计算当前项的TERM
of a term,
315
00:19:13,040 --> 00:19:14,416
下界A
lower bound,
316
00:19:15,240 --> 00:19:17,040
计算下一项索引的NEXT
method of computing the next index,
317
00:19:17,248 --> 00:19:18,560
上界B
and upper bound,
318
00:19:19,360 --> 00:19:20,160
过程体是
such that,
319
00:19:23,160 --> 00:19:26,940
如果A>B
if a is greater than b
320
00:19:27,150 --> 00:19:28,640
那么结果就是0
then the result is 0,
321
00:19:30,240 --> 00:19:31,088
否则就是
otherwise,
322
00:19:33,680 --> 00:19:39,824
(+ (TERM A)
it's the sum, of the term, procedure, applied to a
323
00:19:40,608 --> 00:19:44,240
(SUM TERM
and the result of adding up, terms,
324
00:19:47,680 --> 00:19:52,640
(NEXT A)
with the next a being the a,
325
00:20:00,300 --> 00:20:03,560
这个NEXT过程直接传递过去
the next procedure passed along,
326
00:20:06,400 --> 00:20:08,256
上界B也直接传递过去
and the upper bound being passed along.
327
00:20:14,510 --> 00:20:15,760
(闭合括号中)
Blink, blink, blink--
328
00:20:17,824 --> 00:20:21,450
当我使用SUM过程的时候
OK? Now, when I use this sum procedure,
329
00:20:21,968 --> 00:20:24,352
我可以像这样来用
I can use it, for example, like this.
330
00:20:25,450 --> 00:20:38,048
我们可以把SUM-POWERS过程定义为
We can define the sum of the powers to be,
331
00:20:38,080 --> 00:20:40,330
这个函数是用来计算Σ(X^N)的
for example, sum of a bunch of powers x to the n,
332
00:20:41,104 --> 00:20:45,936
它的参数有A、B以及N
to be that procedure of a, b, and n--
333
00:20:45,952 --> 00:20:47,696
分别指下界、上界以及指数
lower bound, the upper bound, and n--
334
00:20:48,060 --> 00:20:53,344
它的定义是(SUM (LAMBDA (X)
which is sum, of lambda of x,
335
00:20:53,600 --> 00:20:59,310
这个参数为X的过程计算(EXPT X N)
the procedure of one argument x, which exponentiates x to the n,
336
00:21:02,190 --> 00:21:09,296
我们还要传递A、1+还有B
with the a, the incrementer, and b, being passed along.
337
00:21:11,824 --> 00:21:15,760
因此 给定一系列X 我们计算Σ(X^N)的值
So we're adding up x to n, given an x.
338
00:21:16,144 --> 00:21:19,740
X从A到B取值 步长为1
x takes on values from a to b, incrementing by one.
339
00:21:22,940 --> 00:21:24,384
我也可以定义--
I can also write the--
340
00:21:27,680 --> 00:21:28,200
好像这里有点问题
That's right.
341
00:21:29,780 --> 00:21:31,024
不好意思
Product, excuse me.
342
00:21:31,910 --> 00:21:33,360
这里应该是PRODUCT-POWERS
The product of a bunch of powers.
343
00:21:38,080 --> 00:21:39,120
名字有点奇怪
It's a strange name.
344
00:21:40,020 --> 00:21:40,800
还是不改了
I'm going to leave it there.
345
00:21:41,960 --> 00:21:46,320
有点怪 就按原来的吧
Weird-- OK? I write up what I have.
346
00:21:49,344 --> 00:21:50,192
这回应该对了
I'm sure that's right.
347
00:21:51,376 --> 00:21:53,824
而PRODUCT-POWERS的定义则是
And if I want the product of a bunch of powers--
348
00:21:58,416 --> 00:22:02,368
(意义不明)
That was 12 brain cells, that double-take.
349
00:22:03,000 --> 00:22:06,816
我可以用像SUM一样的过程
I can for example use the procedure which is like sum,
350
00:22:06,816 --> 00:22:08,220
只不过是用来计算乘积的
which is for making products,
351
00:22:08,560 --> 00:22:11,056
但是很类似 就跟你们在那里见到的一样
but it's similar to that, that you've seen before.
352
00:22:11,450 --> 00:22:16,384
它也是一个三参数的过程
There's a procedure of three arguments again.
353
00:22:17,000 --> 00:22:25,424
求积的因数是通过构造而来
Which is the product of terms that are constructed, or factors in this case,
354
00:22:25,664 --> 00:22:31,600
也就是(PRODUCT (LAMBDA (X) (EXPT X N))
constructed from exponentiating x to the n,
355
00:22:34,432 --> 00:22:37,856
下界是A 步长为1 上界为B
where I start with a, I increment, and I go to b.
356
00:22:41,530 --> 00:22:41,888
现在
Now,
357
00:22:46,832 --> 00:22:49,504
你可能马上就意识到一些问题
there's some sort of thing here that should disturb you immediately.
358
00:22:50,750 --> 00:22:52,016
它们看起来几乎一样
These look the same.
359
00:22:53,180 --> 00:22:55,200
为什么要重复写代码呢?
Why am I writing this code so many times?
360
00:22:56,590 --> 00:22:59,728
现在就很像我们之前遇到的情况了
Here I am, in the same boat I've been in before.
361
00:23:01,008 --> 00:23:03,152
构建一个抽象不是更好吗?
Right? Wouldn't it be nice to make an abstraction here?
362
00:23:03,810 --> 00:23:05,760
如何构建良好的抽象呢?
What's an example of a good abstraction to make?
363
00:23:05,856 --> 00:23:07,552
我看到有一些完全相同的代码
Well, I see some codes that's identical.
364
00:23:08,470 --> 00:23:09,328
这有一段
Here's one,
365
00:23:09,984 --> 00:23:11,080
这是另一段
and here's another.
366
00:23:14,450 --> 00:23:16,224
所以我应该把它们提取出来
And so maybe I should be able to pull that out.
367
00:23:17,090 --> 00:23:19,232
我就会想
I should be able to say, oh yes,
368
00:23:20,512 --> 00:23:22,672
SUM-POWERS可以用
the sum of the powers could be written in terms of
369
00:23:22,880 --> 00:23:24,528
NTH-POWERS的过程来编写
something called the nth power procedure.
370
00:23:25,710 --> 00:23:27,408
假如有人想写一个
Imagine somebody wanted to write
371
00:23:27,744 --> 00:23:30,030
稍微不同的过程 就像这个一样
a slightly different procedure that looks like this.
372
00:23:37,630 --> 00:23:45,184
(DEFINE SUM-POWERS
The sum powers to be a procedure
373
00:23:46,448 --> 00:23:48,460
(LAMBDA (A B N)
of a, b, and n,
374
00:23:48,752 --> 00:23:52,272
(SUM (NTH-POWER
which the result of summing up the nth power.
375
00:23:53,888 --> 00:23:55,424
我们调用过程NTH-POWER
We're going to give a name to that idea,
376
00:23:58,352 --> 00:24:02,272
下界为A 步长为1 上界为B
for starting at a, going by one, and ending at b.
377
00:24:05,744 --> 00:24:06,912
类似地
And similarly,
378
00:24:10,656 --> 00:24:12,768
我想用这种方式来重写PRODUCT-POWERS
I might want to write the product powers this way,
379
00:24:12,896 --> 00:24:15,248
把求幂指数从这里抽象出来
abstracting out this idea.
380
00:24:16,270 --> 00:24:17,376
可以这样写
I might want this.
381
00:24:22,100 --> 00:24:23,024
(DEFINE PRODUCT-POWERS
Product powers,
382
00:24:29,488 --> 00:24:34,944
(LAMBDA (A B N)
to be a procedure of a, b, and n,
383
00:24:35,312 --> 00:24:42,336
(PRODUCT NTH-POWERS
which is the product of the nth power operation
384
00:24:46,448 --> 00:24:50,304
A 1+ B)))
on a with the incrementation and b being
385
00:24:53,504 --> 00:24:57,568
把NTH-POWER的结果作为PRODUCT的参数
being my arguments for the analogous-thing product.
386
00:24:58,380 --> 00:25:00,240
我们还需要定义
And I'd like to be able to define,
387
00:25:02,048 --> 00:25:03,888
还需要定义过程NTH-POWERS
I'd like to be able to define nth power--
388
00:25:04,896 --> 00:25:05,930
我把它写在这边
I'll put it over here.
389
00:25:12,224 --> 00:25:12,990
写在上面
I'll put it at the top.
390
00:25:25,410 --> 00:25:29,040
它是一个参数为X的过程
--to be, in fact, my procedure of one argument x
391
00:25:29,600 --> 00:25:34,560
计算(EXPT X N)
which is the result of exponentiating x to the n.
392
00:25:35,936 --> 00:25:36,960
但是我遇到一个问题
But I have a problem.
393
00:25:38,640 --> 00:25:39,936
我们使用的环境模型
My environment model,
394
00:25:40,576 --> 00:25:43,232
我们用来解释
that is my means of interpretation
395
00:25:44,000 --> 00:25:45,952
目前所定义的语言的这种手段
of interpretation for the language that we've defined so far,
396
00:25:46,272 --> 00:25:48,810
并没有给我说明这个N的值
does not give me a meaning for this n.
397
00:25:52,768 --> 00:25:59,264
因为 正如大家所知
Because, as you know, the, as you know
398
00:26:00,768 --> 00:26:04,256
在这个过程中 N是自由变量
this n is free in this procedure.
399
00:26:06,410 --> 00:26:07,984
环境模型告诉我们
The environment model tells us
400
00:26:08,608 --> 00:26:10,208
自由变量的值
that the meaning of a free variable
401
00:26:11,216 --> 00:26:14,992
取决于过程被定义时所在的环境
is determined in the environment in which this procedure is defined.
402
00:26:16,640 --> 00:26:17,472
在我编写它们的时候
In a way I have written it,
403
00:26:17,488 --> 00:26:19,840
就假设它们已经在黑板上被定义了
assuming these things are defined on the blackboard as is,
404
00:26:21,648 --> 00:26:23,632
NTH-POWER是定义在全局环境下的
this is defined in the global environment,
405
00:26:24,064 --> 00:26:25,152
其中没有N的定义
where there is no n.
406
00:26:25,936 --> 00:26:27,632
因此 N是未绑定的变量
Therefore, n is unbound variable.
407
00:26:28,720 --> 00:26:31,664
但对我们来说
But it's perfectly clear, to most of us,
408
00:26:32,608 --> 00:26:36,320
我们明确希望它是这里和这里的N
that we would like it to be this n and this n.
409
00:26:38,990 --> 00:26:42,672
另外一方面
On the other hand, OK, it would be nice.
410
00:26:42,840 --> 00:26:44,288
当然我们要十分小心地确保
Certainly we've got to be careful here
411
00:26:44,560 --> 00:26:46,064
这里的N是这里的N
of keeping this to be this,
412
00:26:48,960 --> 00:26:52,832
还有这里的这个 要跟这里的一致
and this one over here, wherever it is to be this one.
413
00:26:57,390 --> 00:26:59,744
这种想法造就了
Well, the desire to make this work
414
00:27:00,672 --> 00:27:02,720
一个非常著名的BUG
has led to a very famous bug.
415
00:27:04,656 --> 00:27:06,048
我来细说下这个BUG
I'll tell you about the famous bug.
416
00:27:07,152 --> 00:27:09,408
请看这张幻灯片
Look at this slide.
417
00:27:10,660 --> 00:27:12,704
这种想法被称作“动态绑定”
This is an idea called dynamic binding.
418
00:27:13,990 --> 00:27:16,912
在这种情况下 自由变量不再被
Where, instead of the free variable being interpreted
419
00:27:17,760 --> 00:27:21,232
定义过程时的环境所解释
in the environment of definition of a procedure,
420
00:27:22,400 --> 00:27:25,168
这种情况下 自由变量的值
the free variable is interpreted as having its value
421
00:27:25,440 --> 00:27:29,312
就像是存储在过程调用者的环境中一样
in the environment of the caller of the procedure.
422
00:27:31,850 --> 00:27:34,848
所以在这个系统中
So what you have is a system
423
00:27:34,860 --> 00:27:39,680
你需要不断地搜索调用过程的调用者的环境
where you search up the chain of callers of a particular procedure,
424
00:27:40,432 --> 00:27:42,656
当然 在本例中
and, of course, in this case,
425
00:27:42,840 --> 00:27:44,304
无论NTH-POWER在何处定义
since nth power is called
426
00:27:44,336 --> 00:27:45,980
它都是在PRODUCT过程中被调用的
from inside product whatever it is--
427
00:27:46,416 --> 00:27:48,688
我就需要在SUM过程中再编写一个类似的过程
I had to write our own sum which is the analogous procedure--
428
00:27:50,512 --> 00:27:54,928
而PRODUCT又是被PRODUCT-POWERS所调用
and product is presumably called from product powers,
429
00:27:55,136 --> 00:27:56,144
就是你们在这里看到的
as you see over here,
430
00:27:56,832 --> 00:27:59,376
由于PRODUCT-POWERS过程绑定了变量N
then since product powers bind with variable n ,
431
00:28:00,096 --> 00:28:04,096
因此NTH-POWER中的N会从这个链中派生出来
then nth powers n would be derived through that chain.
432
00:28:08,140 --> 00:28:09,648
相似地 这个N
Similarly, this n,
433
00:28:10,112 --> 00:28:12,016
NTH-POWER中的N在这种情况下
the nth power in n in this case,
434
00:28:12,320 --> 00:28:15,800
可能是来自于这里SUM过程的调用
would come through nth power here being called from inside sum.
435
00:28:15,800 --> 00:28:18,272
你们可以从这里看到 它在SUM内部被调用
You can see it being called from inside sum here.
436
00:28:20,736 --> 00:28:21,696
对应这里的TERM
It's called term here.
437
00:28:22,900 --> 00:28:25,728
而SUM是在SUM-POWERS的内部被调用
But sum was called from inside of sum powers,
438
00:28:26,944 --> 00:28:27,968
后者绑定了N
which bound n.
439
00:28:28,930 --> 00:28:30,656
因此这里就有一个N
Therefore, there would be an n available
440
00:28:32,752 --> 00:28:36,112
可供NTH-POWER中的N取值
that n to get it's value from.
441
00:28:37,950 --> 00:28:39,248
这就是动态 --
This is called dynamic --
442
00:28:39,280 --> 00:28:43,104
这条白线以下的东西 再加上这部分
What we have below this white line plus over here
443
00:28:43,312 --> 00:28:46,048
就是我们所谓的动态绑定
is what's called a dynamic binding view of the world.
444
00:28:46,592 --> 00:28:49,008
用动态绑定的角度来解释 就可以正常运行
If that works, that's a dynamic binding view.
445
00:28:50,850 --> 00:28:52,656
现在 让我们来看一个例子
Now, let's take a look, for example,
446
00:28:54,544 --> 00:28:55,990
要怎么实现这个功能
at just what it takes to implement that.
447
00:28:55,990 --> 00:28:56,960
非常简单
That's real easy.
448
00:28:57,480 --> 00:28:59,344
事实上 最早的Lisp实现
In fact, the very first Lisps
449
00:29:00,016 --> 00:29:02,528
对自由变量有各种形式的解释
had any form of interpretations of the free variables at all,
450
00:29:03,312 --> 00:29:05,984
包括用动态绑定来解释自由变量
had dynamic binding interpretations for the free variables.
451
00:29:06,400 --> 00:29:10,144
APL也是用动态绑定来解释自由变量的
APL has dynamic binding interpretation for the free variables,
452
00:29:11,680 --> 00:29:14,320
而不是词法绑定 或者说静态绑定
not lexical or static binding.
453
00:29:15,220 --> 00:29:17,008
当然 要从EVAL开始修改
So, of course, the change is in eval.
454
00:29:19,312 --> 00:29:20,592
只需修改两个地方就行
And it's really in two places.
455
00:29:22,780 --> 00:29:25,616
首先我们会发现
First of all, one thing we see,
456
00:29:26,528 --> 00:29:28,496
事情变得更简单了
is that things become a little simpler.
457
00:29:29,390 --> 00:29:33,632
如果我不需要
If I don't have to have the -- If I don't have to have the
458
00:29:33,648 --> 00:29:36,200
在定义过程的那个环境中求值
environment be the environment of definition for procedure,
459
00:29:36,448 --> 00:29:38,048
过程在定义的时候就无需
the procedure need not capture
460
00:29:38,432 --> 00:29:40,176
捕获当时的环境了
the environment at the time it's defined.
461
00:29:42,030 --> 00:29:44,960
所以我们可以在幻灯片的这里看到
And so if we look here at this slide,
462
00:29:45,840 --> 00:29:50,080
这条用于判断是否为LAMBDA表达式的子句
we see that the clause for a lambda expression,
463
00:29:50,736 --> 00:29:52,432
过程就是在这个时候创建的
which is the way a procedure is defined,
464
00:29:53,920 --> 00:29:56,736
就不会返回一个带有类型标签
does not make up a thing which has a type closure
465
00:29:56,752 --> 00:30:01,050
和环境结构的过程对象了
and a attached environment structure.
466
00:30:01,290 --> 00:30:02,540
就是EXP本身
It's just the expression itself.
467
00:30:02,540 --> 00:30:04,768
而我们会在其它地方用某种方式来解耦
And we'll decompose that some other way somewhere else.
468
00:30:06,440 --> 00:30:09,408
另外一处修改就是组合式的应用
The other thing we see is the applicator
469
00:30:10,368 --> 00:30:13,696
应用的时候必须要取得调用者的环境
applicator must be able to get the environment of the caller.
470
00:30:14,290 --> 00:30:17,240
调用者的环境就在这里
The caller of a procedure is right here.
471
00:30:17,260 --> 00:30:19,456
如果表达式是一个过程应用--
If the procedure is a application--
472
00:30:19,560 --> 00:30:21,632
如果我们求值的是一个组合式
If the expression we're evaluating is a combination,
473
00:30:21,792 --> 00:30:23,712
我们就会调用一个组合式
then we're going to call a combination
474
00:30:23,936 --> 00:30:25,504
调用一个过程
then we're going to call a procedure
475
00:30:25,664 --> 00:30:27,376
来取得运算符的值
which is the value of the operator.
476
00:30:29,840 --> 00:30:31,440
调用者的环境
The environment of the caller
477
00:30:31,984 --> 00:30:34,512
就是我们当前的环境
is the environment we have right here, available now.
478
00:30:35,890 --> 00:30:40,720
所以 我只需要要把这个环境传递给APPLY
So all I have to do is pass that environment to the applicator, to apply.
479
00:30:41,490 --> 00:30:42,752
我们再来看看APPLY
And if we look at that here,
480
00:30:43,584 --> 00:30:44,976
我们只需要
the only change we have to make
481
00:30:45,712 --> 00:30:48,416
把参数列表加上一个环境ENV
is that fellow takes that environment
482
00:30:48,780 --> 00:30:55,680
然后用这个环境来扩展环境
uses that environment for the purpose of extending that environment
483
00:30:56,670 --> 00:30:59,024
扩展把形式参数
when abiding the formal parameters
484
00:30:59,024 --> 00:31:01,370
和传递过来的实际参数绑定在一起的环境
of the procedure to the arguments that were passed,
485
00:31:03,088 --> 00:31:05,984
而不再是之前由过程捕获的环境了
not an environment that was captured in the procedure.
486
00:31:06,810 --> 00:31:09,456
最早的Lisp偶然地采用了
The reason why the first Lisps were implemented this way,
487
00:31:09,664 --> 00:31:11,968
这种最显然的方式实现
is the sort of the obvious, accidental implementation.
488
00:31:14,130 --> 00:31:16,680
当然 像往常一样 人们习惯了并喜欢上了它
And, of course, as usual, people got used to it and liked it.
489
00:31:17,250 --> 00:31:18,272
因此就有一些人说
And there were some people said,
490
00:31:18,400 --> 00:31:19,504
“就应该这么来做”
this is the way to do it.
491
00:31:21,590 --> 00:31:24,096
不幸的是 这导致一些严重的问题
Unfortunately that causes some serious problems.
492
00:31:25,408 --> 00:31:27,248
最严重的一点是
The most important, serious problem
493
00:31:27,536 --> 00:31:29,840
采用动态绑定
in using dynamic binding
494
00:31:31,008 --> 00:31:33,568
破坏了模块性
is there's a modularity crisis that's involved it.
495
00:31:35,460 --> 00:31:37,664
如果有两个人在一个大型系统上协同工作
If two people are working together on some big system,
496
00:31:38,576 --> 00:31:40,016
那么一个重要的原则就是
then an important thing to one
497
00:31:40,352 --> 00:31:42,192
每个人所使用的名字
is that the names used by each one
498
00:31:42,992 --> 00:31:44,580
都不应该干扰到对方的名字
don't interfere with the names of the other.
499
00:31:47,930 --> 00:31:50,784
如果我写了一段代码
It's important that when I invent some segment of code
500
00:31:51,072 --> 00:31:53,136
别人就不能通过在他代码内部
that no one can make my code stop working
501
00:31:53,880 --> 00:31:56,576
使用我代码中的名字来破坏我的代码
by using my names that I use internal to my code,
502
00:31:56,752 --> 00:31:57,710
这一点很重要
internal to his code.
503
00:31:59,850 --> 00:32:00,464
然而
However,
504
00:32:01,040 --> 00:32:05,184
动态绑定明显地违背了这种特定的模块化约束
dynamic binding violates that particular modularity constraint in a clear way.
505
00:32:06,670 --> 00:32:08,080
我们考虑一下
Consider, for example,
506
00:32:09,184 --> 00:32:10,352
这段代码会有什么效果?
what happens over here.
507
00:32:12,540 --> 00:32:13,792
假设我想要把
Suppose it was the case
508
00:32:15,472 --> 00:32:19,810
我想要把变量NEXT换个名字
that I decided to change the word next.
509
00:32:19,810 --> 00:32:24,416
假设某个人要编写SUM过程
Supposing somebody is writing, somebody is writing sum,
510
00:32:25,104 --> 00:32:26,688
而别人则会使用这个SUM过程
and somebody else is going to use sum.
511
00:32:28,970 --> 00:32:30,320
编写SUM的那个人
The writer of sum
512
00:32:30,496 --> 00:32:32,304
可以选择他想要使用的名字
has a choice of what names he may use.
513
00:32:33,664 --> 00:32:34,848
假设我就是那个编写者
Let's say, I'm that writer.
514
00:32:36,832 --> 00:32:39,300
刚巧 这里我不想用NEXT来表示
Well, by gosh, just happens I didn't want to call this next.
515
00:32:39,300 --> 00:32:40,096
而是用N来表示
I called it n.
516
00:32:41,740 --> 00:32:43,104
所以我把所有出现NEXT的地方
So all places where you see next,
517
00:32:44,288 --> 00:32:45,260
都换成N
I called it n.
518
00:32:48,140 --> 00:32:48,480
哎呀
Whoops.
519
00:32:49,940 --> 00:32:52,224
我没有改变这个程序的规范
I changed nothing about the specifications of this program,
520
00:32:53,328 --> 00:32:54,864
但是整个程序就崩溃了
but this program stops working.
521
00:32:56,110 --> 00:32:57,968
不仅如此 这边也出现了问题
Not only that, unfortunately, this one does too.
522
00:32:59,504 --> 00:33:01,408
为什么会这样?
Why do these programs stop working?
523
00:33:02,260 --> 00:33:03,248
答案非常明显
Well, it's sort of clear.
524
00:33:04,480 --> 00:33:09,296
NTH-POWER中的变量N的值
Instead of chasing out the value of the n
525
00:33:09,310 --> 00:33:13,728
也就是这个N和这个N
that occurs in nth power over here or over here,
526
00:33:14,976 --> 00:33:17,168
根据环境模型的定义
through the environment of definition,
527
00:33:17,200 --> 00:33:19,580
这两个N总是相关的
where this one is always linked to this one,
528
00:33:19,870 --> 00:33:21,488
如果是根据环境模型的定义的话
if it was through the environment of definition,
529
00:33:21,552 --> 00:33:23,630
因为N在这里被绑定
because here is the definition.
530
00:33:24,370 --> 00:33:26,256
这个LAMBDA表达式是在
This lambda expression was executed
531
00:33:26,592 --> 00:33:28,592
N被绑定的环境中执行的
in the environment where that n was defined.
532
00:33:30,700 --> 00:33:31,840
如果不用环境模型的话
If instead of doing that,
533
00:33:32,016 --> 00:33:33,680
我必须追踪过程的调用链
I have to chase through the call chain,
534
00:33:34,784 --> 00:33:36,272
那么就会发生糟糕的事儿
then look what horrible thing happens.
535
00:33:37,320 --> 00:33:41,184
在SUM内部 这个是作为TERM调用的
Well, this was called from inside sum as term, term a.
536
00:33:41,760 --> 00:33:42,384
这里的(TERM A)
term a.
537
00:33:44,780 --> 00:33:46,192
这时再来查找N的值
I'm looking for a value of n.
538
00:33:47,350 --> 00:33:48,400
我得到的不知这个值
Instead of getting this one,
539
00:33:48,848 --> 00:33:49,760
而是这个值
I get that one.
540
00:33:50,700 --> 00:33:52,544
因此 只是这个程序的内部做了修改
So by changing the insides of this program,
541
00:33:52,864 --> 00:33:54,096
这个程序却崩溃了
this program stops working.
542
00:33:56,770 --> 00:34:00,080
LAMBDA就不再像我以前说得那样是个量词了
So I no longer have a quantifier, as I described before.
543
00:34:01,120 --> 00:34:05,136
LAMBDA应该是一个量词
Which is a symbol -- The lambda symbol is supposed to be a quantifier.
544
00:34:05,430 --> 00:34:06,704
量词有一个性质
A thing which has the property
545
00:34:06,896 --> 00:34:11,424
被它绑定的名字都不重要
that the names that are bound by it are unimportant,
546
00:34:12,656 --> 00:34:15,712
只要我用不在过程体中的新名字
that I can uniformly substitute any names for these
547
00:34:16,928 --> 00:34:19,984
统一地在过程体中代换旧名字
throughout this thing, so long as they don't occur in here, the new names,
548
00:34:20,944 --> 00:34:23,168
就不会改变表达式的语义
and the meaning of this expression should remain unchanged.
549
00:34:24,040 --> 00:34:25,504
而我刚才却通过修改一个名字
I've just changed the meaning of the expression
550
00:34:25,536 --> 00:34:27,200
改变了表达式的语义
by changing the one of the names.
551
00:34:28,690 --> 00:34:30,896
因此LAMBDA就不再是一个良好定义的量词了
So lambda is no longer a well defined idea.
552
00:34:32,170 --> 00:34:33,376
这个问题非常严重
It's a very serious problem.
553
00:34:34,550 --> 00:34:35,552
正是因为这个原因
So for that reason,
554
00:34:36,640 --> 00:34:42,512
我和同事放弃了这种抽象方法
I and my buddies have given up this particular kind of abstraction,
555
00:34:43,136 --> 00:34:44,368
相对的 我更喜欢
which I would like to have,
556
00:34:45,616 --> 00:34:47,504
模块化原则
in favor of a modularity principle.
557
00:34:48,090 --> 00:34:50,208
如果你愿意探索解释器
But this is the kind of experiment you can do
558
00:34:51,968 --> 00:34:53,680
那就非常值得做这类实验
if you want to play with these interpreters.
559
00:34:54,832 --> 00:34:56,912
你可以尝试多种设计
You can try them out this way, that way, and the other way.
560
00:34:58,112 --> 00:35:00,256
探索更优雅的语言设计
You see what makes a nicer language.
561
00:35:02,680 --> 00:35:04,496
这是元循环求值器非常重要的功能
So that's a very important thing to be able to do.
562
00:35:04,990 --> 00:35:06,688
现在 我也想讲一讲
Now, I would like to give you a feeling
563
00:35:06,720 --> 00:35:08,496
这种情况下的正确做法
for I think the right thing to do is here.
564
00:35:09,328 --> 00:35:12,912
我又如何来获得这种
How are you going to, how are you going to I get this kind of
565
00:35:13,040 --> 00:35:15,344
词法作用域的能力呢?
of power in a lexical system?
566
00:35:16,280 --> 00:35:17,392
当然 实际情况是
And the answer is, of course,
567
00:35:17,552 --> 00:35:20,032
在这里我想要的是
what I really want is a something that makes up for me
568
00:35:20,688 --> 00:35:22,608
针对特定N的求指数函数
an exponentiator for a particular n.
569
00:35:23,690 --> 00:35:24,288
给定一个N
Given an n,
570
00:35:24,320 --> 00:35:25,664
它会返回给我一个特定的求指数过程
it will make me an exponentiator.
571
00:35:26,280 --> 00:35:27,408
这非常简单
Oh, but that's easy too.
572
00:35:28,170 --> 00:35:30,570
换言之 我可以这样来写
In other words, I can write my program this way.
573
00:35:35,840 --> 00:35:37,840
我要定义一个过程PGEN
I'm going to define a thing called PGEN,
574
00:35:40,256 --> 00:35:42,544
它有一个参数N
which is a procedure of n
575
00:35:43,168 --> 00:35:45,952
返回一个指数过程
which produces for me an exponentiator.
576
00:35:50,240 --> 00:35:51,232
计算X^N
--x to the n.
577
00:35:56,800 --> 00:35:57,984
有了这个以后
Given that I have that,
578
00:35:58,592 --> 00:36:00,880
我就可以进行想要的那种抽象
then I can capture the abstraction I wanted
579
00:36:01,424 --> 00:36:03,936
甚至于现在的封装方法还要更好一些
even better, because now it's encapsulated in a way
580
00:36:04,096 --> 00:36:06,608
因为系统现在不会因改名而崩溃了
where I can't be destroyed by a change of names.
581
00:36:07,890 --> 00:36:12,352
(DEFINE SUM-POWERS
I can define some powers
582
00:36:17,280 --> 00:36:20,704
(LAMBDA (A B N)
I can define some powers to be a procedure again of a, b, and n
583
00:36:21,616 --> 00:36:26,832
(SUM
which is the sum of the term function
584
00:36:26,880 --> 00:36:32,320
(PGEN N)
generated by using this generator, PGEN, n,
585
00:36:34,400 --> 00:36:38,010
A 1+ B)))
with a, incrementer, and b.
586
00:36:42,490 --> 00:36:47,952
(DEFINE PRODUCT-POWERS
And I can define the product of powers
587
00:36:54,112 --> 00:36:58,840
(LAMBDA (A B N)
to be a procedure of a, b, and n
588
00:36:59,808 --> 00:37:09,968
(PRODUCT (PGEN N) A 1+ B)))
which is the product PGEN, n, with a, increment, and b.
589
00:37:11,280 --> 00:37:13,280
当然 这只是一个非常简单的例子
Now, of course, this is a very simple example
590
00:37:13,600 --> 00:37:16,352
这里 我想要抽象的对象也十分简单
where this object that I'm trying to abstract over is small.
591
00:37:17,280 --> 00:37:18,832
但它也有可能是长达100行的代码
But it could be a 100 lines of code.
592
00:37:20,100 --> 00:37:23,670
我这么写是为了保持简单
And so, the purpose of this is, of course, to make it simple.
593
00:37:23,670 --> 00:37:24,576
我给它命了名
I'd give a name to it,
594
00:37:24,736 --> 00:37:26,944
这里它只是一个参数化的名字
it's just that here it's a parameterized name.
595
00:37:28,200 --> 00:37:30,272
这个名字显式地依赖于
It's a name that depends upon, explicitly,
596
00:37:30,496 --> 00:37:33,632
词法作用域下N的值
the lexically apparent value of n.
597
00:37:37,130 --> 00:37:38,592
因此可以把它看做一个很长的名字
So you can think of this as a long name.
598
00:37:40,210 --> 00:37:41,584
这里 我是通过
And here, I've solved my problem
599
00:37:41,760 --> 00:37:45,824
为计算TERM的过程命名
by naming my... by naming the term generation
600
00:37:46,128 --> 00:37:49,220
来解决问题的
procedures within an n in them.
601
00:37:55,080 --> 00:37:55,872
有什么问题吗?
Are there any questions?
602
00:37:57,008 --> 00:37:58,380
David 你说
Oh, yes, David.
603
00:37:58,570 --> 00:38:02,270
学生:刚才那个问题
AUDIENCE: Is the only solution to um...
604
00:38:03,070 --> 00:38:06,464
只能通过新建一个过程来解决吗?
the problem you raise to create another procedure?
605
00:38:06,470 --> 00:38:08,928
换句话说 是不是必须要语言能够
In other words, can this only work in languages that are
606
00:38:08,992 --> 00:38:11,568
把对象定义为过程?
capable of defining objects as procedures?
607
00:38:12,416 --> 00:38:13,760
教授:我明白了
PROFESSOR: Oh, I see.
608
00:38:15,904 --> 00:38:19,744
我构建抽象的这种方法
My solution to making this abstraction,
609
00:38:20,144 --> 00:38:22,864
需要过程能够返回或者导出一个过程
when I didn't want include the procedure inside the body,
610
00:38:23,264 --> 00:38:26,816
以便我不想让过程体中包含特定过程
depends upon my ability to return a procedure or export one.
611
00:38:27,040 --> 00:38:27,248
学生:没错
AUDIENCE: And that's right.
612
00:38:28,190 --> 00:38:28,880
教授:是这样的
PROFESSOR: And that's right.
613
00:38:29,536 --> 00:38:31,520
如果我不能这么做的话
If I don't have that,
614
00:38:32,240 --> 00:38:35,136
那么我就无法去构造一个抽象
then I just don't have this ability to make an abstraction in a way
615
00:38:35,536 --> 00:38:41,776
使得符号之间不会出现冲突
where I don't have possibilities of symbol conflicts that were unanticipated.
616
00:38:43,000 --> 00:38:43,488
你说得对
That's right.
617
00:38:44,144 --> 00:38:46,512
我认为
So one of the, the essential -- I consider, I consider
618
00:38:46,540 --> 00:38:48,912
能够把过程作为返回值
being able to return the procedural value and, therefore,
619
00:38:49,200 --> 00:38:58,288
更一般地说是支持“第一级过程”
and therefore, to sort of have first class procedures, in general,
620
00:38:59,136 --> 00:39:02,464
是模块化程序程序设计所必须的
as being essential to doing very good modular programming.
621
00:39:03,700 --> 00:39:06,432
有很多种方式来解决这个问题
Now, indeed there are many other ways to skin this cat.
622
00:39:07,440 --> 00:39:09,168
你可以的做的就是
What you can do is take for each of the
623
00:39:09,184 --> 00:39:11,840
针对你所需要关心的每一种糟糕情况
for each of the bad things that you have to worry about,
624
00:39:12,272 --> 00:39:15,200
你可以添加一个特殊的FEATURE来解决它
you can make a special feature that covers that thing.
625
00:39:15,840 --> 00:39:17,120
你可以做一个包系统
You can make a package system.
626
00:39:17,744 --> 00:39:21,168
或者像Ada中的模块系统 等等
You can make a module system as in Ada, et cetera. OK?
627
00:39:22,240 --> 00:39:24,880
这些都可以 可能区别只是解决的程度不一
And all of those work, or they cover little regions of it.
628
00:39:26,440 --> 00:39:28,384
而能够把过程作为返回值
The thing is that returning procedures as values
629
00:39:28,416 --> 00:39:29,740
可以解决这所有的问题
cover all of those problems.
630
00:39:32,688 --> 00:39:34,608
这种最简单的机制
And so it's the simplest mechanism
631
00:39:35,584 --> 00:39:37,792
却可以给予你最好的模块性
that gives you the best modularity,
632
00:39:39,216 --> 00:39:41,312
它赋予你所有已知的模块机制
gives you all of the known modularity mechanisms.
633
00:39:45,590 --> 00:39:48,248
好的 该休息一会儿了 谢谢大家
Well, I suppose it's time for the next break, thank you.
634
00:39:48,240 --> 00:40:01,088
[音乐]
[JESU, JOY OF MAN'S DESIRING]
635
00:40:01,280 --> 00:40:04,752
《计算机程序的构造和解释》
636
00:40:25,690 --> 00:40:29,424
讲师:哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授
637
00:40:30,010 --> 00:40:33,280
《计算机程序的构造和解释》
638
00:40:34,170 --> 00:40:37,616
元循环求值器 II
639
00:40:42,320 --> 00:40:44,288
教授:昨天你们学习流的时候
PROFESSOR: Well, yesterday when you learned about streams,
640
00:40:46,016 --> 00:40:51,168
Hal教授告诉了你们求值顺序
Hal worried to you about the order of evaluation
641
00:40:51,952 --> 00:40:53,872
以及过程的延迟求值
and delayed arguments to procedures.
642
00:40:55,616 --> 00:40:58,304
昨天在讲流的时候 我们说
The way we played with streams yesterday,
643
00:41:00,250 --> 00:41:04,224
调用者和被调者都应该认同
it was the responsibility of the caller and the callee
644
00:41:05,776 --> 00:41:08,848
参数是被延迟了的
both agree that an argument was delayed,
645
00:41:09,424 --> 00:41:13,440
如果被调者需要结果 就需要对参数FORCE
and the callee must force the argument if it needs the answer.
646
00:41:15,130 --> 00:41:17,872
因此在过程的设计者和使用者之间
So there had to be a lot of hand shaking between
647
00:41:18,176 --> 00:41:24,320
就有很多关于延时求值的握手
the designer of a procedure and user of it over delayedness.
648
00:41:26,368 --> 00:41:28,720
当然 这看起来相当糟糕
That turns out, of course, to be a fairly bad thing,
649
00:41:29,488 --> 00:41:30,960
虽说对于流没什么不妥
it works all right with streams.
650
00:41:31,740 --> 00:41:32,864
但作为一般性的原则来说
But as a general thing,
651
00:41:32,928 --> 00:41:36,320
我们希望能有个地方
what you want is an idea to have a locus,
652
00:41:36,464 --> 00:41:38,496
能够把我们的设计考虑
a decision, a design decision in general,
653
00:41:38,890 --> 00:41:41,280
显式地、清晰地
to have a place where it's made, explicitly,
654
00:41:41,632 --> 00:41:43,930
标注出来
and notated in a clear way.
655
00:41:45,888 --> 00:41:49,280
因此就不必在过程编写者
And so it's not a very good idea to have to have an agreement,
656
00:41:50,464 --> 00:41:54,896
和使用者之间达成共识
between the person who writes a procedure and the person who calls it,
657
00:41:55,088 --> 00:41:57,984
有关于参数求值
about such details as, maybe, the arguments of evaluation,
658
00:41:58,432 --> 00:41:59,500
以及求值顺序等细节
the order of evaluation.
659
00:41:59,500 --> 00:42:00,750
虽然 这也不是太糟糕
Although, that's not so bad.
660
00:42:01,024 --> 00:42:03,952
我的意思是 可能还有像“输入是一个数字”这样的共识
I mean, we have other such agreements like, the input's a number.
661
00:42:05,200 --> 00:42:06,080
但是
But it would be nice if
662
00:42:06,352 --> 00:42:09,200
如果其中一个人可以全权负责 就再好不过了
one of these guys could take responsibility, completely.
663
00:42:11,020 --> 00:42:13,312
这个想法已经不算新潮了
Now this is not a new idea.
664
00:42:15,510 --> 00:42:21,168
Algol60就支持两种不同的过程调用方法
ALGOL 60 had two different ways of calling a procedure.
665
00:42:22,020 --> 00:42:24,288
参数可以按名或按值传递
The arguments could be passed by name or by value.
666
00:42:25,590 --> 00:42:27,488
按名传递就意味着
And what that meant was that
667
00:42:27,632 --> 00:42:29,720
参数会延时求值
a name argument was delayed.
668
00:42:31,110 --> 00:42:32,848
当你按名传递一个参数时
That when you passed an argument by name,
669
00:42:33,648 --> 00:42:36,528
只有你去取它的值的时候
that its value would only be obtained
670
00:42:36,960 --> 00:42:39,552
它的值才会被计算出来
if you accessed that argument.
671
00:42:42,290 --> 00:42:44,208
所以 现在我就要
So what I'd like to do now is show you,
672
00:42:44,432 --> 00:42:46,960
像之前那样
first of all, a little bit about, again,
673
00:42:46,992 --> 00:42:48,656
对语言做出一些小小的修改
we're going to make a modification to a language.
674
00:42:50,320 --> 00:42:51,792
这里 我们再添加一个新的FEATURE
In this case, we're going to add a feature.
675
00:42:53,370 --> 00:42:55,056
我们要添加的FEATURE是
We're going to add the feature of,
676
00:42:55,360 --> 00:42:58,736
“按名传递参数” 或者可以叫做“延迟求值参数”
by name parameters, if you will, or delayed parameters.
677
00:43:00,430 --> 00:43:04,416
因为事实上 Lisp系统中默认
Because, in fact, the default in our Lisp system
678
00:43:04,768 --> 00:43:06,608
传递的是一个指针
is by the value of a pointer.
679
00:43:08,220 --> 00:43:09,152
指针被复制了一份
A pointer is copied,
680
00:43:09,152 --> 00:43:10,910
但所指的数据结构却没有被复制
but the data structure it points at is not.
681
00:43:13,410 --> 00:43:14,848
现在我要告诉你们
But I'd like to, in fact, show you
682
00:43:15,040 --> 00:43:18,384
如何来添加按名传递参数
is how you add name arguments as well.
683
00:43:19,990 --> 00:43:22,128
为什么我们需要这样的FEATURE呢?
Now again, why would we need such a thing?
684
00:43:23,100 --> 00:43:24,720
假设我们想要开发
Well supposing we wanted to invent
685
00:43:25,248 --> 00:43:28,448
像是某种特殊形式的功能
certain kinds of what otherwise would be special forms,
686
00:43:28,736 --> 00:43:29,720
类似于“保留字”
reserve words?
687
00:43:29,720 --> 00:43:31,488
但不是用保留字的方式来实现
But I'd rather not take up reserve words.
688
00:43:32,180 --> 00:43:34,768
我想用过程来实现类似IF的效果
I want procedures that can do things like if.
689
00:43:36,360 --> 00:43:39,420
无论是IF还是COND 都是特殊形式
If is special, or cond, or whatever it is.
690
00:43:39,420 --> 00:43:40,432
它俩是一样的
It's the same thing.
691
00:43:40,590 --> 00:43:42,864
这个特殊形式用于
It's special in that it determines whether or not
692
00:43:42,928 --> 00:43:45,020
根据谓词返回真假
to evaluate the consequent or the alternative
693
00:43:46,224 --> 00:43:49,760
决定求值真子句还是假子句
based on the value of the predicate part of an expression.
694
00:43:50,840 --> 00:43:53,120
它们都是根据某个值
So taking the value of one thing
695
00:43:53,440 --> 00:43:55,360
来决定是否去做另外的某件事
determines whether or not to do something else.
696
00:43:57,270 --> 00:43:58,880
然而像+之类的过程
Whereas all the procedures like plus,
697
00:43:59,152 --> 00:44:01,200
也就是那些我们现在可以定义的过程
evaluate... the ones that we can define right now,
698
00:44:01,424 --> 00:44:06,560
是在应用前就求值所有的参数
evaluate all of their arguments before application.
699
00:44:08,670 --> 00:44:09,648
因此 举例来说
So, for example,
700
00:44:10,464 --> 00:44:12,416
假设我想定义一个过程
supposing I wish to be able to define something like
701
00:44:15,392 --> 00:44:18,752
用IF来实现与IF相反的效果
the reverse of if in terms of if.
702
00:44:19,856 --> 00:44:20,700
我叫它UNLESS
Call it unless.
703
00:44:24,890 --> 00:44:27,472
参数是 谓词P、真子句C和假子句A
We've a predicate, a consequent, and an alternative.
704
00:44:28,672 --> 00:44:30,448
接下来 我想
Now what I would like to sort of be able to do is
705
00:44:30,464 --> 00:44:32,080
用COND来实现
say-- oh, I'll do it in terms of cond.
706
00:44:32,640 --> 00:44:36,720
(COND ((NOT P)
Cond, if not the predicate,
707
00:44:38,960 --> 00:44:40,320
结果就是真子句C
then take the consequent,
708
00:44:41,584 --> 00:44:45,632
否则就是假子句A
otherwise, take the alternative.
709
00:44:51,290 --> 00:44:52,768
我定义这个过程是为了
Now, what I'd like this to mean,
710
00:44:53,328 --> 00:44:55,408
请考虑下面这种情况
is supposing I do something like this.
711
00:44:56,920 --> 00:45:04,128
(UNLESS (= 1 0)
I'd like this unless say if equals one, 0,
712
00:45:05,088 --> 00:45:06,640
那么结果就是2
then the answer is two,
713
00:45:07,904 --> 00:45:11,350
否则 结果就是(/ 1 0)
otherwise, the quotient of one and 0.
714
00:45:15,920 --> 00:45:18,912
这段代码相当于进行这样的代换:
What I'd like that to mean is the result of substituting
715
00:45:20,000 --> 00:45:23,264
用(= 1 0)、2和(/ 1 0)
equal one, 0, and the quotient of one, 0
716
00:45:23,664 --> 00:45:24,760
分别代换上面的P、C以及A
for p, c, and a.
717
00:45:25,580 --> 00:45:27,584
这样很有趣
I'd like that to mean, and this is funny,
718
00:45:28,112 --> 00:45:30,336
代换后就变成了
I'd like it to transform into or mean
719
00:45:30,752 --> 00:45:38,448
(COND ((NOT (= 1 0))
cond not equal one, 0,
720
00:45:40,624 --> 00:45:42,544
结果就是2
then the result is two,
721
00:45:44,280 --> 00:45:45,104
否则就是
otherwise
722
00:45:48,224 --> 00:45:51,160
(/ 1 0)
I want it to be the quotient one and 0.
723
00:45:54,480 --> 00:45:56,480
你们也知道 如果向Lisp中输入这段代码
Now, you know that if I were to type this into Lisp,
724
00:45:57,744 --> 00:45:58,592
结果会是2
I'd get a two.
725
00:45:59,970 --> 00:46:01,328
这没问题
There's no problem with that.
726
00:46:02,910 --> 00:46:04,640
但如果我输入的是这段代码
However, if I were to type this into Lisp,
727
00:46:05,280 --> 00:46:07,792
由于参数会在过程调用前求值
because all the arguments are evaluated before I start,
728
00:46:09,120 --> 00:46:10,736
那么这段代码就会报错
then I'm going to get an error out of this.
729
00:46:13,380 --> 00:46:15,616
当然 如果成功进行代换的话
So that if the substitutions work at all, of course,
730
00:46:16,032 --> 00:46:16,880
我可以得到正确的结果
I would get the right answer.
731
00:46:16,880 --> 00:46:20,160
但是这里这种情况 代换并不能进行
But here's a case where the substitutions don't work.
732
00:46:22,176 --> 00:46:23,860
我连错误的结果都无法得到
I don't get the wrong answer.
733
00:46:23,860 --> 00:46:24,670
没有结果
I get no answer.
734
00:46:24,800 --> 00:46:25,600
只能得到错误
I get an error.
735
00:46:28,420 --> 00:46:31,216
现在 我要想办法
Now, however, I'd like to be able to make my definition
736
00:46:31,616 --> 00:46:32,992
使这样的定义可以成功运行
so that this kind of thing works.
737
00:46:34,480 --> 00:46:36,512
但我想标注出
What I want to do is say something special
738
00:46:36,704 --> 00:46:38,760
C和A是特殊的东西
about c and a.
739
00:46:39,930 --> 00:46:43,152
我想使它们自动地延时求值
I want them to be delayed automatically.
740
00:46:44,272 --> 00:46:48,080
我不想它们在我调用过程的时候
I don't want them to be, I don't want them to be evaluated
741
00:46:48,528 --> 00:46:49,744
就被求值
at the time I call.
742
00:46:51,520 --> 00:46:52,720
所以我得先制定一种声明
So I'm going to make a declaration,
743
00:46:52,752 --> 00:46:55,328
然后再考虑如何实现此种声明
and then I'm going to see how to implement such a declaration.
744
00:46:55,600 --> 00:46:57,632
再次强调 希望你们能够提醒自己
But again, I want you to say to yourself,
745
00:46:57,792 --> 00:47:00,256
我们这里添加的是临时组件
oh, this is an interesting kluge he's adding in here.
746
00:47:00,760 --> 00:47:02,160
必须要知道
A kluge, you know.
747
00:47:02,256 --> 00:47:04,720
滥用临时组件会造成大混乱
The piles of kluges make a big complicated mess.
748
00:47:05,750 --> 00:47:09,792
还会破坏一些已有的东西
And is this going to foul up something else that might occur.
749
00:47:10,120 --> 00:47:12,704
首先 它会造成语法歧义性么?
First of all, is it syntactically unambiguous?
750
00:47:13,860 --> 00:47:15,504
就我们目前已有的语法来说
Well, it will be syntactically unambiguous
751
00:47:15,712 --> 00:47:16,910
它不会造成什么歧义
with what we've seen so far.
752
00:47:17,840 --> 00:47:20,768
但接下来要做的却可能招来麻烦
But what I'm going to do may, in fact, cause trouble.
753
00:47:21,670 --> 00:47:24,672
我要添加的东西可能会跟
It may be that the thing I had will conflict with
754
00:47:25,152 --> 00:47:27,104
我以后添加的类型声明冲突
type declarations I might want to add in the future
755
00:47:28,192 --> 00:47:31,088
类型系统通过提供已知的类型信息
for giving some system, some compiler or something,
756
00:47:31,216 --> 00:47:33,664
使得语言系统或者编译器可以做出优化
the ability to optimize given the types are known.
757
00:47:34,750 --> 00:47:36,976
当然也会与我想添加的形式参数的
Or it might conflict with other types of declarations
758
00:47:37,008 --> 00:47:39,710
其它类型的声明相冲突
that I might want to make about the formal parameters.
759
00:47:40,570 --> 00:47:42,560
所以这里我并不打算做一个一般性的机制
So I'm not making a general mechanism here
760
00:47:43,770 --> 00:47:45,248
使得我可以添加声明
where I can add declarations.
761
00:47:45,280 --> 00:47:46,544
虽然我很想那么做
And I would like to be able to do that.
762
00:47:46,896 --> 00:47:48,816
但现在并不打算这么做
But I don't want to talk about that right now.
763
00:47:51,010 --> 00:47:53,888
接下来 我要添加某种临时的解决方法
So here I'm going to do, I'm going to build a kluge.
764
00:47:57,568 --> 00:48:08,384
(DEFINE (UNLESS P
So we're going to define unless of a predicate--
765
00:48:08,810 --> 00:48:10,272
后面的参数都是按名调用
and I'm going to call these by name--
766
00:48:12,784 --> 00:48:15,280
分别记作(NAME C)和(NAME A)
the consequent, and name the alternative.
767
00:48:19,850 --> 00:48:25,280
哈 哈 卡在黑板边了
Huh, huh-- I got caught in the corner.
768
00:48:31,760 --> 00:48:35,616
(COND ((NOT P) C)
If not p then the result is c,
769
00:48:36,800 --> 00:48:41,168
(ELSE A)))
else-- that's what I'd like.
770
00:48:44,670 --> 00:48:46,880
我可以显式地声明
Where I can explicitly declare
771
00:48:47,552 --> 00:48:51,650
哪些参数按名称传递或延时求值
certain of the parameters to be delayed, to be computed later.
772
00:48:55,600 --> 00:48:58,480
对解释器的这个修改并不简单
Now, this is actually a very complicated modification to an interpreter
773
00:48:58,704 --> 00:48:59,776
反而相当复杂
rather than a simple one.
774
00:49:00,450 --> 00:49:03,104
我们之前介绍的动态绑定
The ones you saw before, dynamic binding
775
00:49:03,408 --> 00:49:06,896
或者让过程支持不定数目的参数
or adding indefinite argument procedures,
776
00:49:07,504 --> 00:49:08,528
都相对简单
is relatively simple.
777
00:49:09,280 --> 00:49:11,280
这次的修改涉及基本策略
But this one changes a basic strategy.
778
00:49:12,320 --> 00:49:13,392
这里的问题是
The problem here
779
00:49:13,968 --> 00:49:17,630
我们的解释器 就如代码所写的那样
is that our interpreter, as written
780
00:49:17,960 --> 00:49:23,408
在求值组合式时
evaluates a combination by evaluating the procedure,
781
00:49:24,240 --> 00:49:25,920
先通过求值运算符取得过程
the operator producing the procedure,
782
00:49:26,208 --> 00:49:30,352
然后再求值运算对象得到参数
and evaluating the operands producing the arguments,
783
00:49:30,768 --> 00:49:35,264
再把过程应用到参数上
and then doing apply of the procedure to the arguments.
784
00:49:36,384 --> 00:49:37,072
然而这里
However, here,
785
00:49:37,360 --> 00:49:41,488
直到我检查了整个过程
I don't want to evaluate the operands to produce the arguments
786
00:49:41,740 --> 00:49:43,660
确定了程序的声明
until after I examined the procedure
787
00:49:44,624 --> 00:49:46,864
才会去求值程序的参数
to see what the procedure's declarations look like.
788
00:49:49,590 --> 00:49:50,592
我们来看这个
So let's look at that.
789
00:49:52,680 --> 00:49:56,544
这是修改后的求值器
Here we have a changed evaluator.
790
00:49:57,480 --> 00:50:01,152
我是基于那个最简单的词法作用域求值器
I'm starting with the simple lexical evaluator,
791
00:50:01,728 --> 00:50:02,650
不是动态绑定的那个
not dynamic
792
00:50:04,144 --> 00:50:08,208
但是却要做一些类似于动态绑定的修改
but we're going to have to do something sort of similar in some ways.
793
00:50:09,750 --> 00:50:11,456
这是因为
Because of the fact that,
794
00:50:11,904 --> 00:50:13,344
如果我延时一个过程 --
if I delay a procedure--
795
00:50:13,664 --> 00:50:15,152
哦说错了 -- 延时一个过程的参数
I'm sorry-- delay an argument to a procedure,
796
00:50:15,408 --> 00:50:17,520
就必须把当前的环境和参数关联在一起
I'm going to have to attach and environment to it.
797
00:50:19,360 --> 00:50:21,552
还记得Hal教授如何实现DELAY的吧?
Remember how Hal implemented delay.
798
00:50:23,380 --> 00:50:25,440
Hal教授把DELAY实现为
Hal implemented delay as being
799
00:50:25,504 --> 00:50:27,472
一个无参过程
a procedure of no arguments
800
00:50:28,560 --> 00:50:30,528
用来执行某些表达式
which does some expression.
801
00:50:31,180 --> 00:50:36,944
就是这样让表达式延迟求值的
That's what delay of the expression is. --of that expression.
802
00:50:39,296 --> 00:50:40,992
(DELAY E)实际上是这个
This turned into something like this.
803
00:50:44,520 --> 00:50:46,928
然而 如果我求值这个LAMBDA表达式
Now, however, if I evaluate a lambda expression,
804
00:50:47,424 --> 00:50:49,200
我就必须得捕获当前环境
I have to capture the environment.
805
00:50:51,410 --> 00:50:53,456
这是因为
The reason why is because there are
806
00:50:54,608 --> 00:50:56,320
我想让这其中的变量的值
there are variables in there
807
00:50:57,024 --> 00:51:00,832
取决于它们被定义时的上下文
who's meaning I wish to derive from the context where this was written.
808
00:51:04,010 --> 00:51:05,760
这也就是为什么要用LAMBDA表达式
So that's why a lambda does the job.
809
00:51:06,624 --> 00:51:07,504
这才是正确的
It's the right thing.
810
00:51:08,070 --> 00:51:15,120
(FORCE E)则相当于
And such that the forcing of a delayed expression
811
00:51:16,528 --> 00:51:20,080
无参地调用这个过程
was same thing as calling that with no arguments.
812
00:51:21,090 --> 00:51:22,288
恰恰和上面相对
It's just the opposite of this.
813
00:51:24,100 --> 00:51:26,944
这个调用产生的环境则是
Producing an environment of the call
814
00:51:27,360 --> 00:51:29,904
定义这个过程时的环境
which is, in fact, the environment where this was defined
815
00:51:30,816 --> 00:51:32,368
额外加上一个空框架
with an extra frame in it that's empty.
816
00:51:33,232 --> 00:51:34,416
我并不在意它
I don't care about that.
817
00:51:36,240 --> 00:51:39,408
我们再来看这张幻灯片
Well, if we go back to this slide,
818
00:51:40,992 --> 00:51:43,728
仔细观察一会儿
since it's the case, if we look at this for a second,
819
00:51:44,144 --> 00:51:46,128
会发现大部分跟以前相同
everything is the same as it was before
820
00:51:46,350 --> 00:51:50,656
只是对应用或组合式的处理不同
except the case of applications or combinations.
821
00:51:51,980 --> 00:51:53,712
处理组合式分两步
And combinations are going to do two things.
822
00:51:54,680 --> 00:51:57,792
首先要求值这个过程
One, is I have to evaluate the procedure--
823
00:51:57,920 --> 00:51:59,888
我就必须通过求值运算符来得到对应过程
I have to get the procedure-- by evaluating the operator.
824
00:52:00,704 --> 00:52:01,696
也就是这一部分
That's what you see right here.
825
00:52:02,380 --> 00:52:04,352
我得这个值是计算求出的现值
I have to make sure that that's current,
826
00:52:04,464 --> 00:52:05,760
而不是一个延时对象
that is not a delayed object,
827
00:52:06,368 --> 00:52:09,856
也就要求值它在被延时前的表达式
and evaluate that to the point where became it's forced now.
828
00:52:10,730 --> 00:52:12,080
接下来我就要
And then I have to somehow
829
00:52:12,240 --> 00:52:17,328
把它应用于运算对象
apply that to the, to the operands.
830
00:52:18,030 --> 00:52:19,616
但我仍然要保持这个环境
But I have to keep the environment,
831
00:52:19,632 --> 00:52:20,920
并将其传递过去
pass that environmental along.
832
00:52:21,530 --> 00:52:23,710
如果有一些运算对象是延时了的
So some of those operands I may have to delay.
833
00:52:23,710 --> 00:52:27,536
我就需要为这些运算对象附上相应的环境
I may have to attach that environment to those operands.
834
00:52:29,664 --> 00:52:31,520
这里的处理相当复杂
This is a rather complicated thing happening here.
835
00:52:32,990 --> 00:52:34,240
来看看APPLY中对应的部分
Looking at that in apply.
836
00:52:36,400 --> 00:52:38,720
APPLY这一部分处理基本过程
Apply, well it has a primitive procedure
837
00:52:39,360 --> 00:52:40,600
这和之前一样
thing just like before.
838
00:52:42,610 --> 00:52:44,688
但复合过程部分就比较有意思了
But the compound one is a little more interesting.
839
00:52:47,250 --> 00:52:49,520
和之前一样 我需要求值过程体
I have to evaluate the body, just as before,
840
00:52:50,480 --> 00:52:51,984
基于的环境是
in an environment which is
841
00:52:52,288 --> 00:52:54,976
把形式参数和
which is the result of binding some
842
00:52:55,616 --> 00:53:00,290
实际参数绑定在一起的结果
formal parameters to arguments in the environment.
843
00:53:00,290 --> 00:53:01,072
是这样的
That's true.
844
00:53:01,530 --> 00:53:03,820
环境来自于过程对象
The environment is the one that comes from the procedure now.
845
00:53:03,820 --> 00:53:06,656
因为我们的语言是词法作用域、静态绑定的
It's a lexical language, statically bound.
846
00:53:08,040 --> 00:53:11,824
然而 我还需要去掉NAME声明
However, one thing I have to do is strip off the declarations
847
00:53:11,840 --> 00:53:12,840
获得变量的实际名字
to get the names of the variables.
848
00:53:12,848 --> 00:53:15,200
这是由VNAMES过程完成的
That's what this guy does, vnames.
849
00:53:15,450 --> 00:53:16,672
然后要做的就是
And the other thing I have to do
850
00:53:16,976 --> 00:53:18,864
处理这些声明
is process these declarations,
851
00:53:19,136 --> 00:53:21,520
决定这些运算对象中
deciding which of these operands--
852
00:53:21,760 --> 00:53:23,920
现在它们还是形式参数 而非实际参数
that's the operands now, as opposed to the arguments--
853
00:53:24,096 --> 00:53:25,872
哪些运算对象需要立即求值
which of these operands to evaluate,
854
00:53:26,624 --> 00:53:30,208
而哪些运算对象又要
and which of them are to be
855
00:53:30,992 --> 00:53:33,770
用某种方式封装为延时对象
encapsulated in delays of some sort.
856
00:53:37,280 --> 00:53:40,080
另外 在处理基本过程这里
The other thing you see here is that we got a primitive,
857
00:53:40,600 --> 00:53:42,384
当遇到像+这样的基本过程
a primitive like plus,
858
00:53:42,688 --> 00:53:45,580
它们的参数最好立即求值
had better get at the real operands.
859
00:53:45,820 --> 00:53:47,392
也就我们需要是这里FORCE这些表达式
So here is a place where we're going to have to force them.
860
00:53:47,920 --> 00:53:50,384
EVLIST中完成了很多FORCE操作
And we're going to look at what evlist is going to have to do a bunch of forces.
861
00:53:51,340 --> 00:53:52,780
现在 我们有了两种不同的EVLIST
So we have two different kinds of evlist now.
862
00:53:52,780 --> 00:53:54,096
EVLIST和GEVLIST
We have evlist and gevlist.
863
00:53:54,520 --> 00:53:57,168
GEVLIST封装延迟参数
Gevlist is going to wrap delays around some things
864
00:53:57,184 --> 00:53:59,740
而对另外的参数立即求值
and force others, evaluate others.
865
00:53:59,870 --> 00:54:05,856
而EVLIST则会FORCE所有的表达式
And this guy's going to do some forcing of things.
866
00:54:07,900 --> 00:54:09,168
简单地看下EVLIST的代码
Just looking at this a little bit,
867
00:54:09,696 --> 00:54:11,984
课后你们一定要亲自上手试试
this is a game you must play for yourself, you know.
868
00:54:12,250 --> 00:54:14,672
光是听我在这里讲课
It's not something that you're going to see all possible
869
00:54:14,720 --> 00:54:18,200
可不能够学到求值器的不同变种
variations on an evaluator talking to me.
870
00:54:19,520 --> 00:54:21,248
你们需要上手亲自实践一下。
What you have to do is do this for yourself.
871
00:54:21,376 --> 00:54:23,840
你试验过后 对它们有了感悟
And after you feel this, you play this a bit,
872
00:54:24,224 --> 00:54:27,024
你才能理解各种可能的设计决策
you get to see all the possible design decisions and what they might mean,
873
00:54:27,776 --> 00:54:29,168
才能清楚它们如何相互关联
and how they interact with each other.
874
00:54:29,930 --> 00:54:32,384
了解求值器描述的是何种语言
So what languages might have in them.
875
00:54:33,160 --> 00:54:34,640
以及构建一门合理的语言
And what are some of the consistent sets
876
00:54:34,944 --> 00:54:36,320
需要哪些一致性集合
that make a legitimate language.
877
00:54:37,200 --> 00:54:40,064
哪些临时方案又是复杂而无用
Whereas what things are complicated kluges that are just piles of junk.
878
00:54:41,850 --> 00:54:44,688
就和我说得一样 这里的EVLIST
So evlist of course, over here, just as I said,
879
00:54:44,816 --> 00:54:46,032
参数之一为运算对象表
is a list of operands
880
00:54:46,704 --> 00:54:50,280
表中的元素会在求值之后被取消延时
which are going to be undelayed after evaluation.
881
00:54:50,750 --> 00:54:51,904
它们都会被FORCE
So these are going to be forced,
882
00:54:53,280 --> 00:54:54,448
无论它们是否为延时对象
whatever that's going to mean.
883
00:54:56,050 --> 00:54:58,512
下一个 GEVLIST
And gevlist, which is the next thing--
884
00:55:01,264 --> 00:55:01,856
谢谢
Thank you.
885
00:55:04,040 --> 00:55:06,350
我们在这里会发现
What we see here, uh
886
00:55:07,808 --> 00:55:09,616
这里面有多种可能
well there's a couple of possibilities.
887
00:55:09,810 --> 00:55:11,520
要么是普通的情况
Either it's a normal, ordinary thing,
888
00:55:12,480 --> 00:55:13,696
比如元素直接是一个符号
a symbol sitting there
889
00:55:13,744 --> 00:55:16,200
就像UNLESS中的参数P那样
like the predicate in the unless,
890
00:55:17,648 --> 00:55:18,816
对应这一部分代码
and that's what we have here.
891
00:55:19,390 --> 00:55:22,496
在这种情况下 我们就用应用序来求值
In which case, this is intended to be evaluated in applicative order.
892
00:55:23,340 --> 00:55:25,456
基本上就像以前一样
And it's, essentially, just what we had before.
893
00:55:25,630 --> 00:55:28,848
就是将EVAL映射在这个表上
It's mapping eval down the list.
894
00:55:29,952 --> 00:55:32,144
换言之 就是先求值第一个表达式
In other words, I evaluate the first expression
895
00:55:32,656 --> 00:55:37,360
然后在ENV中 求值(GEVLIST (CDR EXPRS))
and continue gevlisting the CDR of the expression in the environment.
896
00:55:37,936 --> 00:55:43,200
然而 我们也可能遇到按名传递的参数
However, it's possible that this is a name parameter.
897
00:55:44,000 --> 00:55:45,056
如果参数是按名传递
If it's a name parameter,
898
00:55:45,200 --> 00:55:46,592
我就需要给它包裹上一个DELAY
I want to put a delay in
899
00:55:47,008 --> 00:55:50,976
DELAY里面就是我想按名调用的表达式
which combines that expression, which I'm calling by name,
900
00:55:52,144 --> 00:55:57,740
还要附上定义过程时的环境
with the environment that's available at this time
901
00:55:59,056 --> 00:56:00,592
把它们作为实际参数
and passing that as the parameter.
902
00:56:02,790 --> 00:56:05,040
然后像这样继续递归处理
And this is part of the mapping process that you see here.
903
00:56:09,070 --> 00:56:11,310
这个解释器中另外一个有意思的地方
The only other interesting place in this procedure
904
00:56:11,376 --> 00:56:13,536
就在于COND
in this interpreter is cond.
905
00:56:14,700 --> 00:56:15,920
人们可能就这么来写
People tend to write this thing,
906
00:56:15,936 --> 00:56:17,248
然后就不管了
and then they leave this one out.
907
00:56:18,550 --> 00:56:19,984
你需要在一处FORCE
There's a place where you have to force.
908
00:56:20,510 --> 00:56:23,104
COND表达式需要知道
Conditionals have to know
909
00:56:24,208 --> 00:56:25,904
谓词判定结果的真假
whether or not the answer is true or false.
910
00:56:25,990 --> 00:56:26,832
就像基本过程那样
It's like a primitive.
911
00:56:28,550 --> 00:56:30,560
求值COND语句时 需要FORCE
When you do a conditional, you have to force.
912
00:56:31,728 --> 00:56:33,952
剩下的细节就没什么特别的了
Now, I'm not going to look at any more of this in any detail.
913
00:56:34,624 --> 00:56:36,288
就先不深究了
It isn't very exciting.
914
00:56:36,750 --> 00:56:38,990
剩下的就是如何实现MAKE-DELAY
And what's left is how you make delays.
915
00:56:38,990 --> 00:56:40,912
延时对象是一种数据结构
Well, delays are data structures
916
00:56:41,312 --> 00:56:44,752
它包括:类型标识、表达式以及环境
which contain an expression, an environment, and a type on them.
917
00:56:44,840 --> 00:56:46,368
它的类型标识是'THUNK
And it says they're a thunk.
918
00:56:46,960 --> 00:56:48,464
这个术语来自于Algol语言
That comes from ALGOL language,
919
00:56:49,072 --> 00:56:50,816
据说这是个拟声词
and it's claimed to be the sound of
920
00:56:50,832 --> 00:56:52,064
是把东西压栈的声音
of something being pushed on a stack.
921
00:56:52,970 --> 00:56:53,410
我不太清楚
I don't know.
922
00:56:53,410 --> 00:56:57,120
我既不是Algol学家 又不是Algol程序员
I was not an ALGOLician, so or an ALGOLite or whatever,
923
00:56:57,600 --> 00:56:58,384
所以我不太清楚
so I don't know.
924
00:56:58,740 --> 00:56:59,648
但据说它是那样的
But that's what was claimed.
925
00:57:00,270 --> 00:57:01,568
而UNDELAY的定义则是
And undelay is something
926
00:57:01,770 --> 00:57:03,664
递归地UNDELAY这些THUNK
which will recursively undelay thunks
927
00:57:03,696 --> 00:57:06,000
直到得到一个非THUNK对象
until the thunk becomes something which isn't a thunk.
928
00:57:07,728 --> 00:57:10,944
这就是如何实现Algol中的按名调用
This is the way you implement a call by name like thing in ALGOL.
929
00:57:12,050 --> 00:57:13,760
差不多就是这样了
And that's about all there is.
930
00:57:15,210 --> 00:57:16,256
有什么问题吗?
Are there any questions?
931
00:57:26,688 --> 00:57:27,520
学生:Gerry?
AUDIENCE: Gerry?
932
00:57:28,096 --> 00:57:28,800
教授:你说 Vesko
PROFESSOR: Yes, Vesko?
933
00:57:30,030 --> 00:57:32,992
学生:我注意到 对于基本过程
AUDIENCE: I noticed you avoided calling by name
934
00:57:33,440 --> 00:57:34,890
你是避免按名调用的
in the primitive procedures,
935
00:57:36,410 --> 00:57:38,384
我很想知道 你为什么要这样?
I was wondering what cause you have on that?
936
00:57:38,416 --> 00:57:39,216
需要这样吗?
You never need that?
937
00:57:40,070 --> 00:57:41,616
教授:Vesko想问的是
PROFESSOR: Vesko is asking
938
00:57:42,064 --> 00:57:46,000
基本过程也按名调用是否合理?
if it's ever reasonable to call a primitive procedure by name?
939
00:57:47,140 --> 00:57:48,704
答案是:是的
The answer is, yes.
940
00:57:49,270 --> 00:57:52,320
有一种情况下是可以的 实际上是两种
There's one particular case where it's reasonable, actually two.
941
00:57:55,536 --> 00:57:58,272
比如用CONS来构造一个数据结构
Construction of a data structure like cons
942
00:57:59,020 --> 00:58:02,000
构建一个元素个数不定的数组时
where making an array if you have arrays with any number of elements.
943
00:58:03,264 --> 00:58:07,440
就没必要求值参数
OK? It's unnecessary to evaluate those arguments.
944
00:58:07,440 --> 00:58:08,832
你只需要创建一些PROMISE
All you need is promises
945
00:58:09,104 --> 00:58:10,816
在确实需要时才来求值这些参数
to evaluate those arguments if you look at them.
946
00:58:11,504 --> 00:58:15,088
如果我把两个对象CONS起来
If I cons together a, two things,
947
00:58:16,240 --> 00:58:17,776
那么我CONS这些PROMISE
then I could cons together the promises
948
00:58:17,808 --> 00:58:19,936
就和CONS这些对象一样容易
just as easily as I can cons together the things.
949
00:58:21,150 --> 00:58:23,376
甚至在对它们进行CAR CDR的时候
And it's not even when I CAR CDR them
950
00:58:23,392 --> 00:58:24,304
也不用进行实际的计算
that I have to look at them.
951
00:58:24,840 --> 00:58:26,976
取出PROMISE 并直接传递给其它人
That just gets out the promises and passes them to somebody.
952
00:58:28,260 --> 00:58:30,512
这也就是为什么Alonzo Church用LAMBDA演算
That's why the lambda calculus definition, the
953
00:58:30,576 --> 00:58:34,032
定义的CAR、CDR和CONS说得通的原因
the Alonzo Church definition of CAR, CDR, and cons makes sense.
954
00:58:34,420 --> 00:58:36,320
这是因为CAR、CDR以及CONS并没有执行计算
It's because no work is done in CAR, CDR, and cons,
955
00:58:36,380 --> 00:58:40,064
你们可以认为它是在重组数据而已
it's just shuffling data, it's just routing, if you will.
956
00:58:40,990 --> 00:58:42,208
然而像 + 这样的过程
However, the things that do have
957
00:58:42,240 --> 00:58:43,840
必须要了解参数是什么
to look at data are things like plus.
958
00:58:45,280 --> 00:58:46,912
它们需要确认
Because they have a look at the bits
959
00:58:47,120 --> 00:58:48,304
构成这些数字的比特
that the numbers are made out of,
960
00:58:48,320 --> 00:58:50,448
除非它们处理的是LAMBDA演算中的数字
unless they're lambda calculus numbers
961
00:58:50,448 --> 00:58:51,880
这就是另外一码事了
which are funny. OK?
962
00:58:52,430 --> 00:58:53,584
为了运算加法
They have to look at the bits to
963
00:58:53,776 --> 00:58:55,530
它需要知道构成数字的比特
be able to crunch them together to do the add.
964
00:58:59,210 --> 00:58:59,920
因此 实际上
So, in fact,
965
00:59:00,192 --> 00:59:02,784
数据的构造过程和选择过程
data constructors, data selectors,
966
00:59:03,248 --> 00:59:05,504
以及具有副作用的数据对象
in fact, things that side-effect data objects
967
00:59:06,270 --> 00:59:09,760
在最极端的惰性解释器中
don't need to do, don't need to do any forcing
968
00:59:11,344 --> 00:59:13,392
也不需要被FORCE
in the laziest possible interpreters.
969
00:59:16,460 --> 00:59:16,992
另外一方面
On the other hand
970
00:59:17,024 --> 00:59:18,700
针对数据结构的谓词需要被FORCE
predicates on data structures have to.
971
00:59:19,616 --> 00:59:22,656
如果你想判断 这是一个序对吗?
If you want to say, is this a, is this a pair?
972
00:59:23,560 --> 00:59:24,400
或者是一个符号?
Or is it a symbol?
973
00:59:24,640 --> 00:59:26,576
最好搞清楚是什么
Well, you better find out. You got to look at it then.
974
00:59:30,300 --> 00:59:31,184
还有问题吗?
Any other questions?
975
00:59:40,050 --> 00:59:41,610
那好吧 下课
Oh, well, I suppose it's time for a break.
976
00:59:42,100 --> 00:59:55,840
MIT OpenCourseWare
http://ocw.mit.edu
977
00:59:55,840 --> 01:00:04,560
本项目主页
https://github.com/DeathKing/Learning-SICP
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Ruby
1
https://gitee.com/jacklisp/Learning-SICP.git
git@gitee.com:jacklisp/Learning-SICP.git
jacklisp
Learning-SICP
Learning-SICP
master

搜索帮助