#+TITLE: Structure and Interpretation of Computer Programs #+AUTHOR: Lio Novelli * Foreword and Preface #+begin_quote Lisp je preživeli, v uporabi je že "polovico stoletja". #+end_quote #+begin_quote The discretionary exportable functionality entrusted to the individual Lisp programmer is more than an order of magniture greater than that to be found within Pascal enterprises. #+end_quote #+begin_quote Želimo vzpostaviti idejo, da programski jezik ni samo način, da računalnik izvaja operacije, ampak da je predvsem nov formalni medij za izražanje idej o metodologiji. Zato morajo biti programi napisani predvsem zato, da jih ljudje berejo, in slučajno, da jih izvajajo računalniki. Bistvena tema ni sintaksa določenih struktur v programskem jeziku, niti ..., temveč tehnike nadzora intelektualne kompleksnosti veliki programskih sistemov. #+end_quote #+begin_quote Naš pristop k temi izvira iz prepričanja, da "computer science" ni znanost in da ima njen pomen bolj malo opraviti z računalniki. Računalniška revolucija je revolucija v načinu mišljenja in izražanju idej. Bistvo teh sprememb najbolše opiše pojem _proceduralne epistemologije_, ki se ukvarja s strukturo vednosti z imperativnega stališča za razliko od klasične matematike, ki je bolj deklerativna. Matematika postavi okvir za natančno spoprijemanje s pojmovanjem "kaj je". Računanje pa ponudi okvir za natančno ukvarjanje s pojmovanjem "kako". #+end_quote * 1. Grajenje abstrakcij s procedurami ** Elementi programiranja - Primitivni izrazi :: predstavtljajo najpreprostejše gradnike (entitete) programskega jezika - Načini kombinacije, :: s katerimi so sestavljeni elementi zgrajeni iz preprostejših - Načini abstrakcije, :: s katerimi so lahko sestavljeni elementi poimenovani in omogočajo upravljanje z njimii kot enotami ** Izvajanje kombinacij(e) Postopek za izvajanje kombinacij: 1. Izvedi podizraz kombinacije. 2. Uporabi/uveljavi proceduro, ki je najbolje levi podizraz (operator) z argumenti, ki so vrednosti drugih podizrazov (operandi). Postopek evalvacije je rekurziven, saj drugi korak v sebi vključuje prvega, oziroma vključuje svojo definicijo. Tako se zgradi akumulacijsko drevo. Na koncu vedno prideš do točke, ko izvajaš primitivne izraze, ki so: - vrednosti numeričnih števk, ki jo označujejo. - vrednosti vgrajenih operatorjev so strojni ukazi sekvenc, ki izvedejo te operacije. - vrednosti drugih imen so objekti asociirani s temi imeni v okolju. Drugo pravilo je poseben primer tretjega pravila. Simboli + in * so tudi vključeni v globalno okolje in so asociirani s strojnimi ukazi, ki so njihove vrednosti. *Pomembno je prepoznati vlogo okolja pri določanju pomena simbolov v izrazih.* To pravilo se ne nanaša na _posebne oblike (special forms)_. ~define~ je posebna oblika. ** 1.1.4 Sestavljene procedure - Številke in aritmetične operacije so primitivni podatki in procedure. - Gnezdenje kombinacij omogoča način za združevanje operacij. - Definicije, ki asociirajo imena z vrednostmi omogočajo omejene načine abstrakcije. ~(define (square x) (* x x))~ ~(define square (lambda (x) (* x x)))~ ** 1.1.5 Substitucijski model za izvajanje procedur Za izvajanje sestavljenih procedur z argumenti, izvedeš telo procedure z vsakim formalnim parametrom, ki ga nadomestiš s pripadajočim argumentom. _ergh, tukaj se zapletam s slovenskimi prevodi_ _kaj je application in kaj evaluation?_ Načini, na katere deluje interpreter (prevajalnik): - Aplikativni vrstni red :: Najprej evalviraj operator in operande, potem pa izvedi proizvedeno proceduro s pridobljenimi argumenti. - Normalni vrstni red :: Ne izvajaj operandov dokler njihove vrednost niso potrebne. Najprej zamenjaj izraze operandov s parametri, dokler ne pride do izraza, ki vsebuje zgolj primitivne izraze in potem izvedi (vso) evalvacijo. ** meta Linki: https://develop.spacemacs.org/layers/+lang/scheme/README.html https://www.nongnu.org/geiser/ https://www.gnu.org/software/guile/learn/ https://spritely.institute/static/papers/scheme-primer.html#introduction Kako nastavit spacemacs, in malo o guile-u. *** video lekcije https://yewtu.be/channel/UCEBb1b_L6zDS3xTUrIALZOw (6.001 SICP: Structure and Interpretation of Computer Programs (2004)) https://yewtu.be/playlist?list=PL7BcsI5ueSNFPCEisbaoQ0kXIDX9rR5FF (MIT 6.001 Structure and Interpretation, 1986) ** vaje *** 1.3 **** najprej narobe Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers. #+begin_src scheme (define (sum-of-large x y z) (+ (if (> x y) (* x x) (* y y)) (if (> y z) (* y y) (* z z)) ) ) (sum-of-large 3 8 5) #+end_src #+RESULTS: : 128 #+begin_src scheme (define (sum-of-larger x y z) (let* ((s (lambda (a) (* a a))) (sl (lambda (b c) (if (> b c) (s b) (s c)))) ) (+ (sl x y) (sl y z)) )) (sum-of-larger 3 8 5) #+end_src #+RESULTS: : 128 **** pravilno #+begin_src scheme (define (sum-squares-of-larger x y z) (if (> x y) (if (> y z) (+ (* x x) (* y y)) (+ (* x x) (* z z)) ) (if (> x z) (+ (* y y) (* x x)) (+ (* y y) (* z z)) ) ) ) (sum-squares-of-larger 9 10 8) #+end_src #+RESULTS: : 181 *** 1.5 Aplikativni vrstni red: pade takoj v neskoncno zanko. Normalni vrstni red: izvrsi test in pride v if, ki ne izvrsi drugega dela. *** 1.6 [[file:sqrt-newton.scm][sqrt-newton.scm]] *** 1.7 - ~good-enough?~ ni vredu za iskanje korenov majhnih stevil. - pravtako za zelo velika stevila - napisi alternativno ~good-enough?~ proceduro, ki bo gledala, kdaj so spremembe dovolj majhne in takrat prekini funkcijo. // Poglej v sqrt-newton.scm *** 1.8 // Glej v sqrt-newton.sqm ** 1.1.8 Procedure kot crne skatle abstrakcij - block structure - lexical scoping ** 1.2.2 Drevesna rekurzija ** 1.2.3 Redi rasti ** 1.2.4 Eksponentna funkcija ** 1.2.5 Najvecji skupni deljitel ** 1.2.6 Primer: Iskanje prastevil ** 1.3 Sestavljanje abstrakcij s procedurami visjega reda ** 1.3.1 Procedure kot argumenti //exercise 1.29 #name: simpson #+begin_src scheme (define (sum term a next b) (if (> a b) 0 (+ (term a) (sum term (next a) next b) ) ) ) (define (integral f a b dx) (define (add-dx x) (+ x dx)) (* (sum f (+ a (/ dx 2.0)) add-dx b) dx) ) (define (sum-s term a next b fact) ;; fact is altering between 4 and 2 (define (check-fact fact) (if (= fact 4) 2 4)) (if (> a b) 0 (+ (* fact (term a)) (sum-s term (next a) next b (check-fact fact)) ) ) ) (define (simpson f a b dx) (define (add-dx x) (+ x dx)) (* (+ (f a) (f b) (sum-s f (add-dx a) add-dx (- b dx) 4) ) (/ dx 3.0)) ) (define (simpson-gizmo f a b dx) (define (add-dxdx x) (+ x dx dx)) (* (+ (* 4 (sum f (+ a dx) add-dxdx b)) (* 2 (sum f a add-dxdx b)) (- (f a)) (- (f b)) ) (/ dx 3.0)) ) (define (cube x) (* x x x)) (list (integral cube 1 2 0.01) (integral cube 1 2 0.001) (simpson cube 1 2 0.01) (simpson cube 1 2 0.001) (simpson cube 1 2 (/ 1 1000)) (simpson-gizmo cube 1 2 0.01) (simpson-gizmo cube 1 2 (/ 1 10000)) (simpson-gizmo cube 1 2 0.00001) ) #+end_src #+RESULTS: | 3.7499625000000045 | 3.7499996249995324 | 3.644925346666673 | 3.7499999999995324 | 3.749893334961112 | // exercise 1.30 #+begin_src scheme (define (sum-i term a next b) (define (iter a result) (if (> a b) result (iter (next a) (+ result (term a))) ) ) (iter a 0) ) #+end_src ** 1.3.2 Sestavljanje procedur z Lambda ** 1.3.3 Procedure kot splosne metode ** 1.3.4 Procedure kot vrnjene vrednosti