learning-sicp

My embarrassing half assed SICP run.
git clone https://kaka.farm/~git/learning-sicp
Log | Files | Refs

commit 062e23d5d35c65680f37b3e7d6472a5f84093575
parent bab5b89784fa0b2d7c5f3f9cc53b9aa6d7a7ba35
Author: Yuval Langer <yuval.langer@gmail.com>
Date:   Mon, 22 Jul 2024 15:19:50 +0300

Add solution to exercise 4.3. .  Also, save olde solutions.

Diffstat:
Asicp/solutions/chapter-4/exercise-3.scm | 564+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asicp/solutions/chapter-4/old/exercise-3.scm | 134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asicp/solutions/chapter-4/old/exercise-4.scm | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asicp/solutions/chapter-4/old/exercise-5.scm | 42++++++++++++++++++++++++++++++++++++++++++
Asicp/solutions/chapter-4/old/exercise-6.scm | 37+++++++++++++++++++++++++++++++++++++
Asicp/solutions/chapter-4/old/exercise-7.scm | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asicp/solutions/chapter-4/old/exercise-8.scm | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asicp/solutions/chapter-4/old/exercise-9.scm | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asicp/tests/chapter-4/exercise-3.scm | 16++++++++++++++++
9 files changed, 1085 insertions(+), 0 deletions(-)

