SICP / CYMRAEG

SICP · Yr ail argraffiad · Scheme

1.1 Elfennau Rhaglennu

Harold Abelson a Gerald Jay Sussman gyda Julie Sussman · Cyfieithiad Cymraeg

Mae iaith raglennu rymus yn fwy na modd o gyfarwyddo cyfrifiadur i gyflawni tasgau yn unig. Mae'r iaith hefyd yn gweithredu fel fframwaith yr ydym yn trefnu ein syniadau am brosesau ynddo. Felly, wrth ddisgrifio iaith, dylem roi sylw arbennig i'r modd y mae'r iaith yn ei ddarparu ar gyfer cyfuno syniadau syml i ffurfio syniadau mwy cymhleth. Mae gan bob iaith rymus dri mecanwaith i gyflawni hyn:

  • mynegiadau cyntefig, sy'n cynrychioli'r endidau symlaf y mae'r iaith yn ymwneud â hwy,
  • dulliau cyfuno, a ddefnyddir i adeiladu elfennau cyfansawdd o rai symlach, a
  • dulliau haniaethu, a ddefnyddir i enwi a thrin elfennau cyfansawdd fel unedau.

Wrth raglennu, ymdriniwn â dau fath o elfen: gweithdrefnau a data. (Yn ddiweddarach byddwn yn darganfod nad ydynt mewn gwirionedd mor wahanol â hynny.) Yn anffurfiol, data yw'r “pethau” yr ydym am eu trin, a disgrifiadau o'r rheolau ar gyfer trin y data yw gweithdrefnau. Felly, dylai unrhyw iaith raglennu rymus allu disgrifio data cyntefig a gweithdrefnau cyntefig a dylai fod ganddi ddulliau ar gyfer cyfuno a haniaethu gweithdrefnau a data.

Yn y bennod hon byddwn yn ymdrin â data rhifiadol syml yn unig er mwyn gallu canolbwyntio ar y rheolau ar gyfer adeiladu gweithdrefnau.4 Mewn penodau diweddarach gwelwn fod yr un rheolau hyn yn caniatáu inni adeiladu gweithdrefnau i drin data cyfansawdd hefyd.

1.1.1Mynegiadau

Un ffordd hawdd o ddechrau rhaglennu yw archwilio rhywfaint o ryngweithio nodweddiadol â dehonglydd ar gyfer tafodiaith Scheme Lisp. Dychmygwch eich bod yn eistedd wrth derfynell gyfrifiadurol. Rydych yn teipio mynegiad, ac mae'r dehonglydd yn ymateb drwy ddangos canlyniad gwerthuso'r mynegiad hwnnw.

Un math o fynegiad cyntefig y gallech ei deipio yw rhif. (Yn fwy manwl gywir, mae'r mynegiad a deipiwch yn cynnwys y rhifolion sy'n cynrychioli'r rhif ym môn 10.) Os cyflwynwch rif i Lisp

486

bydd y dehonglydd yn ymateb drwy argraffu5

486

Gellir cyfuno mynegiadau sy'n cynrychioli rhifau â mynegiad sy'n cynrychioli gweithdrefn gyntefig (megis + neu *) i ffurfio mynegiad cyfansawdd sy'n cynrychioli cymhwyso'r weithdrefn i'r rhifau hynny. Er enghraifft:

(+ 137 349)
486

(- 1000 334)
666

(* 5 99)
495

(/ 10 5)
2

(+ 2.7 10)
12.7

Gelwir mynegiadau fel y rhain, a ffurfir drwy amgáu rhestr o fynegiadau mewn cromfachau er mwyn dynodi cymhwyso gweithdrefn, yn gyfuniadau. Gelwir yr elfen bellaf i'r chwith yn y rhestr yn weithredydd, a gelwir yr elfennau eraill yn operandau. Ceir gwerth cyfuniad drwy gymhwyso'r weithdrefn a bennir gan y gweithredydd i'r argiau sy'n werthoedd yr operandau.

Gelwir y confensiwn o roi'r gweithredydd i'r chwith o'r operandau yn nodiant rhagddodiadol, a gall fod braidd yn ddryslyd ar y dechrau oherwydd ei fod yn wahanol iawn i'r confensiwn mathemategol arferol. Mae gan nodiant rhagddodiadol sawl mantais, fodd bynnag. Un ohonynt yw y gall ddarparu ar gyfer gweithdrefnau sy'n gallu cymryd nifer mympwyol o argiau, fel yn yr enghreifftiau canlynol:

(+ 21 35 12 7)
75

(* 25 4 12)
1200

Ni all unrhyw amwysedd godi, oherwydd mai'r gweithredydd yw'r elfen bellaf i'r chwith bob amser a bod y cyfuniad cyfan wedi'i amgáu gan y cromfachau.

Ail fantais nodiant rhagddodiadol yw ei fod yn ymestyn mewn ffordd syml i ganiatáu nythu cyfuniadau, hynny yw, cael cyfuniadau y mae eu helfennau eu hunain yn gyfuniadau:

(+ (* 3 5) (- 10 6))
19

Nid oes terfyn (mewn egwyddor) ar ddyfnder nythu o'r fath nac ar gymhlethdod cyffredinol y mynegiadau y gall y dehonglydd Lisp eu gwerthuso. Ni bobl sy'n cael ein drysu gan fynegiadau sy'n dal yn gymharol syml, megis

(+ (* 3 (+ (* 2 4) (+ 3 5))) (+ (- 10 7) 6))

y byddai'r dehonglydd yn ei werthuso'n rhwydd i fod yn 57. Gallwn helpu ein hunain drwy ysgrifennu mynegiad o'r fath ar y ffurf

(+ (* 3
      (+ (* 2 4)
         (+ 3 5)))
   (+ (- 10 7)
      6))

gan ddilyn confensiwn fformatio a elwir yn argraffu taclus, lle ysgrifennir pob cyfuniad hir fel bod yr operandau wedi'u halinio'n fertigol. Mae'r mewnoliadau a geir yn dangos strwythur y mynegiad yn glir.6

Hyd yn oed â mynegiadau cymhleth, mae'r dehonglydd bob amser yn gweithredu yn yr un cylch sylfaenol: mae'n darllen mynegiad o'r derfynell, yn gwerthuso'r mynegiad, ac yn argraffu'r canlyniad. Yn aml mynegir y modd gweithredu hwn drwy ddweud bod y dehonglydd yn rhedeg mewn dolen darllen-gwerthuso-argraffu. Sylwch yn benodol nad oes angen cyfarwyddo'r dehonglydd yn benodol i argraffu gwerth y mynegiad.7

1.1.2Enwi a'r Amgylchedd

Agwedd hollbwysig ar iaith raglennu yw'r modd y mae'n ei ddarparu ar gyfer defnyddio enwau i gyfeirio at wrthrychau cyfrifiadurol. Dywedwn fod yr enw yn dynodi newidyn y mae ei werth yn wrthrych hwnnw.

Yn nhafodiaith Scheme Lisp, enwn bethau â define. Mae teipio

(define size 2)

yn peri i'r dehonglydd gysylltu'r gwerth 2 â'r enw size.8 Unwaith y bydd yr enw size wedi'i gysylltu â'r rhif 2, gallwn gyfeirio at y gwerth 2 yn ôl ei enw:

size
2

(* 5 size)
10

Dyma enghreifftiau pellach o ddefnyddio define:

(define pi 3.14159)
(define radius 10)

(* pi (* radius radius))
314.159

(define circumference (* 2 pi radius))

circumference
62.8318

Define yw dull symlaf ein hiaith o haniaethu, oherwydd ei fod yn caniatáu inni ddefnyddio enwau syml i gyfeirio at ganlyniadau gweithrediadau cyfansawdd, megis yr circumference a gyfrifwyd uchod. Yn gyffredinol, gall fod gan wrthrychau cyfrifiadurol strwythurau cymhleth iawn, a byddai'n hynod anghyfleus gorfod cofio ac ailadrodd eu manylion bob tro yr ydym am eu defnyddio. Yn wir, llunnir rhaglenni cymhleth drwy adeiladu, gam wrth gam, wrthrychau cyfrifiadurol o gymhlethdod cynyddol. Mae'r dehonglydd yn gwneud y gwaith hwn o lunio rhaglen gam wrth gam yn arbennig o gyfleus oherwydd y gellir creu cysylltiadau enw-gwrthrych yn gynyddrannol mewn rhyngweithiadau olynol. Mae'r nodwedd hon yn annog datblygu a phrofi rhaglenni fesul cam ac mae'n gyfrifol i raddau helaeth am y ffaith bod rhaglen Lisp fel arfer yn cynnwys nifer fawr o weithdrefnau cymharol syml.

Dylai fod yn glir bod y posibilrwydd o gysylltu gwerthoedd â symbolau a'u hadalw'n ddiweddarach yn golygu bod yn rhaid i'r dehonglydd gynnal rhyw fath o gof sy'n cadw golwg ar y parau enw-gwrthrych. Gelwir y cof hwn yn amgylchedd (yn fwy manwl gywir yr amgylchedd byd-eang, gan y gwelwn yn ddiweddarach y gall cyfrifiad gynnwys nifer o amgylcheddau gwahanol).9

1.1.3Gwerthuso Cyfuniadau

Un o'n nodau yn y bennod hon yw ynysu materion sy'n ymwneud â meddwl yn weithdrefnol. Fel enghraifft, gadewch inni ystyried bod y dehonglydd ei hun yn dilyn gweithdrefn wrth werthuso cyfuniadau.

I werthuso cyfuniad, gwnewch y canlynol:

  1. Gwerthuswch isfynegiadau'r cyfuniad.
  2. Cymhwyswch y weithdrefn sy'n werth yr isfynegiad pellaf i'r chwith (y gweithredydd) i'r argiau sy'n werthoedd yr isfynegiadau eraill (yr operandau).

Mae hyd yn oed y rheol syml hon yn dangos rhai pwyntiau pwysig am brosesau yn gyffredinol. Yn gyntaf, sylwch fod y cam cyntaf yn mynnu, er mwyn cyflawni'r broses werthuso ar gyfer cyfuniad, bod yn rhaid inni gyflawni'r broses werthuso ar bob elfen o'r cyfuniad yn gyntaf. Felly, mae'r rheol werthuso yn ddychweliadol ei natur; hynny yw, mae'n cynnwys, fel un o'i chamau, yr angen i alw'r rheol ei hun.10

Sylwch mor gryno y gellir defnyddio'r syniad o ddychweliad i fynegi'r hyn a fyddai fel arall, yn achos cyfuniad sydd wedi'i nythu'n ddwfn, yn cael ei ystyried yn broses eithaf cymhleth. Er enghraifft, mae gwerthuso

(* (+ 2 (* 4 6)) (+ 3 5 7))

yn gofyn am gymhwyso'r rheol werthuso i bedwar cyfuniad gwahanol. Gallwn gael darlun o'r broses hon drwy gynrychioli'r cyfuniad ar ffurf coeden, fel y dangosir yn Ffigur 1.1. Cynrychiolir pob cyfuniad gan nod â changhennau sy'n cyfateb i weithredydd ac operandau'r cyfuniad yn deillio ohono. Mae'r nodau terfyn (hynny yw, nodau heb ganghennau'n deillio ohonynt) yn cynrychioli naill ai gweithredyddion neu rifau. Wrth edrych ar werthuso yn nhermau'r goeden, gallwn ddychmygu bod gwerthoedd yr operandau yn hidlo i fyny, gan ddechrau o'r nodau terfyn ac yna gyfuno ar lefelau uwch ac uwch. Yn gyffredinol, gwelwn fod dychweliad yn dechneg rymus iawn ar gyfer ymdrin â gwrthrychau hierarchaidd tebyg i goed. Yn wir, mae ffurf “hidlo gwerthoedd i fyny” y rheol werthuso yn enghraifft o fath cyffredinol o broses a elwir yn gronni mewn coeden.

SICP Figure 1.1 15 26 24 2 390 7 5 3 6 4 + * * +

Ffigur 1.1: Cynrychioliad coeden, yn dangos gwerth pob isgyfuniad.

Nesaf, sylwch fod cymhwyso'r cam cyntaf dro ar ôl tro yn dod â ni i'r pwynt lle mae angen inni werthuso mynegiadau cyntefig, megis rhifolion, gweithredyddion cynhenid, neu enwau eraill, yn hytrach na chyfuniadau. Ymdriniwn â'r achosion cyntefig drwy bennu bod

  • gwerthoedd rhifolion yn rhifau y maent yn eu henwi,
  • gwerthoedd gweithredyddion cynhenid yn ddilyniannau cyfarwyddiadau peiriant sy'n cyflawni'r gweithrediadau cyfatebol, a
  • gwerthoedd enwau eraill yn wrthrychau sy'n gysylltiedig â'r enwau hynny yn yr amgylchedd.

Gallwn ystyried yr ail reol yn achos arbennig o'r drydedd drwy bennu bod symbolau megis + a * hefyd wedi'u cynnwys yn yr amgylchedd byd-eang, ac wedi'u cysylltu â'r dilyniannau cyfarwyddiadau peiriant sy'n “werthoedd” iddynt. Y pwynt allweddol i sylwi arno yw rôl yr amgylchedd wrth bennu ystyr y symbolau mewn mynegiadau. Mewn iaith ryngweithiol megis Lisp, nid oes ystyr mewn siarad am werth mynegiad megis (+ x 1) heb bennu unrhyw wybodaeth am yr amgylchedd a fyddai'n rhoi ystyr i'r symbol x (neu hyd yn oed i'r symbol +). Fel y gwelwn ym Mhennod 3, bydd y syniad cyffredinol o'r amgylchedd fel rhywbeth sy'n darparu cyd-destun lle mae gwerthuso'n digwydd yn chwarae rhan bwysig yn ein dealltwriaeth o weithredu rhaglenni.

Sylwch nad yw'r rheol werthuso a roddir uchod yn trin diffiniadau. Er enghraifft, nid yw gwerthuso (define x 3) yn cymhwyso define i ddau arg, un ohonynt yn werth y symbol x a'r llall yn 3, gan mai union ddiben y define yw cysylltu x â gwerth. (Hynny yw, nid cyfuniad yw (define x 3).)

Gelwir eithriadau o'r fath i'r rheol werthuso gyffredinol yn ffurfiau arbennig. Define yw'r unig enghraifft o ffurf arbennig yr ydym wedi'i gweld hyd yma, ond byddwn yn cwrdd ag eraill yn fuan. Mae gan bob ffurf arbennig ei rheol werthuso ei hun. Mae'r gwahanol fathau o fynegiadau (pob un â'i reol werthuso gysylltiedig) yn ffurfio cystrawen yr iaith raglennu. O'i gymharu â'r rhan fwyaf o ieithoedd rhaglennu eraill, mae gan Lisp gystrawen syml iawn; hynny yw, gellir disgrifio'r rheol werthuso ar gyfer mynegiadau drwy reol gyffredinol syml ynghyd â rheolau arbenigol ar gyfer nifer fach o ffurfiau arbennig.11

1.1.4Gweithdrefnau Cyfansawdd

Rydym wedi nodi yn Lisp rai o'r elfennau y mae'n rhaid iddynt ymddangos mewn unrhyw iaith raglennu rymus:

  • Data a gweithdrefnau cyntefig yw rhifau a gweithrediadau rhifyddol.
  • Mae nythu cyfuniadau yn darparu modd o gyfuno gweithrediadau.
  • Mae diffiniadau sy'n cysylltu enwau â gwerthoedd yn darparu modd cyfyngedig o haniaethu.

Nawr byddwn yn dysgu am ddiffiniadau gweithdrefnau, techneg haniaethu lawer mwy grymus sy'n caniatáu rhoi enw i weithrediad cyfansawdd ac yna gyfeirio ato fel uned.

Dechreuwn drwy archwilio sut i fynegi'r syniad o “sgwario”. Gallem ddweud, “I sgwario rhywbeth, lluoswch ef ag ef ei hun.” Mynegir hyn yn ein hiaith fel

(define (square x) (* x x))

Gallwn ddeall hyn yn y ffordd ganlynol:

(define (square x)    (*       x       x))

I sgwario rhywbeth, lluoswch ef ag ef ei hun.

Mae gennym yma weithdrefn gyfansawdd, a roddwyd yr enw square arni. Mae'r weithdrefn yn cynrychioli'r gweithrediad o luosi rhywbeth ag ef ei hun. Rhoddir enw lleol, x, i'r peth sydd i'w luosi, ac mae hwn yn chwarae'r un rôl ag y mae rhagenw'n ei chwarae mewn iaith naturiol. Mae gwerthuso'r diffiniad yn creu'r weithdrefn gyfansawdd hon ac yn ei chysylltu â'r enw square.12

Ffurf gyffredinol diffiniad gweithdrefn yw

(define (⟨name⟩ ⟨formal parameters⟩) ⟨body⟩)

Mae'r ⟨name⟩ yn symbol i'w gysylltu â diffiniad y weithdrefn yn yr amgylchedd.13 Yr ⟨formal parameters⟩ yw'r enwau a ddefnyddir yng nghorff y weithdrefn i gyfeirio at argiau cyfatebol y weithdrefn. Mae'r ⟨body⟩ yn fynegiad a fydd yn rhoi gwerth cymhwyso'r weithdrefn pan roddir yr argiau gwirioneddol y cymhwysir y weithdrefn iddynt yn lle'r paramedrau ffurfiol.14 Mae'r ⟨name⟩ a'r ⟨formal parameters⟩ wedi'u grwpio mewn cromfachau, yn union fel y byddent mewn galwad wirioneddol i'r weithdrefn sy'n cael ei diffinio.

Ar ôl diffinio square, gallwn nawr ei defnyddio:

(square 21)
441

(square (+ 2 5))
49

(square (square 3))
81

Gallwn hefyd ddefnyddio square fel bloc adeiladu wrth ddiffinio gweithdrefnau eraill. Er enghraifft, gellir mynegi x 2 + y 2 fel