diff --git a/sicp/solutions/chapter-4/exercise-3.scm b/sicp/solutions/chapter-4/exercise-3.scm @@ -0,0 +1,564 @@ +(define-library (sicp solutions chapter-4 exercise-3) + (export + eval + main + + run-internal-tests + + make-environment + setup-environment + extend-environment + ) + (import + (rename (scheme base) (apply scheme:base:apply)) + (scheme cxr) + (scheme read) + (scheme write) + + (srfi srfi-1) + (srfi srfi-9) + (srfi srfi-64) + + (system vm trace) + + (ice-9 match) + (ice-9 pretty-print) + + (sicp utils) + ) + + (begin + ;; XXX: In 4.1.3 we see that the procedure `true?` is defined + ;; using the host-variable `false` whose value is 'false, but we + ;; don't see it defined anywhere in the good book, so we need to + ;; define the host-variable false ourselves. + ;; + ;; In MIT Scheme, the one the SICP people seem to love to use for + ;; SICP, the values of `false` and `true` are #f and #t, #f being + ;; the only value that is falsituous and #t there for having a + ;; truthious value that has no other meaning other than being + ;; truthitiousic. + ;; + ;; ``` + ;; # `scheme` is the MIT Scheme executable: + ;; $ guix shell mit-scheme -- scheme + ;; MIT/GNU Scheme running under GNU/Linux + ;; Type `^C' (control-C) followed by `H' to obtain information about interrupts. + ;; + ;; Copyright (C) 2020 Massachusetts Institute of Technology + ;; This is free software; see the source for copying conditions. There is NO warranty; not even for + ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + ;; + ;; Image saved on Sunday March 7, 2021 at 3:24:56 PM + ;; Release 11.2 || SF || LIAR/x86-64 + ;; + ;; 1 ]=> false + ;; + ;; ;Value: #f + ;; + ;; 1 ]=> true + ;; + ;; ;Value: #t + ;; + ;; 1 ]=> + ;; ``` + (define false #f) + (define true #t) + + (define (make-environment vars vals) + "A comfort procedure because calling extend on the-empty-environment is a PITA." + (extend-environment vars + vals + the-empty-environment)) + + ;; XXX: As described in chapter 4.1.4 note 2, we need to name the + ;; host `apply`, and the guest `apply` differently. I define the + ;; host's `apply` to be the name used in the book. + (define apply-in-underlying-scheme scheme:base:apply) + +;;; Start: + +;;; 4.1.1 + + (define *form-table* '()) + + (define (add-form-handler! form? handler) + (set! *form-table* + (cons (cons form? + handler) + *form-table*))) + + (define (get-form-handler exp) + (let loop ((table *form-table*)) + (match table + ('() + (error "Unknown form" exp)) + (`((,form? . ,handler) . ,rest) + (if (form? exp) + handler + (loop rest)))))) + + (define (eval exp env) + (cond ((self-evaluating? exp) + exp) + ((variable? exp) + (lookup-variable-value exp env)) + ((pair? exp) + ((get-form-handler exp) exp env)) + (else + (error "Unknown expression type -- EVAL" exp)))) + + (define (apply procedure arguments) + (cond ((primitive-procedure? procedure) + (apply-primitive-procedure + procedure + arguments)) + ((compound-procedure? procedure) + (eval-sequence + (procedure-body procedure) + (extend-environment + (procedure-parameters + procedure) + arguments + (procedure-environment + procedure)))) + (else + (error "Unknown procedure type -- APPLY" + procedure)))) + +;;; Procedure arguments: + + (define (list-of-values exps env) + (if (no-operands? exps) + '() + (cons (eval (first-operand exps) env) + (list-of-values (rest-operands exps) env)))) + +;;; Conditionals: + + (define (eval-if exp env) + (if (true? (eval (if-predicate exp) env)) + (eval (if-consequent exp) env) + (eval (if-alternative exp) env))) + +;;; Sequences: + + (define (eval-sequence exps env) + (cond ((last-exp? exps) + (eval (first-exp exps) env)) + (else + (eval (first-exp exps) env) + (eval-sequence (rest-exps exps) + env)))) + +;;; Assignments and definitions + + (define (eval-assignment exp env) + (set-variable-value! + (assignment-variable exp) + (eval (assignment-value exp) env) + env) + 'ok) + + (define (eval-definition exp env) + (define-variable! + (definition-variable exp) + (eval (definition-value exp) env) + env) + 'ok) + +;;; end 4.1.1 + +;;; 4.1.2 + + + (define (self-evaluating? exp) + (cond ((number? exp) true) + ((string? exp) true) + (else false))) + + (define (variable? exp) (symbol? exp)) + + (define (quoted? exp) + (tagged-list? exp 'quote)) + + (define (text-of-quotation exp) + (cadr exp)) + + (define (tagged-list? exp tag) + (if (pair? exp) + (eq? (car exp) tag) + false)) + + (define (assignment? exp) + (tagged-list? exp 'set!)) + + (define (assignment-variable exp) + (cadr exp)) + + (define (assignment-value exp) (caddr exp)) + + (define (definition? exp) + (tagged-list? exp 'define)) + + (define (definition-variable exp) + (if (symbol? (cadr exp)) + (cadr exp) + (caadr exp))) + + (define (definition-value exp) + (if (symbol? (cadr exp)) + (caddr exp) + (make-lambda + (cdadr exp) ; formal-parameters + (cddr exp)))) ; body + + (define (lambda? exp) + (tagged-list? exp 'lambda)) + (define (lambda-parameters exp) (cadr exp)) + (define (lambda-body exp) (cddr exp)) + + (define (make-lambda parameters body) + (cons 'lambda (cons parameters body))) + + (define (if? exp) (tagged-list? exp 'if)) + (define (if-predicate exp) (cadr exp)) + (define (if-consequent exp) (caddr exp)) + (define (if-alternative exp) + (if (not (null? (cdddr exp))) + (cadddr exp) + 'false)) + + (define (make-if predicate + consequent + alternative) + (list 'if + predicate + consequent + alternative)) + + (define (begin? exp) + (tagged-list? exp 'begin)) + (define (begin-actions exp) (cdr exp)) + (define (last-exp? seq) (null? (cdr seq))) + (define (first-exp seq) (car seq)) + (define (rest-exps seq) (cdr seq)) + + (define (sequence->exp seq) + (cond ((null? seq) seq) + ((last-exp? seq) (first-exp seq)) + (else (make-begin seq)))) + + (define (make-begin seq) (cons 'begin seq)) + + (define (application? exp) (pair? exp)) + (define (operator exp) (car exp)) + (define (operands exp) (cdr exp)) + (define (no-operands? ops) (null? ops)) + (define (first-operand ops) (car ops)) + (define (rest-operands ops) (cdr ops)) + + (define (cond? exp) + (tagged-list? exp 'cond)) + (define (cond-clauses exp) (cdr exp)) + (define (cond-else-clause? clause) + (eq? (cond-predicate clause) 'else)) + (define (cond-predicate clause) + (car clause)) + (define (cond-actions clause) + (cdr clause)) + (define (cond->if exp) + (expand-clauses (cond-clauses exp))) + (define (expand-clauses clauses) + (if (null? clauses) + 'false + (let ((first (car clauses)) + (rest (cdr clauses))) + (if (cond-else-clause? first) + (if (null? rest) + (sequence->exp + (cond-actions first)) + (error "ELSE clause isn't last: COND->IF" + clauses)) + (make-if (cond-predicate first) + (sequence->exp + (cond-actions first)) + (expand-clauses + rest)))))) + +;;; end 4.1.2 + +;;; 4.1.3 + + ;; XXX: By default, false's value is #f, which is the only true + ;; false. All others are fake and would have the truthitousness + ;; property. Consult `info r7rs-small` or `C-h + (define (true? x) + (not (eq? x false))) + + (define (false? x) + (eq? x false)) + + (define (make-procedure parameters body env) + (list 'procedure parameters body env)) + (define (compound-procedure? p) + (tagged-list? p 'procedure)) + (define (procedure-parameters p) (cadr p)) + (define (procedure-body p) (caddr p)) + (define (procedure-environment p) (cadddr p)) + + (define (enclosing-environment env) (cdr env)) + (define (first-frame env) (car env)) + (define the-empty-environment '()) + + (define (make-frame variables values) + (cons variables values)) + (define (frame-variables frame) (car frame)) + (define (frame-values frame) (cdr frame)) + (define (add-binding-to-frame! var val frame) + (set-car! frame (cons var (car frame))) + (set-cdr! frame (cons val (cdr frame)))) + + (define (extend-environment vars vals base-env) + (if (= (length vars) (length vals)) + (cons (make-frame vars vals) base-env) + (if (< (length vars) (length vals)) + (error "Too many arguments supplied" + vars + vals) + (error "Too few arguments supplied" + vars + vals)))) + + (define (lookup-variable-value var env) + (define (env-loop env) + (define (scan vars vals) + (cond ((null? vars) + (env-loop + (enclosing-environment env))) + ((eq? var (car vars)) + (car vals)) + (else (scan (cdr vars) + (cdr vals))))) + (if (eq? env the-empty-environment) + (error "Unbound variable" var) + (let ((frame (first-frame env))) + (scan (frame-variables frame) + (frame-values frame))))) + (env-loop env)) + + (define (set-variable-value! var val env) + ;; XXX: Just trying to see what it would look like if I just used named lets. + ;; + ;; (let loop-over-environments ((env env)) + ;; (cond + ;; ((eq? env the-empty-enviornment) + ;; (error "Unbound variable: SET!" var)) + ;; (else + ;; (let ((frame (first-frame env))) + ;; (let loop-over-frame ((vars (frame-variables frame)) + ;; (vals (frame-values frame))) + ;; (cond + ;; ((null? vars) + ;; (loop-over-environments (enclosing-environment env))) + ;; ((eq? var (car vars)) + ;; (set-car! vals val)) + ;; (else + ;; (loop-over-frame ((cdr vars) + ;; (cdr vals)))))))))) + + (define (env-loop env) + (define (scan vars vals) + (cond ((null? vars) + (env-loop + (enclosing-environment env))) + ((eq? var (car vars)) + (set-car! vals val)) + (else (scan (cdr vars) + (cdr vals))))) + (if (eq? env the-empty-environment) + (error "Unbound variable: SET!" var) + (let ((frame (first-frame env))) + (scan (frame-variables frame) + (frame-values frame))))) + (env-loop env)) + + (define (define-variable! var val env) + "Add a new variable VAR with value VAL in the top frame of environment ENV. + +If variable VAR already exists in the top frame, set VAR in the top +frame to VAL." + + ;; We will CHANGE (why did I all uppercase "CHANGE" here? I + ;; don't remember. Maybe it is some sort of a joke?) only + ;; the first frame. + (let ((frame (first-frame env))) + (define (scan vars vals) + (cond ((null? vars) + (add-binding-to-frame! + var val frame)) + ((eq? var (car vars)) + (set-car! vals val)) + (else (scan (cdr vars) + (cdr vals))))) + (scan (frame-variables frame) + (frame-values frame)))) + +;;; 4.1.4 + + (define (setup-environment) + (dpp 'moo) + (let* (;; XXX: See bug below on the quoted (define + ;; primitive-procedures ...) + (primitive-procedures + (list (list 'car car) + (list 'cdr cdr) + (list 'cons cons) + (list 'null? null?) + (list '+ +) + (list '- -) + (list '* *) + (list '/ /) + (list '= =) + (list 'display display) + (list 'write write) + (list 'read read))) + (initial-env + (extend-environment + (primitive-procedure-names primitive-procedures) + (primitive-procedure-objects primitive-procedures) + the-empty-environment))) + (define-variable! 'true true initial-env) + (define-variable! 'false false initial-env) + initial-env)) + + (define the-global-environment + (begin + (dpp 'moo) + (setup-environment))) + + (define (primitive-procedure? proc) + (tagged-list? proc 'primitive)) + + (define (primitive-implementation proc) + (cadr proc)) + + ;; XXX: There is a bug here in SICP or GNU Guile or both. + ;; primitive-procedures is `#<unspecified>` when this library is + ;; being loaded. + '(define primitive-procedures + (list (list 'car car) + (list 'cdr cdr) + (list 'cons cons) + (list 'null? null?) + (list '+ +) + (list '- -) + (list '* *) + (list '/ /) + (list 'display display) + (list 'write write) + (list 'read read))) + + (define (primitive-procedure-names primitive-procedures) + (map car + primitive-procedures)) + + (define (primitive-procedure-objects primitive-procedures) + (map (lambda (proc) + (list 'primitive (cadr proc))) + primitive-procedures)) + + (define (apply-primitive-procedure proc args) + (apply-in-underlying-scheme + (primitive-implementation proc) args)) + + (define input-prompt ";;; M-Eval input:") + (define output-prompt ";;; M-Eval value:") + + (define (driver-loop) + (prompt-for-input input-prompt) + (let ((input (read))) + (let ((output + (eval input + the-global-environment))) + (announce-output output-prompt) + (user-print output))) + (driver-loop)) + + (define (prompt-for-input string) + (newline) (newline) + (display string) (newline)) + + (define (announce-output string) + (newline) (display string) (newline)) + + (define (user-print object) + (if (compound-procedure? object) + (display + (list 'compound-procedure + (procedure-parameters object) + (procedure-body object) + '<procedure-env>)) + (display object))) + + ;; XXX: Already defined above: + ;; (define the-global-environment + ;; (setup-environment)) + + (define (main args) + (match args + ('() + (error "Arguments should have something rather than nothing.")) + (`(,arg0) + (display arg0) + (newline)) + (`(,arg0 "--debug") + (display "DEBUG TURN ON!\n") + (set! *debug* #t)) + (args (error "Unknown arguments:" args))) + + (driver-loop)) + + (define (run-internal-tests) + (test-eq 1 + (lookup-variable-value 'a + (extend-environment '(a +) + `(1 ,+) + the-empty-environment))) + (test-eq 1 + (lookup-variable-value 'a + (extend-environment '(+ a) + `(,+ 1) + the-empty-environment))) + (test-eq + + (lookup-variable-value '+ + (extend-environment '(a +) + `(1 ,+) + the-empty-environment)))) + + (add-form-handler! quoted? (lambda (exp env) (text-of-quotation exp))) + (add-form-handler! assignment? eval-assignment) + (add-form-handler! definition? eval-definition) + + (add-form-handler! if? eval-if) + (add-form-handler! lambda? + (lambda (exp env) + (make-procedure (lambda-parameters exp) + (lambda-body exp) + env))) + (add-form-handler! begin? + (lambda (exp env) + (eval-sequence + (begin-actions exp) + env))) + (add-form-handler! cond? + (lambda (exp env) + (eval (cond->if exp) env))) + (add-form-handler! application? + (lambda (exp env) + (apply (eval (operator exp) env) + (list-of-values + (operands exp) + env)))) + + )) diff --git a/sicp/solutions/chapter-4/old/exercise-3.scm b/sicp/solutions/chapter-4/old/exercise-3.scm @@ -0,0 +1,134 @@ +(define-library (sicp chapter-4 exercise-3) + (import + (scheme base) + (scheme process-context) + (scheme write) + + (srfi :1) + (srfi :64) + + (ice-9 format) + (ice-9 match) + (ice-9 pretty-print) + + (sicp utils)) + + (begin + (define *forms-table* '()) + + '((define-record-type <compound-procedure> + (make-compound-procedure parameters body env) + compound-procedure? + (parameters compound-procedure-parameters) + (body compound-procedure-body) + (env compound-procedure-env)) + + (define (put-form form-type form-handler) + (set! *forms-table* + (alist-cons form-type + form-handler + (alist-delete form-type *forms-table*)))) + + (define (get-form form-type) + (match (assoc form-type *forms-table*) + (`(,form-type . ,form-handler) + form-handler) + (_ #f))) + + (define (get-variable variable-name env) + (match (assoc variable-name env) + (`(,variable-name . ,variable-value) + variable-value) + (_ (error "Unknown variable:" variable-name)))) + + (define (form-symbol exp) (car exp)) + + (define host-eval eval) + + (define (eval exp env) + (pretty-print (list 'eval exp)) + (match exp + ((? self-evaluating?) exp) + ((? variable?) (lookup-variable-value exp env)) + (_ + (match (get-form (form-symbol exp)) + ((our-form-symbol . our-form-handler) + (our-form-handler + (form-parameters exp) + env)) + (_ + (match exp + ((? application? exp) + (apply (eval (operator exp) env) + (list-of-values (operands exp) env))) + (_ + (pretty-print (list "uknown express -- EVAL" exp)) + (error "Unknown expression type -- EVAL" exp)))))))) + + (define (form-parameters exp) (cdr exp)) + + (define (operator exp) (car exp)) + (define (operands exp) (cdr exp)) + + (define (application? exp) (pair? exp)) + + (define (apply-in-underlying-scheme proc arguments) + (apply proc arguments)) + + (define (apply procedure arguments) + (cond ((primitive-procedure? procedure) + (apply-primitive-procedure procedure arguments)) + ((compound-procedure? procedure) + (eval-sequence + (procedure-body procedure) + (extend-environment + (procedure-parameters procedure) + arguments + (procedure-environment procedure)))) + (else + (pretty-print (list "Unknown procedure type -- APPLY" procedure)) + (error + "Unknown procedure type -- APPLY" procedure)))) + + (define (primitive-implementation proc) (cadr proc)) + + (define (apply-primitive-procedure procedure arguments) + (apply-in-underlying-scheme + (primitive-implementation proc) + arguments)) + + (define (primitive-procedure? procedure) (symbol? procedure)) + + (define (list-of-values exps env) + (if (no-operands? exps) + '() + (cons (eval (first-operand exps) + env) + (list-of-values (rest-operands exps) + env)))) + (define (first-operand exps) (car exps)) + (define (rest-operands exps) (cdr exps)) + (define (no-operands? exp) (null? (cdr exp))) + + (define (println-handler exp env) + (display exp) (newline) + (values '() env)) + + (define (self-evaluating? exp) + (or (string? exp) + (number? exp) + (null? exp) + (vector? exp) + (symbol? exp))) + + (define (variable? exp) (symbol? exp)) + + (define (quote-handler exp env) (cadr exp)) + + (put-form 'quote quote-handler) + ((get-form 'quote) '(quote 1) '()) + + (eval (quote 1) '()) + (eval (list 'quote 1) '()) + (eval '(quote a) `()) + ))) diff --git a/sicp/solutions/chapter-4/old/exercise-4.scm b/sicp/solutions/chapter-4/old/exercise-4.scm @@ -0,0 +1,75 @@ +(define-library (sicp solutions chapter-4 exercise-4) + (import (schemb base) + (ice-9 match)) + + (begin + (define (eval exp env) + (cond ((self-evaluating? exp) exp) + ((variable? exp) (lookup-variable-value exp env)) + ((quoted? exp) (text-of-quotation exp)) + ((assignment? exp) (eval-assignment exp env)) + ((definition? exp) (eval-definition exp env)) + ((if? exp) (eval-if exp env)) + ((lambda? exp) + (make-procedure (lambda-parameters exp) + (lambda-body exp) + env)) + ((begin? exp) + (eval-sequence (begin-actions exp) env)) + ((cond? exp) (eval (cond->if exp) env)) + ((and? exp) (eval-and (cdr exp) env)) + ((or? exp) (eval-or (cdr exp) env)) + ((application? exp) + (apply (eval (operator exp) env) + (list-of-values (operands exp) env))) + (else + (error "Unknown expression type -- EVAL" exp)))) + + (define (and? exp) (tagged-list? exp 'and)) + (define (or? exp) (tagged-list? exp 'or)) + + (define (eval-and exp env) + (match exp + ((and) + 'true) + ((and ,head ,rest ...) + (let ((head-value (eval rest env))) + (if (eqv? head-value 'true) + head-value + (eval-and rest env)))))) + + (define (eval-or exp env) + (match exp + ((or) + 'false) + ((or ,head ,rest ...) + (let ((head-value (eval rest env))) + (if (eqv? head-value 'true) + (eval-or rest env) + 'false))))) + + (define (eval-and-2 exp env) + (eval + `(if (null? ,exp) + 'true + ((lambda (car-value) + (if (true? car-value) + (if (null? ,(cdr exp)) + car-value + (and ,(cdr exp))) + 'false)) + ,(car exp))) + env)) + + (define (eval-or-2 exp env) + (eval + `(if (null? ,exp) + 'false + ((lambda (car-value) + (if (true? car-value) + car-value + (if (null? ,(cdr exp)) + 'false + (or ,(cdr exp))))) + ,(car exp))) + env)))) diff --git a/sicp/solutions/chapter-4/old/exercise-5.scm b/sicp/solutions/chapter-4/old/exercise-5.scm @@ -0,0 +1,42 @@ +(define-library (sicp solutions chapter-4 exercise-5) + (import (schemb base) + (ice-9 match)) + + (begin + (define (eval exp env) + (cond ((self-evaluating? exp) exp) + ((variable? exp) (lookup-variable-value exp env)) + ((quoted? exp) (text-of-quotation exp)) + ((assignment? exp) (eval-assignment exp env)) + ((definition? exp) (eval-definition exp env)) + ((if? exp) (eval-if exp env)) + ((lambda? exp) + (make-procedure (lambda-parameters exp) + (lambda-body exp) + env)) + ((begin? exp) + (eval-sequence (begin-actions exp) env)) + ((cond? exp) (eval (cond->if exp) env)) + ((application? exp) + (apply (eval (operator exp) env) + (list-of-values (operands exp) env))) + (else + (error "Unknown expression type -- EVAL" exp)))) + + (define (cond->if exp) + (let expand-clauses ((clauses (cdr exp))) + (match clauses + ((cond) 'false) + (`((else ,actions)) (sequence->exp actions)) + (`((else ,actions) ,rest ...) + (error "ELSE clause isn't last -- COND->IF" + clauses)) + (`((,predicate ,actions) ,rest ...) + (make-if predicate + (sequence->exp actions) + (expand-clauses '()))) + (`((,predicate => ,recipient) ,rest ...) + (let ((predicate-value (eval predicate))) + (make-if predicate-value + (recipient predicate-value) + rest)))))))) diff --git a/sicp/solutions/chapter-4/old/exercise-6.scm b/sicp/solutions/chapter-4/old/exercise-6.scm @@ -0,0 +1,37 @@ +(define-library (sicp solutions chapter-4 exercise-6) + (import (scheme base) + (ice-9 match)) + + (begin + (define (eval exp env) + (cond ((self-evaluating? exp) exp) + ((variable? exp) (lookup-variable-value exp env)) + ((quoted? exp) (text-of-quotation exp)) + ((assignment? exp) (eval-assignment exp env)) + ((definition? exp) (eval-definition exp env)) + ((if? exp) (eval-if exp env)) + ((lambda? exp) + (make-procedure (lambda-parameters exp) + (lambda-body exp) + env)) + ((begin? exp) + (eval-sequence (begin-actions exp) env)) + ((cond? exp) (eval (cond->if exp) env)) + ((let? exp) (eval (let->combination exp) env)) + ((application? exp) + (apply (eval (operator exp) env) + (list-of-values (operands exp) env))) + (else + (error "Unknown expression type -- EVAL" exp)))) + + (define (let? exp) (eqv? (car exp) 'let)) + + (define (let->combination exp) + (match exp + (`(let ,variables ,first-code-expression . ,rest-of-code-expressions) + (let ((variable-names (map car variables)) + (variable-expressions (map cadr variables))) + `((lambda ,variable-names + ,first-code-expression + ,@rest-of-code-expressions) + ,@variable-expressions))))))) diff --git a/sicp/solutions/chapter-4/old/exercise-7.scm b/sicp/solutions/chapter-4/old/exercise-7.scm @@ -0,0 +1,73 @@ +(define-library (sicp solutions chapter-4 exercise-7) + (import (scheme base) + (ice-9 match)) + + (begin + (define (eval exp env) + (cond ((self-evaluating? exp) exp) + ((variable? exp) (lookup-variable-value exp env)) + ((quoted? exp) (text-of-quotation exp)) + ((assignment? exp) (eval-assignment exp env)) + ((definition? exp) (eval-definition exp env)) + ((if? exp) (eval-if exp env)) + ((lambda? exp) + (make-procedure (lambda-parameters exp) + (lambda-body exp) + env)) + ((begin? exp) + (eval-sequence (begin-actions exp) env)) + ((cond? exp) (eval (cond->if exp) env)) + ((let? exp) (eval (let->combination exp) env)) + ((let*? exp) (eval (let*->nested-lets exp) env)) + ((application? exp) + (apply (eval (operator exp) env) + (list-of-values (operands exp) env))) + (else + (error "Unknown expression type -- EVAL" exp)))) + + (define (let*? exp) (eqv? (car exp) 'let*)) + + (let*->combination '(let* () a b c)) + (let*->combination '(let* ((a (b)) (c (d))) 1)) + + (define (let*->combination exp) + (match exp + (`(let* () ,first-code-expression . ,rest-of-code-expressions) + `(begin ,first-code-expression + ,@rest-of-code-expressions)) + (`(let* ((,variable-name ,variable-expression)) + ,first-code-expression . ,rest-of-code-expressions) + `((lambda (,variable-name) + ,first-code-expression + ,@rest-of-code-expressions) + ,variable-expression)) + (`(let* ((,variable-name ,variable-expression) . ,rest-of-variables) + ,first-code-expression . ,rest-of-code-expressions) + (let ((inner + (let*->combination `(let* ,rest-of-variables + ,first-code-expression + ,@rest-of-code-expressions)))) + `((lambda (,variable-name) + ,inner) + ,variable-expression))))) + + (let*->nested-lets '(let* () a b c)) + (let*->nested-lets '(let* ((a (b)) (c (d))) 1 2 3)) + + (define (let*->nested-lets exp) + (match exp + (`(let* () ,first-code-expression . ,rest-of-code-expressions) + `(begin ,first-code-expression + ,@rest-of-code-expressions)) + (`(let* ((,variable-name ,variable-expression)) + ,first-code-expression . ,rest-of-code-expressions) + `(let ((,variable-name ,variable-expression)) + ,first-code-expression + ,@rest-of-code-expressions)) + (`(let* ((,variable-name ,variable-expression) . ,rest-of-variables) + ,first-code-expression . ,rest-of-code-expressions) + `(let ((,variable-name ,variable-expression)) + ,(let*->nested-lets + `(let* ,rest-of-variables + ,first-code-expression + ,@rest-of-code-expressions)))))))) diff --git a/sicp/solutions/chapter-4/old/exercise-8.scm b/sicp/solutions/chapter-4/old/exercise-8.scm @@ -0,0 +1,72 @@ +(define-library (sicp solutions chapter-4 exercise-8) + (import (scheme base) + (ice-9 match)) + + (begin + (define (eval exp env) + (cond ((self-evaluating? exp) exp) + ((variable? exp) (lookup-variable-value exp env)) + ((quoted? exp) (text-of-quotation exp)) + ((assignment? exp) (eval-assignment exp env)) + ((definition? exp) (eval-definition exp env)) + ((if? exp) (eval-if exp env)) + ((lambda? exp) + (make-procedure (lambda-parameters exp) + (lambda-body exp) + env)) + ((begin? exp) + (eval-sequence (begin-actions exp) env)) + ((cond? exp) (eval (cond->if exp) env)) + ((let*? exp) (eval (let*->combination exp) env)) + ((application? exp) + (apply (eval (operator exp) env) + (list-of-values (operands exp) env))) + (else + (error "Unknown expression type -- EVAL" exp)))) + + (define (let*? exp) (eqv? (car exp) 'let*)) + + (let*->combination '(let* () a b c)) + (let*->combination '(let* ((a (b)) (c (d))) 1)) + + (define (let*->combination exp) + (match exp + (`(let* () ,first-code-expression . ,rest-of-code-expressions) + `(begin ,first-code-expression + ,@rest-of-code-expressions)) + (`(let* ((,variable-name ,variable-expression)) + ,first-code-expression . ,rest-of-code-expressions) + `((lambda (,variable-name) + ,first-code-expression + ,@rest-of-code-expressions) + ,variable-expression)) + (`(let* ((,variable-name ,variable-expression) . ,rest-of-variables) + ,first-code-expression . ,rest-of-code-expressions) + (let ((inner + (let*->combination `(let* ,rest-of-variables + ,first-code-expression + ,@rest-of-code-expressions)))) + `((lambda (,variable-name) + ,inner) + ,variable-expression))))) + + (let*->nested-lets '(let* () a b c)) + (let*->nested-lets '(let* ((a (b)) (c (d))) 1 2 3)) + + (define (let*->nested-lets exp) + (match exp + (`(let* () ,first-code-expression . ,rest-of-code-expressions) + `(begin ,first-code-expression + ,@rest-of-code-expressions)) + (`(let* ((,variable-name ,variable-expression)) + ,first-code-expression . ,rest-of-code-expressions) + `(let ((,variable-name ,variable-expression)) + ,first-code-expression + ,@rest-of-code-expressions)) + (`(let* ((,variable-name ,variable-expression) . ,rest-of-variables) + ,first-code-expression . ,rest-of-code-expressions) + `(let ((,variable-name ,variable-expression)) + ,(let*->nested-lets + `(let* ,rest-of-variables + ,first-code-expression + ,@rest-of-code-expressions)))))))) diff --git a/sicp/solutions/chapter-4/old/exercise-9.scm b/sicp/solutions/chapter-4/old/exercise-9.scm @@ -0,0 +1,72 @@ +(define-library (sicp solutions chapter-4 exercise-9) + (import (scheme base) + (ice-9 match)) + + (begin + (define (eval exp env) + (cond ((self-evaluating? exp) exp) + ((variable? exp) (lookup-variable-value exp env)) + ((quoted? exp) (text-of-quotation exp)) + ((assignment? exp) (eval-assignment exp env)) + ((definition? exp) (eval-definition exp env)) + ((if? exp) (eval-if exp env)) + ((lambda? exp) + (make-procedure (lambda-parameters exp) + (lambda-body exp) + env)) + ((begin? exp) + (eval-sequence (begin-actions exp) env)) + ((cond? exp) (eval (cond->if exp) env)) + ((let*? exp) (eval (let*->combination exp) env)) + ((application? exp) + (apply (eval (operator exp) env) + (list-of-values (operands exp) env))) + (else + (error "Unknown expression type -- EVAL" exp)))) + + (define (let*? exp) (eqv? (car exp) 'let*)) + + (let*->combination '(let* () a b c)) + (let*->combination '(let* ((a (b)) (c (d))) 1)) + + (define (let*->combination exp) + (match exp + (`(let* () ,first-code-expression . ,rest-of-code-expressions) + `(begin ,first-code-expression + ,@rest-of-code-expressions)) + (`(let* ((,variable-name ,variable-expression)) + ,first-code-expression . ,rest-of-code-expressions) + `((lambda (,variable-name) + ,first-code-expression + ,@rest-of-code-expressions) + ,variable-expression)) + (`(let* ((,variable-name ,variable-expression) . ,rest-of-variables) + ,first-code-expression . ,rest-of-code-expressions) + (let ((inner + (let*->combination `(let* ,rest-of-variables + ,first-code-expression + ,@rest-of-code-expressions)))) + `((lambda (,variable-name) + ,inner) + ,variable-expression))))) + + (let*->nested-lets '(let* () a b c)) + (let*->nested-lets '(let* ((a (b)) (c (d))) 1 2 3)) + + (define (let*->nested-lets exp) + (match exp + (`(let* () ,first-code-expression . ,rest-of-code-expressions) + `(begin ,first-code-expression + ,@rest-of-code-expressions)) + (`(let* ((,variable-name ,variable-expression)) + ,first-code-expression . ,rest-of-code-expressions) + `(let ((,variable-name ,variable-expression)) + ,first-code-expression + ,@rest-of-code-expressions)) + (`(let* ((,variable-name ,variable-expression) . ,rest-of-variables) + ,first-code-expression . ,rest-of-code-expressions) + `(let ((,variable-name ,variable-expression)) + ,(let*->nested-lets + `(let* ,rest-of-variables + ,first-code-expression + ,@rest-of-code-expressions)))))))) diff --git a/sicp/tests/chapter-4/exercise-3.scm b/sicp/tests/chapter-4/exercise-3.scm @@ -0,0 +1,16 @@ +(define-library (sicp tests chapter-4 exercise-3) + (import (scheme base) + + (srfi :64) + + (sicp solutions chapter-4 exercise-3)) + + (begin + (test-begin "chapter-4-exercise-3") + + (test-equal -1 + (eval '(+ -2 1) + (make-environment '(+) + `((primitive ,+))))) + + (test-end "chapter-4-exercise-3")))