(+ (square x) (square y))

Gallwn ddiffinio'n rhwydd weithdrefn sum-of-squares sydd, o gael unrhyw ddau rif yn argiau, yn cynhyrchu swm eu sgwariau:

(define (sum-of-squares x y)
  (+ (square x) (square y)))

(sum-of-squares 3 4)
25

Nawr gallwn ddefnyddio sum-of-squares fel bloc adeiladu wrth lunio rhagor o weithdrefnau:

(define (f a)
  (sum-of-squares (+ a 1) (* a 2)))

(f 5)
136

Defnyddir gweithdrefnau cyfansawdd yn union yr un ffordd â gweithdrefnau cyntefig. Yn wir, ni ellid dweud drwy edrych ar y diffiniad o sum-of-squares a roddir uchod a oedd square wedi'i hadeiladu i mewn i'r dehonglydd, fel + a *, neu wedi'i diffinio fel gweithdrefn gyfansawdd.

1.1.5Y Model Amnewid ar gyfer Cymhwyso Gweithdrefnau

I werthuso cyfuniad y mae ei weithredydd yn enwi gweithdrefn gyfansawdd, mae'r dehonglydd yn dilyn proses debyg iawn i'r un ar gyfer cyfuniadau y mae eu gweithredyddion yn enwi gweithdrefnau cyntefig, a ddisgrifiwyd gennym yn 1.1.3. Hynny yw, mae'r dehonglydd yn gwerthuso elfennau'r cyfuniad ac yn cymhwyso'r weithdrefn (sef gwerth gweithredydd y cyfuniad) i'r argiau (sef gwerthoedd operandau'r cyfuniad).

Gallwn dybio bod y mecanwaith ar gyfer cymhwyso gweithdrefnau cyntefig i argiau wedi'i adeiladu i mewn i'r dehonglydd. Ar gyfer gweithdrefnau cyfansawdd, mae'r broses gymhwyso fel a ganlyn:

I gymhwyso gweithdrefn gyfansawdd i argiau, gwerthuswch gorff y weithdrefn gan roi'r arg cyfatebol yn lle pob paramedr ffurfiol.

I ddangos y broses hon, gadewch inni werthuso'r cyfuniad

(f 5)

lle mai f yw'r weithdrefn a ddiffiniwyd yn 1.1.4. Dechreuwn drwy adalw corff f:

(sum-of-squares (+ a 1) (* a 2))

Yna rhoddwn yr arg 5 yn lle'r paramedr ffurfiol a:

(sum-of-squares (+ 5 1) (* 5 2))

Felly lleihëir y broblem i werthuso cyfuniad â dau operand a gweithredydd sum-of-squares. Mae gwerthuso'r cyfuniad hwn yn cynnwys tair isbroblem. Rhaid inni werthuso'r gweithredydd i gael y weithdrefn sydd i'w chymhwyso, a rhaid inni werthuso'r operandau i gael yr argiau. Nawr mae (+ 5 1) yn cynhyrchu 6 ac mae (* 5 2) yn cynhyrchu 10, felly rhaid inni gymhwyso'r weithdrefn sum-of-squares i 6 a 10. Rhoddir y gwerthoedd hyn yn lle'r paramedrau ffurfiol x ac y yng nghorff sum-of-squares, gan leihau'r mynegiad i

(+ (square 6) (square 10))

Os defnyddiwn y diffiniad o square, mae hyn yn lleihau i

(+ (* 6 6) (* 10 10))

sy'n lleihau drwy luosi i

(+ 36 100)

ac yn olaf i

136

Gelwir y broses yr ydym newydd ei disgrifio yn fodel amnewid ar gyfer cymhwyso gweithdrefnau. Gellir ei chymryd yn fodel sy'n pennu “ystyr” cymhwyso gweithdrefnau, o ran y gweithdrefnau yn y bennod hon. Fodd bynnag, dylid pwysleisio dau bwynt:

  • Diben yr amnewid yw ein helpu i feddwl am gymhwyso gweithdrefnau, nid darparu disgrifiad o sut mae'r dehonglydd yn gweithio mewn gwirionedd. Nid yw dehonglwyr nodweddiadol yn gwerthuso cymwysiadau gweithdrefnau drwy drin testun gweithdrefn i roi gwerthoedd yn lle'r paramedrau ffurfiol. Yn ymarferol, cyflawnir yr “amnewid” drwy ddefnyddio amgylchedd lleol ar gyfer y paramedrau ffurfiol. Trafodwn hyn yn llawnach ym Mhennod 3 a Phennod 4 pan archwiliwn weithrediad dehonglydd yn fanwl.
  • Yn ystod y llyfr hwn, cyflwynwn ddilyniant o fodelau cynyddol fanwl o sut mae dehonglwyr yn gweithio, gan gyrraedd uchafbwynt â gweithrediad cyflawn o ddehonglydd a chrynhoydd ym Mhennod 5. Y model amnewid yw'r cyntaf o'r modelau hyn yn unig—ffordd o ddechrau meddwl yn ffurfiol am y broses werthuso. Yn gyffredinol, wrth fodelu ffenomenau mewn gwyddoniaeth a pheirianneg, dechreuwn â modelau syml, anghyflawn. Wrth inni archwilio pethau'n fwy manwl, daw'r modelau syml hyn yn annigonol a rhaid eu disodli â modelau mwy soffistigedig. Nid yw'r model amnewid yn eithriad. Yn benodol, pan ymdriniwn ym Mhennod 3 â defnyddio gweithdrefnau â “data newidiadwy”, gwelwn fod y model amnewid yn methu a bod yn rhaid ei ddisodli â model mwy cymhleth o gymhwyso gweithdrefnau.15

Trefn gymhwysol a threfn arferol

Yn ôl y disgrifiad o werthuso a roddir yn 1.1.3, mae'r dehonglydd yn gwerthuso'r gweithredydd a'r operandau yn gyntaf ac yna'n cymhwyso'r weithdrefn a geir i'r argiau a geir. Nid dyma'r unig ffordd o gyflawni gwerthuso. Ni fyddai model gwerthuso arall yn gwerthuso'r operandau nes bod angen eu gwerthoedd. Yn lle hynny byddai'n rhoi mynegiadau operand yn lle paramedrau yn gyntaf nes iddo gael mynegiad sy'n cynnwys gweithredyddion cyntefig yn unig, ac yna'n cyflawni'r gwerthuso. Pe defnyddiem y dull hwn, byddai gwerthuso (f 5) yn mynd rhagddo yn ôl y dilyniant o ehangiadau

(sum-of-squares (+ 5 1) (* 5 2))

(+ (square (+ 5 1)) 
   (square (* 5 2)))

(+ (* (+ 5 1) (+ 5 1)) 
   (* (* 5 2) (* 5 2)))

ac yna'r lleihadau

(+ (* 6 6) 
   (* 10 10))

(+ 36 100)

136

Mae hyn yn rhoi'r un ateb â'n model gwerthuso blaenorol, ond mae'r broses yn wahanol. Yn benodol, cyflawnir gwerthusiadau (+ 5 1) ac (* 5 2) ddwywaith yr un yma, sy'n cyfateb i leihau'r mynegiad (* x x) gan roi (+ 5 1) ac (* 5 2) yn eu tro yn lle x.

Gelwir y dull gwerthuso amgen hwn, “ehangu'n llawn ac yna lleihau”, yn werthuso yn y drefn arferol, yn wahanol i'r dull “gwerthuso'r argiau ac yna cymhwyso” y mae'r dehonglydd yn ei ddefnyddio mewn gwirionedd, a elwir yn werthuso yn y drefn gymhwysol. Gellir dangos, ar gyfer cymwysiadau gweithdrefnau y gellir eu modelu drwy ddefnyddio amnewid (gan gynnwys pob gweithdrefn yn nwy bennod gyntaf y llyfr hwn) ac sy'n rhoi gwerthoedd dilys, fod gwerthuso yn y drefn arferol a gwerthuso yn y drefn gymhwysol yn cynhyrchu'r un gwerth. (Gweler Ymarfer 1.5 am enghraifft o werth “annilys” lle nad yw gwerthuso yn y drefn arferol a gwerthuso yn y drefn gymhwysol yn rhoi'r un canlyniad.)

Mae Lisp yn defnyddio gwerthuso yn y drefn gymhwysol, yn rhannol oherwydd yr effeithlonrwydd ychwanegol a geir drwy osgoi gwerthuso mynegiadau droeon, fel y dangosir ag (+ 5 1) ac (* 5 2) uchod, ac, yn fwy arwyddocaol, oherwydd bod gwerthuso yn y drefn arferol yn mynd yn llawer mwy cymhleth i'w drin pan adawn fyd y gweithdrefnau y gellir eu modelu drwy amnewid. Ar y llaw arall, gall gwerthuso yn y drefn arferol fod yn offeryn hynod werthfawr, a byddwn yn ymchwilio i rai o'i oblygiadau ym Mhennod 3 a Phennod 4.16

1.1.6Mynegiadau Amodol a Thraethiadau

Mae grym mynegiannol y dosbarth o weithdrefnau y gallwn eu diffinio ar y pwynt hwn yn gyfyngedig iawn, oherwydd nad oes gennym ffordd o wneud profion a chyflawni gweithrediadau gwahanol yn dibynnu ar ganlyniad prawf. Er enghraifft, ni allwn ddiffinio gweithdrefn sy'n cyfrifo gwerth absoliwt rhif drwy brofi a yw'r rhif yn bositif, yn negatif, neu'n sero a chymryd camau gwahanol yn y gwahanol achosion yn ôl y rheol | x | = { x os yw x > 0 , 0 os yw x = 0 , − x os yw x < 0. Gelwir y lluniad hwn yn ddadansoddiad achosion, ac mae ffurf arbennig yn Lisp ar gyfer nodi dadansoddiad achosion o'r fath. Fe'i gelwir yn cond (sy'n sefyll am “conditional”, sef “amodol”), ac fe'i defnyddir fel a ganlyn:

(define (abs x)
  (cond ((> x 0) x)
        ((= x 0) 0)
        ((< x 0) (- x))))

Ffurf gyffredinol mynegiad amodol yw

(cond (⟨p₁⟩ ⟨e₁⟩)
      (⟨p₂⟩ ⟨e₂⟩)
      …
      (⟨pₙ⟩ ⟨eₙ⟩))

sy'n cynnwys y symbol cond ac yna barau o fynegiadau mewn cromfachau

(⟨p⟩ ⟨e⟩)

a elwir yn gymalau. Mae'r mynegiad cyntaf ym mhob pâr yn draethiad—hynny yw, mynegiad y dehonglir ei werth naill ai'n wir neu'n anwir.17

Gwerthusir mynegiadau amodol fel a ganlyn. Gwerthusir y traethiad ⟨ p 1 ⟩ yn gyntaf. Os yw ei werth yn anwir, yna gwerthusir ⟨ p 2 ⟩ . Os yw gwerth ⟨ p 2 ⟩ hefyd yn anwir, yna gwerthusir ⟨ p 3 ⟩ . Mae'r broses hon yn parhau nes canfod traethiad y mae ei werth yn wir, ac yn yr achos hwnnw mae'r dehonglydd yn dychwelyd gwerth mynegiad canlyniadol cyfatebol ⟨ e ⟩ y cymal fel gwerth y mynegiad amodol. Os na chanfyddir bod unrhyw un o'r ⟨ p ⟩ yn wir, mae gwerth y cond heb ei ddiffinio.

Defnyddir y gair traethiad ar gyfer gweithdrefnau sy'n dychwelyd gwir neu anwir, yn ogystal ag ar gyfer mynegiadau sy'n gwerthuso i wir neu anwir. Mae'r weithdrefn gwerth absoliwt abs yn defnyddio'r traethiadau cyntefig >, <, ac =.18 Mae'r rhain yn cymryd dau rif yn argiau ac yn profi a yw'r rhif cyntaf, yn eu trefn, yn fwy na'r ail rif, yn llai nag ef, neu'n hafal iddo, gan ddychwelyd gwir neu anwir yn unol â hynny.

Ffordd arall o ysgrifennu'r weithdrefn gwerth absoliwt yw

(define (abs x)
  (cond ((< x 0) (- x))
        (else x)))

y gellid ei fynegi yn Saesneg fel “Os yw x yn llai na sero dychwelwch − x ; fel arall dychwelwch x .” Mae Else yn symbol arbennig y gellir ei ddefnyddio yn lle'r ⟨ p ⟩ yng nghymal olaf cond. Mae hyn yn peri i'r cond ddychwelyd, fel ei werth, werth yr ⟨ e ⟩ cyfatebol pryd bynnag y mae pob cymal blaenorol wedi'i hepgor. Yn wir, gellid defnyddio unrhyw fynegiad sydd bob amser yn gwerthuso i werth gwir fel yr ⟨ p ⟩ yma.

Dyma ffordd arall eto o ysgrifennu'r weithdrefn gwerth absoliwt:

(define (abs x)
  (if (< x 0)
      (- x)
      x))

Mae hon yn defnyddio'r ffurf arbennig if, math cyfyngedig o amod y gellir ei ddefnyddio pan fo union ddau achos yn y dadansoddiad achosion. Ffurf gyffredinol mynegiad if yw

(if ⟨predicate⟩ ⟨consequent⟩ ⟨alternative⟩)

I werthuso mynegiad if, mae'r dehonglydd yn dechrau drwy werthuso rhan ⟨predicate⟩ y mynegiad. Os yw'r ⟨predicate⟩ yn gwerthuso i werth gwir, mae'r dehonglydd wedyn yn gwerthuso'r ⟨consequent⟩ ac yn dychwelyd ei werth. Fel arall mae'n gwerthuso'r ⟨alternative⟩ ac yn dychwelyd ei werth.19

Yn ogystal â thraethiadau cyntefig megis <, =, ac >, ceir gweithrediadau cyfansoddi rhesymegol, sy'n ein galluogi i lunio traethiadau cyfansawdd. Y tri a ddefnyddir amlaf yw'r rhain:

  • (and ⟨e₁⟩ … ⟨eₙ⟩)

    Mae'r dehonglydd yn gwerthuso'r mynegiadau ⟨e⟩ un ar y tro, yn nhrefn o'r chwith i'r dde. Os yw unrhyw ⟨e⟩ yn gwerthuso i anwir, mae gwerth y mynegiad and yn anwir, ac ni werthusir gweddill yr ⟨e⟩. Os yw pob ⟨e⟩ yn gwerthuso i werthoedd gwir, gwerth y mynegiad and yw gwerth yr un olaf.

  • (or ⟨e₁⟩ … ⟨eₙ⟩)

    Mae'r dehonglydd yn gwerthuso'r mynegiadau ⟨e⟩ un ar y tro, yn nhrefn o'r chwith i'r dde. Os yw unrhyw ⟨e⟩ yn gwerthuso i werth gwir, dychwelir y gwerth hwnnw fel gwerth y mynegiad or, ac ni werthusir gweddill yr ⟨e⟩. Os yw pob ⟨e⟩ yn gwerthuso i anwir, mae gwerth y mynegiad or yn anwir.

  • (not ⟨e⟩)

    Mae gwerth mynegiad not yn wir pan fo'r mynegiad ⟨e⟩ yn gwerthuso i anwir, ac yn anwir fel arall.

Sylwch mai ffurfiau arbennig yw and ac or, nid gweithdrefnau, oherwydd nad yw'r holl isfynegiadau o reidrwydd yn cael eu gwerthuso. Mae Not yn weithdrefn arferol.

Fel enghraifft o sut y defnyddir y rhain, gellir mynegi'r amod bod rhif x yn yr amrediad 5 < x < 10 fel

(and (> x 5) (< x 10))

Fel enghraifft arall, gallwn ddiffinio traethiad i brofi a yw un rhif yn fwy na neu'n hafal i un arall fel

(define (>= x y) 
  (or (> x y) (= x y)))

neu fel arall fel

(define (>= x y) 
  (not (< x y)))

Ymarfer 1.1: Isod ceir dilyniant o fynegiadau. Beth yw'r canlyniad a argreffir gan y dehonglydd mewn ymateb i bob mynegiad? Tybiwch fod y dilyniant i'w werthuso yn y drefn y'i cyflwynir.

10
(+ 5 3 4)
(- 9 1)
(/ 6 2)
(+ (* 2 4) (- 4 6))
(define a 3)
(define b (+ a 1))
(+ a b (* a b))
(= a b)
(if (and (> b a) (< b (* a b)))
    b
    a)
(cond ((= a 4) 6)
      ((= b 4) (+ 6 7 a))
      (else 25))
(+ 2 (if (> b a) b a))
(* (cond ((> a b) a)
         ((< a b) b)
         (else -1))
   (+ a 1))

Ymarfer 1.2: Troswch y mynegiad canlynol i ffurf ragddodiadol: 5 + 4 + ( 2 − ( 3 − ( 6 + 4 5 ) ) ) 3 ( 6 − 2 ) ( 2 − 7 ) .

Ymarfer 1.3: Diffiniwch weithdrefn sy'n cymryd tri rhif yn argiau ac yn dychwelyd swm sgwariau'r ddau rif mwyaf.

Ymarfer 1.4: Sylwch fod ein model gwerthuso yn caniatáu cyfuniadau y mae eu gweithredyddion yn fynegiadau cyfansawdd. Defnyddiwch y sylw hwn i ddisgrifio ymddygiad y weithdrefn ganlynol:

(define (a-plus-abs-b a b)
  ((if (> b 0) + -) a b))

Ymarfer 1.5: Mae Ben Bitdiddle wedi dyfeisio prawf i bennu a yw'r dehonglydd sydd o'i flaen yn defnyddio gwerthuso yn y drefn gymhwysol neu werthuso yn y drefn arferol. Mae'n diffinio'r ddwy weithdrefn ganlynol:

(define (p) (p))

(define (test x y) 
  (if (= x 0) 
      0 
      y))

Yna mae'n gwerthuso'r mynegiad

(test 0 (p))

Pa ymddygiad fydd Ben yn ei weld gyda dehonglydd sy'n defnyddio gwerthuso yn y drefn gymhwysol? Pa ymddygiad fydd yn ei weld gyda dehonglydd sy'n defnyddio gwerthuso yn y drefn arferol? Eglurwch eich ateb. (Tybiwch fod rheol gwerthuso'r ffurf arbennig if yr un fath p'un a yw'r dehonglydd yn defnyddio'r drefn arferol neu'r drefn gymhwysol: gwerthusir y mynegiad traethol yn gyntaf, a'r canlyniad sy'n pennu a ddylid gwerthuso'r mynegiad canlynol neu'r mynegiad amgen.)

1.1.7Enghraifft: Gwreiddiau Sgwâr drwy Ddull Newton

Mae gweithdrefnau, fel y'u cyflwynwyd uchod, yn debyg iawn i ffwythiannau mathemategol cyffredin. Maent yn pennu gwerth a bennir gan un neu ragor o baramedrau. Ond mae gwahaniaeth pwysig rhwng ffwythiannau mathemategol a gweithdrefnau cyfrifiadurol. Rhaid i weithdrefnau fod yn weithredadwy.

Er enghraifft, ystyriwch y broblem o gyfrifiannu gwreiddiau sgwâr. Gallwn ddiffinio'r ffwythiant gwreiddyn sgwâr fel x = y gwerth y sy'n bodloni y ≥ 0 a y 2 = x . Mae hyn yn disgrifio ffwythiant mathemategol cwbl ddilys. Gallem ei ddefnyddio i adnabod a yw un rhif yn wreiddyn sgwâr rhif arall, neu i ddeillio ffeithiau am wreiddiau sgwâr yn gyffredinol. Ar y llaw arall, nid yw'r diffiniad yn disgrifio gweithdrefn. Yn wir, nid yw bron yn dweud dim wrthym am sut i ganfod gwreiddyn sgwâr rhif penodol mewn gwirionedd. Ni fydd ailfynegi'r diffiniad hwn mewn ffug-Lisp yn helpu:

(define (sqrt x)
  (the y (and (>= y 0) 
              (= (square y) x))))

Nid yw hyn ond yn cymryd yr hyn y mae angen ei esbonio yn ganiataol.

Mae'r cyferbyniad rhwng ffwythiant a gweithdrefn yn adlewyrchu'r gwahaniaeth cyffredinol rhwng disgrifio priodweddau pethau a disgrifio sut i wneud pethau, neu, fel y'i gelwir weithiau, y gwahaniaeth rhwng gwybodaeth ddatganiadol a gwybodaeth orchmynnol. Mewn mathemateg, disgrifiadau datganiadol (beth sydd) sydd fel arfer o ddiddordeb inni, ond mewn cyfrifiadureg disgrifiadau gorchmynnol (sut i wneud) sydd fel arfer o ddiddordeb inni.20

Sut mae cyfrifiannu gwreiddiau sgwâr? Y ffordd fwyaf cyffredin yw defnyddio dull brasamcanion olynol Newton. Mae hwn yn dweud, pryd bynnag y bydd gennym ddyfaliad y ar gyfer gwerth gwreiddyn sgwâr rhif x , y gallwn gyflawni triniaeth syml i gael dyfaliad gwell (un sy'n nes at y gwreiddyn sgwâr gwirioneddol) drwy gymryd cyfartaledd y a x / y .21 Er enghraifft, gallwn gyfrifiannu gwreiddyn sgwâr 2 fel a ganlyn. Tybiwch mai 1 yw ein dyfaliad cychwynnol:

Dyfaliad  Cyniferydd    Cyfartaledd

1         (2/1)  = 2    ((2 + 1)/2)  = 1.5

1.5       (2/1.5)       ((1.3333 + 1.5)/2)
            = 1.3333      = 1.4167

1.4167    (2/1.4167)    ((1.4167 + 1.4118)/2) 
            = 1.4118      = 1.4142  

1.4142    ...           ...

Drwy barhau â'r broses hon, cawn frasamcanion gwell a gwell o'r gwreiddyn sgwâr.

Gadewch inni bellach ffurfioli'r broses yn nhermau gweithdrefnau. Dechreuwn â gwerth ar gyfer y rhif dan y gwreiddyn (y rhif yr ydym yn ceisio cyfrifiannu ei wreiddyn sgwâr) a gwerth ar gyfer y dyfaliad. Os yw'r dyfaliad yn ddigon da at ein dibenion, rydym wedi gorffen; os nad yw, rhaid ailadrodd y broses â dyfaliad gwell. Ysgrifennwn y strategaeth sylfaenol hon fel gweithdrefn:

(define (sqrt-iter guess x)
  (if (good-enough? guess x)
      guess
      (sqrt-iter (improve guess x) x)))

Gwellir dyfaliad drwy gymryd cyfartaledd y dyfaliad a chyniferydd y rhif dan y gwreiddyn a'r hen ddyfaliad:

(define (improve guess x)
  (average guess (/ x guess)))

lle

(define (average x y) 
  (/ (+ x y) 2))

Rhaid inni hefyd ddweud beth a olygwn wrth “ddigon da.” Bydd y canlynol yn ddigon i ddangos y syniad, ond nid yw'n brawf da iawn mewn gwirionedd. (Gweler Ymarfer 1.7.) Y syniad yw gwella'r ateb nes ei fod yn ddigon agos fel bod ei sgwâr yn wahanol i'r rhif dan y gwreiddyn o lai na goddefiant a bennwyd ymlaen llaw (0.001 yma):22

(define (good-enough? guess x)
  (< (abs (- (square guess) x)) 0.001))

Yn olaf, mae angen ffordd o ddechrau arnom. Er enghraifft, gallwn bob amser ddyfalu mai 1 yw gwreiddyn sgwâr unrhyw rif:23

(define (sqrt x)
  (sqrt-iter 1.0 x))

Os teipiwn y diffiniadau hyn i'r dehonglydd, gallwn ddefnyddio sqrt yn union fel unrhyw weithdrefn arall:

(sqrt 9)
3.00009155413138

(sqrt (+ 100 37))
11.704699917758145

(sqrt (+ (sqrt 2) (sqrt 3)))
1.7739279023207892

(square (sqrt 1000))
1000.000369924366

Mae'r rhaglen sqrt hefyd yn dangos bod yr iaith weithdrefnol syml yr ydym wedi'i chyflwyno hyd yma yn ddigonol i ysgrifennu unrhyw raglen gwbl rifol y gellid ei hysgrifennu mewn, er enghraifft, C neu Pascal. Gall hyn ymddangos yn syndod, gan nad ydym wedi cynnwys yn ein hiaith unrhyw gystrawennau iteru (dolenni) sy'n cyfarwyddo'r cyfrifiadur i wneud rhywbeth dro ar ôl tro. Fodd bynnag, mae Sqrt-iter yn dangos sut y gellir cyflawni iteru heb unrhyw gystrawen arbennig heblaw'r gallu arferol i alw gweithdrefn.24

Ymarfer 1.6: Nid yw Alyssa P. Hacker yn gweld pam mae angen darparu if fel ffurf arbennig. “Pam na allaf ei ddiffinio fel gweithdrefn arferol yn nhermau cond?” mae'n gofyn. Mae Eva Lu Ator, ffrind Alyssa, yn honni y gellir gwneud hyn yn wir, ac mae'n diffinio fersiwn newydd o if:

(define (new-if predicate 
                then-clause 
                else-clause)
  (cond (predicate then-clause)
        (else else-clause)))

Mae Eva yn dangos y rhaglen i Alyssa:

(new-if (= 2 3) 0 5)
5

(new-if (= 1 1) 0 5)
0

Wrth ei bodd, mae Alyssa yn defnyddio new-if i ailysgrifennu'r rhaglen gwreiddyn sgwâr:

(define (sqrt-iter guess x)
  (new-if (good-enough? guess x)
          guess
          (sqrt-iter (improve guess x) x)))

Beth sy'n digwydd pan fydd Alyssa yn ceisio defnyddio hyn i gyfrifiannu gwreiddiau sgwâr? Eglurwch.

Ymarfer 1.7: Ni fydd y prawf good-enough? a ddefnyddir wrth gyfrifiannu gwreiddiau sgwâr yn effeithiol iawn ar gyfer canfod gwreiddiau sgwâr rhifau bach iawn. Hefyd, mewn cyfrifiaduron go iawn, cyflawnir gweithrediadau rhifyddol bron bob amser â thrachywiredd cyfyngedig. Mae hyn yn gwneud ein prawf yn annigonol ar gyfer rhifau mawr iawn. Eglurwch y gosodiadau hyn, gydag enghreifftiau sy'n dangos sut mae'r prawf yn methu ar gyfer rhifau bach a mawr. Strategaeth amgen ar gyfer gweithredu good-enough? yw gwylio sut mae guess yn newid o un iteriad i'r nesaf a stopio pan fydd y newid yn ffracsiwn bach iawn o'r dyfaliad. Dyluniwch weithdrefn gwreiddyn sgwâr sy'n defnyddio prawf terfynu o'r fath. A yw hyn yn gweithio'n well ar gyfer rhifau bach a mawr?

Ymarfer 1.8: Mae dull Newton ar gyfer gwreiddiau ciwb yn seiliedig ar y ffaith, os yw y yn frasamcan o wreiddyn ciwb x , yna rhoddir brasamcan gwell gan y gwerth x / y 2 + 2 y 3 . Defnyddiwch y fformiwla hon i weithredu gweithdrefn gwreiddyn ciwb sy'n cyfateb i'r weithdrefn gwreiddyn sgwâr. (Yn 1.3.4 byddwn yn gweld sut i weithredu dull Newton yn gyffredinol drwy haniaethu'r gweithdrefnau gwreiddyn sgwâr a gwreiddyn ciwb hyn.)

1.1.8Gweithdrefnau fel Haniaethau Blwch Du

Sqrt yw ein henghraifft gyntaf o broses a ddiffinnir gan set o weithdrefnau a ddiffinnir yn nhermau ei gilydd. Sylwch fod diffiniad sqrt-iter yn ddychweliadol; hynny yw, diffinnir y weithdrefn yn nhermau ei hun. Gall y syniad o allu diffinio gweithdrefn yn nhermau ei hun beri pryder; gall ymddangos yn aneglur sut y gallai diffiniad mor “gylchol” wneud synnwyr o gwbl, heb sôn am bennu proses wedi'i diffinio'n dda i gyfrifiadur ei chyflawni. Byddwn yn ymdrin â hyn yn fwy gofalus yn 1.2. Ond yn gyntaf, gadewch inni ystyried rhai pwyntiau pwysig eraill a ddangosir gan yr enghraifft sqrt.

Sylwch fod y broblem o gyfrifiannu gwreiddiau sgwâr yn ymrannu'n naturiol yn nifer o isbroblemau: sut i ddweud a yw dyfaliad yn ddigon da, sut i wella dyfaliad, ac ati. Cyflawnir pob un o'r tasgau hyn gan weithdrefn ar wahân. Gellir ystyried y rhaglen sqrt gyfan yn glwstwr o weithdrefnau (a ddangosir yn Ffigur 1.2) sy'n adlewyrchu dadelfeniad y broblem yn isbroblemau.

square / good-enough \ abs average \ improve / \ sqrt-iter | sqrt

Ffigur 1.2: Dadelfeniad gweithdrefnol y rhaglen sqrt.

Nid rhannu'r rhaglen yn rannau yn unig sy'n rhoi pwysigrwydd i'r strategaeth ddadelfennu hon. Wedi'r cyfan, gallem gymryd unrhyw raglen fawr a'i rhannu'n rannau—y deg llinell gyntaf, y deg llinell nesaf, y deg llinell nesaf, ac ati. Yr hyn sy'n hanfodol yw bod pob gweithdrefn yn cyflawni tasg adnabyddadwy y gellir ei defnyddio fel modiwl wrth ddiffinio gweithdrefnau eraill. Er enghraifft, pan ddiffiniwn y weithdrefn good-enough? yn nhermau square, gallwn ystyried y weithdrefn square yn “flwch du.” Nid ydym bryd hynny'n ymwneud â sut mae'r weithdrefn yn cyfrifiannu ei chanlyniad, ond yn unig â'r ffaith ei bod yn cyfrifiannu'r sgwâr. Gellir cuddio manylion sut y cyfrifiannir y sgwâr, i'w hystyried yn ddiweddarach. Yn wir, o safbwynt y weithdrefn good-enough?, nid gweithdrefn yn union yw square ond haniaeth o weithdrefn, sef haniaeth weithdrefnol. Ar y lefel haniaethu hon, mae unrhyw weithdrefn sy'n cyfrifiannu'r sgwâr yr un mor dda.

Felly, gan ystyried dim ond y gwerthoedd a ddychwelant, dylai'r ddwy weithdrefn ganlynol ar gyfer sgwario rhif fod yn anwahanadwy. Mae pob un yn cymryd arg rhifol ac yn cynhyrchu sgwâr y rhif hwnnw fel ei gwerth.25

(define (square x) (* x x))

(define (square x) 
  (exp (double (log x))))

(define (double x) (+ x x))

Felly dylai diffiniad gweithdrefn allu cuddio manylion. Efallai nad defnyddwyr y weithdrefn sydd wedi'i hysgrifennu, ond eu bod wedi'i chael gan raglennydd arall fel blwch du. Ni ddylai fod angen i ddefnyddiwr wybod sut y gweithredir y weithdrefn er mwyn ei defnyddio.

Enwau lleol

Un o fanylion gweithrediad gweithdrefn na ddylai fod o bwys i ddefnyddiwr y weithdrefn yw dewis y gweithredwr o enwau ar gyfer paramedrau ffurfiol y weithdrefn. Felly, ni ddylai fod modd gwahaniaethu rhwng y gweithdrefnau canlynol:

(define (square x) (* x x))
(define (square y) (* y y))

Mae'r egwyddor hon—y dylai ystyr gweithdrefn fod yn annibynnol ar yr enwau paramedrau a ddefnyddir gan ei hawdur—yn ymddangos yn hunanamlwg ar yr wyneb, ond mae ei chanlyniadau'n ddwys. Y canlyniad symlaf yw bod yn rhaid i enwau paramedrau gweithdrefn fod yn lleol i gorff y weithdrefn. Er enghraifft, defnyddiasom square yn y diffiniad o good-enough? yn ein gweithdrefn gwreiddyn sgwâr:

(define (good-enough? guess x)
  (< (abs (- (square guess) x)) 0.001))

Bwriad awdur good-enough? yw pennu a yw sgwâr yr arg cyntaf o fewn goddefiant penodol i'r ail arg. Gwelwn fod awdur good-enough? wedi defnyddio'r enw guess i gyfeirio at yr arg cyntaf a x i gyfeirio at yr ail arg. Arg square yw guess. Os defnyddiodd awdur square yr enw x (fel uchod) i gyfeirio at yr arg hwnnw, gwelwn fod yn rhaid i'r x yn good-enough? fod yn x gwahanol i'r un yn square. Ni ddylai rhedeg y weithdrefn square effeithio ar werth x a ddefnyddir gan good-enough?, oherwydd gall fod angen y gwerth hwnnw o x ar good-enough? ar ôl i square orffen cyfrifiannu.

Pe na bai'r paramedrau'n lleol i gyrff eu gweithdrefnau priodol, yna gellid cymysgu'r paramedr x yn square â'r paramedr x yn good-enough?, a byddai ymddygiad good-enough? yn dibynnu ar ba fersiwn o square a ddefnyddiem. Felly, ni fyddai square yn flwch du o'r math a ddymunem.

Mae gan baramedr ffurfiol gweithdrefn rôl arbennig iawn yn y diffiniad o'r weithdrefn, gan nad yw enw'r paramedr ffurfiol o bwys. Gelwir enw o'r fath yn newidyn rhwym, a dywedwn fod diffiniad y weithdrefn yn rhwymo ei pharamedrau ffurfiol. Nid yw ystyr diffiniad gweithdrefn yn newid os ailenwir newidyn rhwym yn gyson drwy gydol y diffiniad.26 Os nad yw newidyn yn rhwym, dywedwn ei fod yn rhydd. Gelwir y set o fynegiadau y mae rhwymiad yn diffinio enw ar eu cyfer yn gwmpas yr enw hwnnw. Mewn diffiniad gweithdrefn, cwmpas y newidynnau rhwym a ddatgenir fel paramedrau ffurfiol y weithdrefn yw corff y weithdrefn.

Yn y diffiniad o good-enough? uchod, mae guess a x yn newidynnau rhwym ond mae <, -, abs, a square yn rhydd. Dylai ystyr good-enough? fod yn annibynnol ar yr enwau a ddewiswn ar gyfer guess a x cyhyd â'u bod yn wahanol i'w gilydd ac i <, -, abs, a square. (Pe baem yn ailenwi guess yn abs byddem wedi cyflwyno nam drwy ddal y newidyn abs. Byddai wedi newid o fod yn rhydd i fod yn rhwym.) Fodd bynnag, nid yw ystyr good-enough? yn annibynnol ar enwau ei newidynnau rhydd. Mae'n sicr yn dibynnu ar y ffaith (y tu allan i'r diffiniad hwn) fod y symbol abs yn enwi gweithdrefn ar gyfer cyfrifiannu gwerth absoliwt rhif. Bydd Good-enough? yn cyfrifiannu ffwythiant gwahanol os rhoddwn cos yn lle abs yn ei ddiffiniad.

Diffiniadau mewnol a strwythur blociau

Hyd yma, mae un math o ynysu enwau ar gael inni: mae paramedrau ffurfiol gweithdrefn yn lleol i gorff y weithdrefn. Mae'r rhaglen gwreiddyn sgwâr yn dangos ffordd arall y byddem yn hoffi rheoli defnydd enwau. Mae'r rhaglen bresennol yn cynnwys gweithdrefnau ar wahân:

(define (sqrt x) 
  (sqrt-iter 1.0 x))

(define (sqrt-iter guess x)
  (if (good-enough? guess x)
      guess
      (sqrt-iter (improve guess x) x)))

(define (good-enough? guess x)
  (< (abs (- (square guess) x)) 0.001))

(define (improve guess x)
  (average guess (/ x guess)))

Y broblem gyda'r rhaglen hon yw mai sqrt yw'r unig weithdrefn sy'n bwysig i ddefnyddwyr sqrt. Nid yw'r gweithdrefnau eraill (sqrt-iter, good-enough?, a improve) ond yn annibennu eu meddyliau. Ni allant ddiffinio unrhyw weithdrefn arall o'r enw good-enough? fel rhan o raglen arall i weithio gyda'r rhaglen gwreiddyn sgwâr, oherwydd bod ei hangen ar sqrt. Mae'r broblem yn arbennig o ddifrifol wrth adeiladu systemau mawr gan lawer o raglenwyr ar wahân. Er enghraifft, wrth adeiladu llyfrgell fawr o weithdrefnau rhifol, cyfrifiannir llawer o ffwythiannau rhifol drwy frasamcanion olynol, ac felly gallai fod ganddynt weithdrefnau ategol o'r enwau good-enough? a improve. Hoffem leoleiddio'r isweithdrefnau, gan eu cuddio y tu mewn i sqrt fel y gallai sqrt gydfodoli â brasamcanion olynol eraill, a phob un â'i weithdrefn good-enough? breifat ei hun. Er mwyn gwneud hyn yn bosibl, caniatawn i weithdrefn gynnwys diffiniadau mewnol sy'n lleol i'r weithdrefn honno. Er enghraifft, yn y broblem gwreiddyn sgwâr gallwn ysgrifennu

(define (sqrt x)
  (define (good-enough? guess x)
    (< (abs (- (square guess) x)) 0.001))
  (define (improve guess x)
    (average guess (/ x guess)))
  (define (sqrt-iter guess x)
    (if (good-enough? guess x)
        guess
        (sqrt-iter (improve guess x) x)))
  (sqrt-iter 1.0 x))

Yn y bôn, nythu diffiniadau fel hyn, a elwir yn strwythur blociau, yw'r ateb cywir i'r broblem symlaf o becynnu enwau. Ond mae syniad gwell yn llechu yma. Yn ogystal â mewnoli diffiniadau'r gweithdrefnau ategol, gallwn eu symleiddio. Gan fod x yn rhwym yn y diffiniad o sqrt, mae'r gweithdrefnau good-enough?, improve, a sqrt-iter, a ddiffinnir yn fewnol i sqrt, o fewn cwmpas x. Felly, nid oes angen trosglwyddo x yn benodol i bob un o'r gweithdrefnau hyn. Yn hytrach, caniatawn i x fod yn newidyn rhydd yn y diffiniadau mewnol, fel y dangosir isod. Yna daw gwerth x o'r arg a ddefnyddir i alw'r weithdrefn amgáu sqrt. Gelwir y drefn hon yn gwmpasu geiriadurol.27

(define (sqrt x)
  (define (good-enough? guess)
    (< (abs (- (square guess) x)) 0.001))
  (define (improve guess)
    (average guess (/ x guess)))
  (define (sqrt-iter guess)
    (if (good-enough? guess)
        guess
        (sqrt-iter (improve guess))))
  (sqrt-iter 1.0))

Byddwn yn defnyddio strwythur blociau yn helaeth i'n helpu i rannu rhaglenni mawr yn ddarnau y gellir eu trin.28 Tarddodd y syniad o strwythur blociau yn yr iaith raglennu Algol 60. Mae'n ymddangos yn y rhan fwyaf o ieithoedd rhaglennu datblygedig ac mae'n arf pwysig ar gyfer helpu i drefnu adeiladu rhaglenni mawr.

Troednodiadau

4 Mae disgrifio rhifau fel “data syml” yn dwyll digywilydd. Mewn gwirionedd, ymdrin â rhifau yw un o agweddau mwyaf dyrys a dryslyd unrhyw iaith raglennu. Dyma rai materion nodweddiadol: mae rhai systemau cyfrifiadurol yn gwahaniaethu rhwng cyfanrifau, megis 2, a rhifau real, megis 2.71. A yw'r rhif real 2.00 yn wahanol i'r cyfanrif 2? A yw'r gweithrediadau rhifyddol a ddefnyddir ar gyfanrifau yr un fath â'r gweithrediadau a ddefnyddir ar rifau real? A yw 6 wedi'i rannu â 2 yn cynhyrchu 3, neu 3.0? Pa mor fawr yw'r rhif mwyaf y gallwn ei gynrychioli? Sawl lle degol o gywirdeb y gallwn eu cynrychioli? A yw amrediad y cyfanrifau yr un fath ag amrediad y rhifau real? Y tu hwnt i'r cwestiynau hyn, wrth gwrs, mae casgliad o faterion yn ymwneud â gwallau talgrynnu a thocio—holl wyddoniaeth dadansoddi rhifiadol. Gan ein bod yn canolbwyntio yn y llyfr hwn ar ddylunio rhaglenni ar raddfa fawr yn hytrach nag ar dechnegau rhifiadol, byddwn yn anwybyddu'r problemau hyn. Bydd yr enghreifftiau rhifol yn y bennod hon yn arddangos yr ymddygiad talgrynnu arferol a welir wrth ddefnyddio gweithrediadau rhifyddol sy'n cadw nifer cyfyngedig o leoedd degol o gywirdeb mewn gweithrediadau ar rifau nad ydynt yn gyfanrifau.

5 Drwy gydol y llyfr hwn, pan fyddwn am bwysleisio'r gwahaniaeth rhwng y mewnbwn a deipir gan y defnyddiwr a'r ymateb a argreffir gan y dehonglydd, byddwn yn dangos yr olaf mewn llythrennau ar ogwydd.

6 Fel arfer mae systemau Lisp yn darparu nodweddion i helpu'r defnyddiwr i fformatio mynegiadau. Dwy nodwedd arbennig o ddefnyddiol yw un sy'n mewnoli'n awtomatig i'r safle argraffu taclus priodol pryd bynnag y dechreuir llinell newydd, ac un sy'n amlygu'r gromfach chwith gyfatebol pryd bynnag y teipir cromfach dde.

7 Mae Lisp yn dilyn y confensiwn bod gan bob mynegiad werth. Y confensiwn hwn, ynghyd â hen enw Lisp fel iaith aneffeithlon, yw ffynhonnell sylw ffraeth Alan Perlis (gan aralleirio Oscar Wilde) fod “rhaglenwyr Lisp yn gwybod gwerth popeth ond cost dim.”

8 Yn y llyfr hwn, nid ydym yn dangos ymateb y dehonglydd i werthuso diffiniadau, gan fod hyn yn dibynnu'n helaeth ar y gweithrediad.

9 Bydd Pennod 3 yn dangos bod y syniad hwn o amgylchedd yn hanfodol, ar gyfer deall sut mae'r dehonglydd yn gweithio ac ar gyfer gweithredu dehonglwyr.

10 Gall ymddangos yn rhyfedd fod y rheol gwerthuso yn dweud, fel rhan o'r cam cyntaf, y dylem werthuso elfen bellaf i'r chwith cyfuniad, gan mai dim ond gweithredydd megis + neu *, sy'n cynrychioli gweithdrefn gyntefig adeiledig megis adio neu luosi, y gall hwnnw fod ar hyn o bryd. Byddwn yn gweld yn ddiweddarach fod gallu gweithio â chyfuniadau y mae eu gweithredyddion eu hunain yn fynegiadau cyfansawdd yn ddefnyddiol.

11 Weithiau gelwir ffurfiau cystrawennol arbennig nad ydynt ond yn strwythurau arwynebol amgen cyfleus ar gyfer pethau y gellir eu hysgrifennu mewn ffyrdd mwy unffurf yn siwgr cystrawennol, gan ddefnyddio ymadrodd a fathwyd gan Peter Landin. O'u cymharu â defnyddwyr ieithoedd eraill, mae rhaglenwyr Lisp, fel rheol, yn poeni llai am faterion cystrawen. (Mewn cyferbyniad, archwiliwch unrhyw lawlyfr Pascal a sylwch faint ohono a neilltuir i ddisgrifiadau o gystrawen.) Mae'r dirmyg hwn tuag at gystrawen yn deillio'n rhannol o hyblygrwydd Lisp, sy'n ei gwneud yn hawdd newid cystrawen arwynebol, ac yn rhannol o'r sylw fod llawer o gystrawennau “cyfleus,” sy'n gwneud yr iaith yn llai unffurf, yn achosi mwy o drafferth nag y maent yn werth pan fydd rhaglenni'n mynd yn fawr a chymhleth. Yng ngeiriau Alan Perlis, “Mae siwgr cystrawennol yn achosi canser y hanner colon.”

12 Sylwch fod dau weithrediad gwahanol yn cael eu cyfuno yma: rydym yn creu'r weithdrefn, ac yn rhoi'r enw square iddi. Mae'n bosibl, ac yn wir yn bwysig, gallu gwahanu'r ddau syniad hyn—creu gweithdrefnau heb eu henwi, a rhoi enwau i weithdrefnau sydd eisoes wedi'u creu. Byddwn yn gweld sut i wneud hyn yn 1.3.2.

13 Drwy gydol y llyfr hwn, byddwn yn disgrifio cystrawen gyffredinol mynegiadau drwy ddefnyddio symbolau italig wedi'u hamgáu mewn cromfachau onglog—e.e., ⟨name⟩—i ddynodi'r “bylchau” yn y mynegiad sydd i'w llenwi pan ddefnyddir mynegiad o'r fath mewn gwirionedd.

14 Yn fwy cyffredinol, gall corff y weithdrefn fod yn ddilyniant o fynegiadau. Yn yr achos hwn, mae'r dehonglydd yn gwerthuso pob mynegiad yn y dilyniant yn ei dro ac yn dychwelyd gwerth y mynegiad olaf fel gwerth cymhwyso'r weithdrefn.

15 Er mor syml yw'r syniad o amnewid, mae rhoi diffiniad mathemategol trylwyr o'r broses amnewid yn troi allan yn rhyfeddol o gymhleth. Mae'r broblem yn codi o'r posibilrwydd o ddryswch rhwng yr enwau a ddefnyddir ar gyfer paramedrau ffurfiol gweithdrefn a'r enwau (a all fod yn union yr un fath) a ddefnyddir yn y mynegiadau y gellir cymhwyso'r weithdrefn iddynt. Yn wir, ceir hanes hir o ddiffiniadau gwallus o amnewid yn llenyddiaeth rhesymeg a semanteg rhaglennu. Gweler Stoy 1977 am drafodaeth ofalus o amnewid.

16 Ym Mhennod 3 byddwn yn cyflwyno prosesu ffrydiau, sef ffordd o drin strwythurau data sy'n ymddangos yn “anfeidraidd” drwy gynnwys ffurf gyfyngedig ar werthuso yn y drefn arferol. Yn 4.2 byddwn yn addasu'r dehonglydd Scheme i gynhyrchu amrywiad ar Scheme sy'n defnyddio'r drefn arferol.

17 Dyma ystyr “wedi'i ddehongli naill ai'n wir neu'n anwir”: yn Scheme, ceir dau werth penodol a ddynodir gan y cysonion #t a #f. Pan fydd y dehonglydd yn gwirio gwerth traethiad, mae'n dehongli #f yn anwir. Trinnir unrhyw werth arall yn wir. (Felly, nid oes angen darparu #t o safbwynt rhesymeg, ond mae'n gyfleus.) Yn y llyfr hwn byddwn yn defnyddio'r enwau true a false, sy'n gysylltiedig â'r gwerthoedd #t a #f yn y drefn honno.

18 Mae Abs hefyd yn defnyddio'r gweithredydd “minws” -, sydd, o'i ddefnyddio gydag un operand yn unig, fel yn (- x), yn dynodi negatifio.

19 Gwahaniaeth bach rhwng if a cond yw y gall rhan ⟨e⟩ pob cymal cond fod yn ddilyniant o fynegiadau. Os canfyddir bod y ⟨p⟩ cyfatebol yn wir, gwerthusir y mynegiadau ⟨e⟩ yn eu trefn a dychwelir gwerth y mynegiad olaf yn y dilyniant fel gwerth y cond. Mewn mynegiad if, fodd bynnag, rhaid i ⟨consequent⟩ a ⟨alternative⟩ fod yn fynegiadau unigol.

20 Mae cysylltiad agos rhwng disgrifiadau datganiadol a gorchmynnol, fel sydd yn wir rhwng mathemateg a chyfrifiadureg. Er enghraifft, mae dweud bod yr ateb a gynhyrchir gan raglen yn “gywir” yn gwneud gosodiad datganiadol am y rhaglen. Mae llawer iawn o ymchwil yn ceisio sefydlu technegau ar gyfer profi bod rhaglenni'n gywir, ac mae llawer o anhawster technegol y pwnc hwn yn ymwneud â phontio rhwng gosodiadau gorchmynnol (y mae rhaglenni'n cael eu hadeiladu ohonynt) a gosodiadau datganiadol (y gellir eu defnyddio i ddiddwytho pethau). Yn gysylltiedig â hyn, maes pwysig ar hyn o bryd mewn dylunio ieithoedd rhaglennu yw archwilio'r hyn a elwir yn ieithoedd lefel uchel iawn, lle bydd rhywun yn rhaglennu mewn gwirionedd yn nhermau gosodiadau datganiadol. Y syniad yw gwneud dehonglwyr yn ddigon soffistigedig fel y gallant, o gael gwybodaeth “beth sydd” a bennir gan y rhaglennydd, gynhyrchu gwybodaeth “sut i wneud” yn awtomatig. Ni ellir gwneud hyn yn gyffredinol, ond mae meysydd pwysig lle gwnaed cynnydd. Byddwn yn dychwelyd at y syniad hwn ym Mhennod 4.

21 Mewn gwirionedd, mae'r algorithm gwreiddyn sgwâr hwn yn achos arbennig o ddull Newton, sef techneg gyffredinol ar gyfer canfod gwreiddiau hafaliadau. Datblygwyd yr algorithm gwreiddyn sgwâr ei hun gan Heron o Alexandria yn y ganrif gyntaf O.C. Byddwn yn gweld sut i fynegi dull cyffredinol Newton fel gweithdrefn Lisp yn 1.3.4.

22 Fel arfer byddwn yn rhoi enwau sy'n gorffen â marciau cwestiwn i draethiadau, i'n helpu i gofio eu bod yn draethiadau. Confensiwn arddull yn unig yw hwn. O safbwynt y dehonglydd, nod cyffredin yn unig yw'r marc cwestiwn.

23 Sylwch ein bod yn mynegi ein dyfaliad cychwynnol fel 1.0 yn hytrach nag 1. Ni fyddai hyn yn gwneud unrhyw wahaniaeth mewn llawer o weithrediadau Lisp. Fodd bynnag, mae Scheme MIT yn gwahaniaethu rhwng cyfanrifau union a gwerthoedd degol, ac mae rhannu dau gyfanrif yn cynhyrchu rhif cymarebol yn hytrach na degolyn. Er enghraifft, mae rhannu 10 â 6 yn rhoi 5/3, ond mae rhannu 10.0 â 6.0 yn rhoi 1.6666666666666667. (Byddwn yn dysgu sut i weithredu rhifyddeg ar rifau cymarebol yn 2.1.1.) Os dechreuwn â dyfaliad cychwynnol o 1 yn ein rhaglen gwreiddyn sgwâr, ac os yw x yn gyfanrif union, rhifau cymarebol yn hytrach na degolion fydd yr holl werthoedd dilynol a gynhyrchir wrth gyfrifiannu'r gwreiddyn sgwâr. Mae gweithrediadau cymysg ar rifau cymarebol a degolion bob amser yn rhoi degolion, felly mae dechrau â dyfaliad cychwynnol o 1.0 yn gorfodi'r holl werthoedd dilynol i fod yn ddegolion.

24 Dylai darllenwyr sy'n poeni am y materion effeithlonrwydd sy'n gysylltiedig â defnyddio galwadau gweithdrefn i weithredu iteru sylwi ar y sylwadau am “ddychweliad cynffon” yn 1.2.1.

25 Nid yw hyd yn oed yn glir pa un o'r gweithdrefnau hyn sy'n weithrediad mwy effeithlon. Mae hyn yn dibynnu ar y caledwedd sydd ar gael. Ceir peiriannau lle mai'r gweithrediad “amlwg” yw'r un lleiaf effeithlon. Ystyriwch beiriant sydd â thablau helaeth o logarithmau a gwrthlogarithmau wedi'u storio mewn ffordd effeithlon iawn.

26 Mewn gwirionedd, mae'r cysyniad o ailenwi cyson yn gynnil ac yn anodd ei ddiffinio'n ffurfiol. Mae rhesymegwyr enwog wedi gwneud camgymeriadau chwithig yma.

27 Mae cwmpasu geiriadurol yn mynnu bod newidynnau rhydd mewn gweithdrefn yn cael eu cymryd i gyfeirio at rwymiadau a wneir gan ddiffiniadau gweithdrefn amgáu; hynny yw, chwilir amdanynt yn yr amgylchedd lle diffiniwyd y weithdrefn. Byddwn yn gweld yn fanwl sut mae hyn yn gweithio ym mhennod 3 wrth astudio amgylcheddau ac ymddygiad manwl y dehonglydd.

28 Rhaid i ddiffiniadau sydd wedi'u mewnosod ddod yn gyntaf yng nghorff gweithdrefn. Nid yw'r rheolwyr yn gyfrifol am ganlyniadau rhedeg rhaglenni sy'n cydblethu diffinio a defnyddio.