From 4a5b13324f78ec64b73c0f32036484cfedd0a830 Mon Sep 17 00:00:00 2001 From: Geir Okkenhaug Jerstad Date: Tue, 20 Aug 2024 19:10:43 +0200 Subject: [PATCH 1/3] a little scheme --- little_schemer/the-little-schemer.rkt | 1247 +++++++++++++++++++++++++ little_schemer/tls.ss | 11 + yast/hello.scm | 11 + 3 files changed, 1269 insertions(+) create mode 100644 little_schemer/the-little-schemer.rkt create mode 100644 little_schemer/tls.ss diff --git a/little_schemer/the-little-schemer.rkt b/little_schemer/the-little-schemer.rkt new file mode 100644 index 0000000..512e689 --- /dev/null +++ b/little_schemer/the-little-schemer.rkt @@ -0,0 +1,1247 @@ +#lang racket + +;; Used to redefine Racket functions in terms of the original functions +(require (rename-in racket + [cons racket-cons] + [null? racket-null?] + [eq? racket-eq?] + [+ racket+] + [- racket-] + [number? racket-number?])) + +(provide (all-defined-out)) + + +;;********************************************************** +;; Preface +;;********************************************************** + +;; [Primitive] +;; Predicate for determining if a value is an atom or not. +;; The definition of this is found in the preface. +(define (atom? x) + (and (not (pair? x)) (not (racket-null? x)))) +;; Note that we need to use the racket-null? and not our newly contracted null? +;; becuase x may be an atom, which racket-null? supports and null? (as defined +;; in the book and thus our contracted version) does not. + + +;;********************************************************** +;; Chapter 1 +;;********************************************************** + +;; [Primitive] +;; Predicate for determining if a value is an S-expression or not +(define (s-exp? x) + (or (atom? x) (list? x))) + +;; [Primitive] +;; Provide a cons as defined in the book such that it requires a list as +;; the second argument. This is enforced using Racket's contract system. +;; Racket's cons works on any values, as mentioned in the footnote on page 8. +(define/contract (cons s l) + (-> any/c list? list?) + (racket-cons s l)) + +;; [Primitive] +;; Provide a cons as defined in the book such that it requires a list as +;; the argument. See the footnote on page 10. +(define/contract (null? l) + (-> list? boolean?) + (racket-null? l)) + +;; [Primitive] +;; Provide an eq? as defined in the book such that it requires a non-numeric +;; atom for each argument. See the footnotes on page 12. +(define/contract (eq? a b) + (-> (and/c atom? (not/c racket-number?)) (and/c atom? (not/c racket-number?)) boolean?) + (racket-eq? a b)) + + +;;********************************************************** +;; Chapter 2 +;;********************************************************** + +;; Predicate for determining if a value is a list of atoms or not +(define lat? + (lambda (l) + (cond + [(null? l) #t] + [(atom? (car l)) (lat? (cdr l))] + [else #f]))) + +;; Predicate for determining if a value is an element of the list of atoms or not +#;(define member? + (lambda (a lat) + (cond + [(null? lat) #f] + [else (or (eq? (car lat) a) + (member? a (cdr lat)))]))) + + +;;********************************************************** +;; Chapter 3 +;;********************************************************** + +;; Removes the first occurence of the atom, if possible, in the list of atoms +;; (Rewritten below in the Chapter 5 section using equal? as instructed by the book) +#;(define rember + (lambda (a lat) + (cond + [(null? lat) '()] + [(eq? a (car lat)) (cdr lat)] + [else (cons (car lat) + (rember a (cdr lat)))]))) + +;; Takes a list and returns a list of the first elements of each sublist +(define firsts + (lambda (l) + (cond + [(null? l) '()] + [else (cons (car (car l)) + (firsts (cdr l)))]))) + +;; Inserts new after the first occurrence, if any, of old in lat, a list of atoms +;; (Rewritten using insert-g in Chapter 8.) +#;(define insertR + (lambda (new old lat) + (cond + [(null? lat) '()] + [(eq? old (car lat)) (cons old + (cons new (cdr lat)))] + [else (cons (car lat) + (insertR new old (cdr lat)))]))) + +;; Inserts new before the first occurrence, if any, of old in lat, a list of atoms +;; (Rewritten using insert-g in Chapter 8.) +#;(define insertL + (lambda (new old lat) + (cond + [(null? lat) '()] + [(eq? old (car lat)) (cons new lat)] ; since (cons old (cdr lat)) = lat when old = (car lat) + [else (cons (car lat) + (insertL new old (cdr lat)))]))) + +;; Replaces the first occurrence of old, if any, with new, in lat, a list of atoms +;; (Rewritten using insert-g in Chapter 8.) +#;(define subst + (lambda (new old lat) + (cond + [(null? lat) '()] + [(eq? old (car lat)) (cons new (cdr lat))] + [else (cons (car lat) + (subst new old (cdr lat)))]))) + +;; Replaces the first occurence of o1 or o2, if any, in lat, a list of atoms +(define subst2 + (lambda (new o1 o2 lat) + (cond + [(null? lat) '()] + [(or (eq? o1 (car lat)) (eq? o2 (car lat))) (cons new (cdr lat))] + [else (cons (car lat) + (subst2 new o1 o2 (cdr lat)))]))) + +;; Removes all occurrences of a in lat, a list of atoms +#;(define multirember + (lambda (a lat) + (cond + [(null? lat) '()] + [(eq? a (car lat)) (multirember a (cdr lat))] + [else (cons (car lat) + (multirember a (cdr lat)))]))) + +;; Inserts new after all occurrences of old in lat, a list of atoms +(define multiinsertR + (lambda (new old lat) + (cond + [(null? lat) '()] + [(eq? old (car lat)) (cons old + (cons new + (multiinsertR new old (cdr lat))))] + [else (cons (car lat) + (multiinsertR new old (cdr lat)))]))) + +;; Inserts new before all occurrences of old in lat, a list of atoms +(define multiinsertL + (lambda (new old lat) + (cond + [(null? lat) '()] + [(eq? old (car lat)) (cons new + (cons (car lat) + (multiinsertL new old (cdr lat))))] ; since (cons old (cdr lat)) = lat when old = (car lat) + [else (cons (car lat) + (multiinsertL new old (cdr lat)))]))) + +;; Replaces all occurrences of old with new in lat, a list of atoms +(define multisubst + (lambda (new old lat) + (cond + [(null? lat) '()] + [(eq? old (car lat)) (cons new (multisubst new old (cdr lat)))] + [else (cons (car lat) + (multisubst new old (cdr lat)))]))) + + +;;********************************************************** +;; Chapter 4 +;;********************************************************** + +;; Adds 1 to the number n +(define add1 + (lambda (n) + (racket+ n 1))) + +;; Subtracts 1 from the number n +(define sub1 + (lambda (n) + (racket- n 1))) + +;; Add two non-negative integer numbers +(define + + (lambda (n m) + (cond + [(zero? m) n] + [else (+ (add1 n) (sub1 m))]))) +; I think this is more clear by adding 1 to n rather than the result + +;; Subtract two non-negative integer numbers +(define - + (lambda (n m) + (cond + [(zero? m) n] + [else (- (sub1 n) (sub1 m))]))) +; I think this is more clear by subtracting 1 from n rather than the result + +;; [Primitive] +;; Predicate for determining if a list is a list of non-negative numbers or not +(define (tup? x) + (andmap exact-nonnegative-integer? x)) + +;; Adds all the numbers in a tuple together +(define addtup + (lambda (tup) + (cond + [(null? tup) 0] + [else (+ (car tup) (addtup (cdr tup)))]))) + +;; Multiples two non-negative integer numbers +(define × + (lambda (n m) + (cond + [(zero? m) 0] + [else (+ n (× n (sub1 m)))]))) + +;; Adds the elements of two tuples together +(define tup+ + (lambda (tup1 tup2) + (cond + [(null? tup1) tup2] + [(null? tup2) tup1] + [else (cons (+ (car tup1) (car tup2)) + (tup+ (cdr tup1) (cdr tup2)))]))) + +;; Determines if n > m +(define > + (lambda (n m) + (cond + [(zero? n) #f] + [(zero? m) #t] + [else (> (sub1 n) (sub1 m))]))) + +;; Determines if n < m +(define < + (lambda (n m) + (cond + [(zero? m) #f] + [(zero? n) #t] + [else (< (sub1 n) (sub1 m))]))) + +;; Determines if two numbers are equal or not +(define = + (lambda (n m) + (cond + [(< n m) #f] + [(> n m) #f] + [else #t]))) + +;; Computes n to the power of m +(define ↑ + (lambda (n m) + (cond + [(zero? m) 1] + [else (× n (↑ n (sub1 m)))]))) + +;; Computes how many times m divides n +(define ÷ + (lambda (n m) + (cond + [(< n m) 0] + [else (add1 (÷ (- n m) m))]))) + +;; Returns the length of lat, a list of atoms +(define length + (lambda (lat) + (cond + [(null? lat) 0] + [else (add1 (length (cdr lat)))]))) + +;; Picks the nth element of lat, a list of atoms +(define pick + (lambda (n lat) + (cond + [(zero? (sub1 n)) (car lat)] + [else (pick (sub1 n) (cdr lat))]))) + +;; Removes the nth element from lat, a list of atoms +(define rempick + (lambda (n lat) + (cond + [(one? n) (cdr lat)] + [else (cons (car lat) + (rempick (sub1 n) (cdr lat)))]))) + +;; [Primitive] +;; Predicate for determining if a value is a numeric atom, i.e. a non-negative integer, or not +(define (number? x) + (exact-nonnegative-integer? x)) + +;; Removes all numbers from lat, a list of atoms +(define no-nums + (lambda (lat) + (cond + [(null? lat) '()] + [(number? (car lat)) (no-nums (cdr lat))] + [else (cons (car lat) + (no-nums (cdr lat)))]))) + +;; Returns a tuple made out of all the numbers in lat, a list of atoms +(define all-nums + (lambda (lat) + (cond + [(null? lat) '()] + [(number? (car lat)) (cons (car lat) (all-nums (cdr lat)))] + [else (all-nums (cdr lat))]))) + +;; Predicate that determines if a1 and a2 are the same number or same atom +(define eqan? + (lambda (a1 a2) + (cond + [(and (number? a1) (number? a2)) (= a1 a2)] + [(or (number? a1) (number? a2)) #f] + [else (eq? a1 a2)]))) + +;; Counts the number of times the atom a occurs in lat, a list of atoms +(define occur + (lambda (a lat) + (cond + [(null? lat) 0] + [(eq? a (car lat)) (add1 (occur a (cdr lat)))] + [else (occur a (cdr lat))]))) + +;; Predicate that determines if n is 1 or not +(define one? + (lambda (n) + (= n 1))) + + +;;********************************************************** +;; Chapter 5 +;;********************************************************** + +;; Removes the atom a everywhere it occurs the list l +(define rember* + (lambda (a l) + (cond + [(null? l) '()] + [(atom? (car l)) + (cond + [(eq? a (car l)) (rember* a (cdr l))] + [else (cons (car l) (rember* a (cdr l)))])] + [else (cons (rember* a (car l)) (rember* a (cdr l)))]))) + +;; Inserts new to the right of where old appears everywhere in the list l +(define insertR* + (lambda (new old l) + (cond + [(null? l) '()] + [(atom? (car l)) + (cond + [(eq? old (car l)) (cons old + (cons new + (insertR* new old (cdr l))))] + [else (cons (car l) (insertR* new old (cdr l)))])] + [else (cons (insertR* new old (car l)) + (insertR* new old (cdr l)))]))) + +;; Counts how many times the atom a occurs in the list l +(define occur* + (lambda (a l) + (cond + [(null? l) 0] + [(atom? (car l)) + (cond + [(eq? a (car l)) (add1 (occur* a (cdr l)))] + [else (occur* a (cdr l))])] + [else (+ (occur* a (car l)) + (occur* a (cdr l)))]))) + +;; Replaces old with new everywhere old appears in the list l +(define subst* + (lambda (new old l) + (cond + [(null? l) '()] + [(atom? (car l)) + (cond + [(eq? old (car l)) (cons new + (subst* new old (cdr l)))] + [else (cons (car l) + (subst* new old (cdr l)))])] + [else (cons (subst* new old (car l)) + (subst* new old (cdr l)))]))) + +;; Inserts new to the left of where old appears everywhere in the list l +(define insertL* + (lambda (new old l) + (cond + [(null? l) '()] + [(atom? (car l)) + (cond + [(eq? old (car l)) (cons new + (cons old + (insertL* new old (cdr l))))] + [else (cons (car l) (insertL* new old (cdr l)))])] + [else (cons (insertL* new old (car l)) + (insertL* new old (cdr l)))]))) + +;; Determines if the atom is found in the list l +(define member* + (lambda (a l) + (cond + [(null? l) #f] + [(atom? (car l)) (or (eq? a (car l)) + (member* a (cdr l)))] + [else (or (member* a (car l)) + (member* a (cdr l)))]))) + +;; Returns the leftmost atom in a non-empty list +(define leftmost + (lambda (l) + (cond + [(atom? (car l)) (car l)] + [else (leftmost (car l))]))) + +;; Determines if the two lists are equal or not +;; (Rewritten below using equal? as instructed by the book) +#;(define eqlist? + (lambda (l1 l2) + (cond + [(and (null? l1) (null? l2)) #t] + [(or (null? l1) (null? l2)) #f] + [(and (atom? (car l1)) (atom? (car l2))) (and (eqan? (car l1) (car l2)) + (eqlist? (cdr l1) (cdr l2)))] + [(or (atom? (car l1)) (atom? (car l2))) #f] + [else (and (eqlist? (car l1) (car l2)) + (eqlist? (cdr l1) (cdr l2)))]))) + +;; Determines if the two S-expressions are equal or not +(define equal? + (lambda (s1 s2) + (cond + [(and (atom? s1) (atom? s2)) (eqan? s1 s2)] + [(or (atom? s1) (atom? s2)) #f] + [else (eqlist? s1 s2)]))) + +;; Determines if the two lists are equal or not +(define eqlist? + (lambda (l1 l2) + (cond + [(and (null? l1) (null? l2)) #t] + [(or (null? l1) (null? l2)) #f] + [else (and (equal? (car l1) (car l2)) + (equal? (cdr l1) (cdr l2)))]))) + +;; Removes the first occurence of the atom, if possible, in the list of atoms +(define rember + (lambda (s l) + (cond + [(null? l) '()] + [(equal? s (car l)) (cdr l)] + [else (cons (car l) + (rember s (cdr l)))]))) + + +;;********************************************************** +;; Chapter 6 +;;********************************************************** + +;; Determines if the arithmetic expression aexp contains only numbers besides +, ×, and ↑ +#;(define numbered? + (lambda (aexp) + (cond + [(atom? aexp) (number? aexp)] + [(or (eq? (car (cdr aexp)) (quote +)) + (eq? (car (cdr aexp)) (quote ×)) + (eq? (car (cdr aexp)) (quote ↑))) (and (numbered? (car aexp)) (numbered? (car (cdr (cdr aexp)))))] + [else #f]))) +;; Note: the book assumes aexp is already an arithmetic expression such that we don't need to test that it is +;; as this implementation does, looking for +, ×, and ↑. + +;; Determines if the arithmetic expression aexp contains only numbers besides +, ×, and ↑ +(define numbered? + (lambda (aexp) + (cond + [(atom? aexp) (number? aexp)] + [else (and (numbered? (car aexp)) + (numbered? (car (cdr (cdr aexp)))))]))) + +;; The book has two implementations of value for two different representations. +;; The value for the first representation is what is implemented here. + +;; Evaluates the value of a numbered arithmetic expression +#;(define value + (lambda (nexp) + (cond + [(atom? nexp) nexp] ; Really should ask number? and not just atom? + [(eq? (car (cdr nexp)) (quote +)) (+ (value (car nexp)) (value (car (cdr (cdr nexp)))))] + [(eq? (car (cdr nexp)) (quote ×)) (× (value (car nexp)) (value (car (cdr (cdr nexp)))))] + [(eq? (car (cdr nexp)) (quote ↑)) (↑ (value (car nexp)) (value (car (cdr (cdr nexp)))))]))) +;; Note: I'm not a fan of the book's implementation, which assumes ↑. + +;; Gets the first sub-expression from an arithmetic expression +(define 1st-sub-exp + (lambda (aexp) + (car (cdr aexp)))) + +;; Gets the second sub-expression from an arithmetic expression +(define 2nd-sub-exp + (lambda (aexp) + (car (cdr (cdr aexp))))) + +;; Gets the operator from an arithmetic expression +(define operator + (lambda (aexp) + (car aexp))) + +;; Evaluates the value of a numbered arithmetic expression +;; (Rewritten using atom-to-function in Chapter 8.) +#;(define value + (lambda (nexp) + (cond + [(atom? nexp) nexp] + [(eq? (operator nexp) (quote +)) (+ (value (1st-sub-exp nexp)) (value (2nd-sub-exp nexp)))] + [(eq? (operator nexp) (quote ×)) (× (value (1st-sub-exp nexp)) (value (2nd-sub-exp nexp)))] + [(eq? (operator nexp) (quote ↑)) (↑ (value (1st-sub-exp nexp)) (value (2nd-sub-exp nexp)))]))) +;; Note: I'm not a fan of the book's implementation, which assumes ↑. + + +;;********************************************************** +;; Chapter 7 +;;********************************************************** + +;; Predicate for determining if a value is an element of the list of atoms or not +;; Redefined using equal? instead of eq? +(define member? + (lambda (a lat) + (cond + [(null? lat) #f] + [else (or (equal? (car lat) a) + (member? a (cdr lat)))]))) + +;; Determines whether a list of atoms is a set or not +(define set? + (lambda (lat) + (cond + [(null? lat) #t] + [(member? (car lat) (cdr lat)) #f] + [else (set? (cdr lat))]))) + +;; Makes a set out of a list of atoms +#;(define makeset + (lambda (lat) + (cond + [(null? lat) '()] + [(member? (car lat) (cdr lat)) (makeset (cdr lat))] + [else (cons (car lat) (makeset (cdr lat)))]))) + +;; Removes all occurrences of a in lat, a list of atoms +;; Redefined using equal? instead of eq? +(define multirember + (lambda (a lat) + (cond + [(null? lat) '()] + [(equal? a (car lat)) (multirember a (cdr lat))] + [else (cons (car lat) + (multirember a (cdr lat)))]))) + +;; Makes a set out of a list of atoms +(define makeset + (lambda (lat) + (cond + [(null? lat) '()] + [else (cons (car lat) + (makeset (multirember (car lat) (makeset (cdr lat)))))]))) + +;; Determines if set1 is a subset of set2 or not +(define subset? + (lambda (set1 set2) + (cond + [(null? set1) #t] + [else (and (member? (car set1) set2) + (subset? (cdr set1) set2))]))) + +;; Determines if the two sets are equal or not +(define eqset? + (lambda (set1 set2) + (and (subset? set1 set2) + (subset? set2 set1)))) + +;; Determines if the two set intersect or not +(define intersect? + (lambda (set1 set2) + (cond + [(null? set1) #t] + [else (or (member? (car set1) set2) + (intersect? (cdr set1) set2))]))) + +;; Returns the intersection of the two sets +(define intersect + (lambda (set1 set2) + (cond + [(null? set1) '()] + [(member? (car set1) set2) (cons (car set1) + (intersect (cdr set1) set2))] + [else (intersect (cdr set1) set2)]))) + +;; Returns the union of the two sets +(define union + (lambda (set1 set2) + (cond + [(null? set1) set2] + [(member? (car set1) set2) (union (cdr set1) set2)] + [else (cons (car set1) + (union (cdr set1) set2))]))) + +;; Intersects all the sets in the list of sets +(define intersectall + (lambda (l-set) + (cond + [(null? (cdr l-set)) (car l-set)] + [else (intersect (car l-set) (intersectall (cdr l-set)))]))) + +;; Determines whether an S-expression is a list of only two S-expressions +(define a-pair? + (lambda (x) + (cond + [(atom? x) #f] + [(null? x) #f] + [(null? (cdr x)) #f] + [else (and (s-exp? (car x)) + (s-exp? (car (cdr x))) + (null? (cdr (cdr x))))]))) + +;; Returns the first S-expression of a list or pair +(define first + (lambda (p) + (car p))) + +;; Returns the second S-expression of a list or pair +(define second + (lambda (p) + (car (cdr p)))) + +;; Returns the third S-expression of a list +(define third + (lambda (p) + (car (cdr (cdr p))))) + +;; Builds a pair out of the two S-expressions +(define build + (lambda (s1 s2) + (cons s1 (cons s2 '())))) + +;; Determines whether a relation is a function or not +(define fun? + (lambda (rel) + (set? (firsts rel)))) + +;; Reverses a pair +(define revpair + (lambda (pair) + (build (second pair) + (first pair)))) + +;; Reverses a relation +(define revrel + (lambda (rel) + (cond + [(null? rel) '()] + [else (cons (revpair (car rel)) + (revrel (cdr rel)))]))) + +;; Takes a list and returns a list of the second elements of each sublist +(define seconds + (lambda (l) + (cond + [(null? l) '()] + [else (cons (second (car l)) + (seconds (cdr l)))]))) + +;; Determines whether a function is full or not +(define fullfun? + (lambda (fun) + (set? (seconds fun)))) + +;; Determines whether a function is one-to-one or not +(define one-to-one? + (lambda (fun) + (fun? (revrel fun)))) + + +;;********************************************************** +;; Chapter 8 +;;********************************************************** + +;; Removes the first occurence of the atom a where (test? a) is true in the list of atoms +;; (Rewritten below as instructed by the book) +#;(define rember-f + (lambda (test? a l) + (cond + [(null? l) '()] + [(test? a (car l)) (cdr l)] + [else (cons (car l) + (rember-f test? a (cdr l)))]))) + +;; Returns a function that tests equality against the atom a +(define eq?-c + (lambda (a) + (lambda (x) + (eq? x a)))) + +;; A function to test if the argument is eq? to 'salad +(define eq?-salad (eq?-c 'salad)) + +;; Removes the first occurence of the atom a where (test? a) is true in the list of atoms +(define rember-f + (lambda (test?) + (lambda (a l) + (cond + [(null? l) '()] + [(test? a (car l)) (cdr l)] + [else (cons (car l) + ((rember-f test?) a (cdr l)))])))) + +;; Removes the first occurence of the atom a, using eq?, in the list of atoms +(define rember-eq? (rember-f eq?)) + +;; Inserts new before the first occurrence, if any, of old in lat, a list of atoms +(define insertL-f + (lambda (test?) + (lambda (new old lat) + (cond + [(null? lat) '()] + [(test? old (car lat)) (cons new lat)] ; since (cons old (cdr lat)) = lat when old = (car lat) + [else (cons (car lat) + ((insertL-f test?) new old (cdr lat)))])))) + +;; Inserts new after the first occurrence, if any, of old in lat, a list of atoms +(define insertR-f + (lambda (test?) + (lambda (new old lat) + (cond + [(null? lat) '()] + [(test? old (car lat)) (cons old + (cons new (cdr lat)))] + [else (cons (car lat) + ((insertR-f test?) new old (cdr lat)))])))) + +;; Conses new onto the cons of old and l +(define seqL + (lambda (new old l) + (cons new (cons old l)))) + +;; Conses old onto the cons of new and l +(define seqR + (lambda (new old l) + (cons old (cons new l)))) + +(define insert-g + (lambda (seq) + (lambda (new old l) + (cond + [(null? l) '()] + [(eq? old (car l)) (seq new old (cdr l))] + [else (cons (car l) + ((insert-g seq) new old (cdr l)))])))) + +;; Inserts new before the first occurrence, if any, of old in lat, a list of atoms +(define insertL (insert-g seqL)) + +;; Inserts new after the first occurrence, if any, of old in lat, a list of atoms +(define insertR (insert-g seqR)) + +(define seqS + (lambda (new old l) + (cons new l))) + +;; Replaces the first occurrence of old, if any, with new, in lat, a list of atoms +(define subst (insert-g seqS)) + +(define seqrem + (lambda (new old l) + l)) + +(define yyy + (lambda (a l) + ((insert-g seqrem) #f a l))) + +;; Takes '+, '×, and '↑ and returns +, ×, and ↑, respectively +(define atom-to-function + (lambda (x) + (cond + [(eq? x (quote +)) +] + [(eq? x (quote ×)) ×] + [else ↑]))) + +;; Evaluates the value of a numbered arithmetic expression +;; (Rewritten below in Chapter 10) +#;(define value + (lambda (nexp) + (cond + [(atom? nexp) nexp] + [else ((atom-to-function (operator nexp)) + (value (1st-sub-exp nexp)) + (value (2nd-sub-exp nexp)))]))) + +;; Removes all occurrences of a, using test?, in lat, a list of atoms +(define multirember-f + (lambda (test?) + (lambda (a lat) + (cond + [(null? lat) '()] + [(test? a (car lat)) ((multirember-f test?) a (cdr lat))] + [else (cons (car lat) + ((multirember-f test?) a (cdr lat)))])))) + +;; Removes all occurrences of a, using eq?, in lat, a list of atoms +(define multirember-eq? (multirember-f eq?)) + +;; A function to test if the argument is eq? to 'tuna +(define eq?-tuna (eq?-c (quote tuna))) + +;; Removes all occurences that pass the test test? in lat, a list of atoms +(define multiremberT + (lambda (test? lat) + (cond [(null? lat) '()] + [(test? (car lat)) (multiremberT test? (cdr lat))] + [else (cons (car lat) + (multiremberT test? (cdr lat)))]))) + +;; Looks at every atom of lat, a list of atoms, to see whether +;; the atom is equal, using eq?, to a. Those atoms that are not +;; equal are collected in one list ls1. The atoms that are equal +;; are collected in a second list ls2. Finally, it determines the +;; value of (f ls1 ls2). +(define multirember&co + (lambda (a lat col) + (cond [(null? lat) (col '() '())] + [(eq? (car lat) a) (multirember&co a + (cdr lat) + (lambda (newlat seen) + (col newlat (cons (car lat) seen))))] + [else (multirember&co a + (cdr lat) + (lambda (newlat seen) + (col (cons (car lat) newlat) seen)))]))) + +(define a-friend + (lambda (x y) + (null? y))) + +(define new-friend + (lambda (newlat seen) + (a-friend newlat + (cons (car 'tuna) seen)))) + +(define latest-friend + (lambda (newlat seen) + (a-friend (cons 'and newlat) + seen))) + +(define last-friend + (lambda (x y) + (length x))) + +;; Inserts new to the left of oldL and to the right of oldR in lat, a list of atoms, +;; for every occurrence of oldL and oldR +(define multiinsertLR + (lambda (new oldL oldR lat) + (cond [(null? lat) '()] + [(eq? (car lat) oldL) (cons new + (cons oldL + (multiinsertLR new oldL oldR (cdr lat))))] + [(eq? (car lat) oldR) (cons oldR + (cons new + (multiinsertLR new oldL oldR (cdr lat))))] + [else (cons (car lat) + (multiinsertLR new oldL oldR (cdr lat)))]))) + +(define multiinsertLR&co + (lambda (new oldL oldR lat col) + (cond [(null? lat) (col '() 0 0)] + [(eq? (car lat) oldL) + (multiinsertLR&co new oldL oldR (cdr lat) + (lambda (newlat L R) + (col (cons new + (cons oldL newlat)) + (add1 L) R)))] + [(eq? (car lat) oldR) + (multiinsertLR&co new oldL oldR (cdr lat) + (lambda (newlat L R) + (col (cons oldR + (cons new newlat)) + L (add1 R))))] + [else + (multiinsertLR&co new oldL oldR (cdr lat) + (lambda (newlat L R) + (col (cons (car lat) newlat) L R)))]))) + +;; Determines whether the number is even or not +(define even? + (lambda (n) + (= (× (÷ n 2) 2) n))) + +;; Removes all odd numbers from a list of nested lists +(define evens-only* + (lambda (l) + (cond [(null? l) '()] + [(atom? (car l)) + (cond [(even? (car l)) (cons (car l) + (evens-only* (cdr l)))] + [else (evens-only* (cdr l))])] + [else (cons (evens-only* (car l)) + (evens-only* (cdr l)))]))) + +(define evens-only*&co + (lambda (l col) + (cond [(null? l) (col '() 1 0)] + [(atom? (car l)) + (cond [(even? (car l)) + (evens-only*&co (cdr l) + (lambda (newl p s) + (col (cons (car l) newl) + (× (car l) p) s)))] + [else (evens-only*&co (cdr l) + (lambda (newl p s) + (col newl + p (+ (car l) s))))])] + [else (evens-only*&co (car l) + (lambda (al ap as) + (evens-only*&co (cdr l) + (lambda (dl dp ds) + (col (cons al dl) + (× ap dp) + (+ as ds))))))]))) + +(define the-last-friend + (lambda (newl product sum) + (cons sum + (cons product newl)))) + + +;;********************************************************** +;; Chapter 9 +;;********************************************************** + +(define looking + (lambda (a lat) + (keep-looking a (pick 1 lat) lat))) + +(define keep-looking + (lambda (a sorn lat) + (cond [(number? sorn) (keep-looking a (pick sorn lat) lat)] + [else (eq? sorn a)]))) +;; Note: a sorn is a symbol or a number + +(define eternity + (lambda (x) + (eternity x))) + +;; Takes a pair whose first component is a pair and builds a pair by +;; shifting the second part of the first component into the second +;; component +(define shift + (lambda (pair) + (build (first (first pair)) + (build (second (first pair)) + (second pair))))) + +(define align + (lambda (pora) + (cond [(atom? pora) pora] + [(a-pair? (first pora)) (align (shift pora))] + [else (build (first pora) + (align (second pora)))]))) + +(define length* + (lambda (pora) + (cond [(atom? pora) 1] + [else (+ (length* (first pora)) + (length* (second pora)))]))) + +(define weight* + (lambda (pora) + (cond [(atom? pora) 1] + [else (+ (× (weight* (first pora)) 2) + (weight* (second pora)))]))) + +(define shuffle + (lambda (pora) + (cond [(atom? pora) pora] + [(a-pair? (first pora)) (shuffle (revpair pora))] + [else (build (first pora) + (shuffle (second pora)))]))) + +(define C + (lambda (n) + (cond [(one? n) 1] + [else (cond [(even? n) (C (÷ n 2))] + [else (C (add1 (× 3 n)))])]))) + +(define A + (lambda (n m) + (cond [(zero? n) (add1 m)] + [(zero? m) (A (sub1 n) 1)] + [else (A (sub1 n) + (A n (sub1 m)))]))) + +(define Y + (lambda (le) + ((lambda (f) (f f)) + (lambda (f) + (le (lambda (x) ((f f) x))))))) + + +;;********************************************************** +;; Chapter 10 +;;********************************************************** + +;; Builds an entry from a set of names and a list of values +(define new-entry build) + +;; Looks up the value corresponding to the name in the entry +;; and calls entry-f on name if the name is not in the entry +(define lookup-in-entry + (lambda (name entry entry-f) + (lookup-in-entry-help name + (first entry) + (second entry) + entry-f))) + +;; Helper function for lookup-in-entry +(define lookup-in-entry-help + (lambda (name names values entry-f) + (cond [(null? names) (entry-f name)] + [(eq? (car names) name) (car values)] + [else (lookup-in-entry-help name + (cdr names) + (cdr values) + entry-f)]))) + +;; Takes an entry and table and returns a new table with the +;; entry at the front +(define extend-table cons) + +;; Looks up the value corresponding to the name in the table, using +;; the first value found, and calls entry-f on name if the name is not +;; found in the entries listed in the table +(define lookup-in-table + (lambda (name table table-f) + (cond [(null? table) (table-f name)] + [else (lookup-in-entry name + (car table) + (lambda (name) + (lookup-in-table name + (cdr table) + (table-f))))]))) + +;; Converts an expression to an action +(define expression-to-action + (lambda (e) + (cond [(atom? e) (atom-to-action e)] + [else (list-to-action e)]))) + +;; Converts an atom to an action +(define atom-to-action + (lambda (e) + (cond [(number? e) *const] + [(eq? e #t) *const] + [(eq? e #f) *const] + [(eq? e 'cons) *const] + [(eq? e 'car) *const] + [(eq? e 'cdr) *const] + [(eq? e 'null?) *const] + [(eq? e 'eq?) *const] + [(eq? e 'atom?) *const] + [(eq? e 'zero?) *const] + [(eq? e 'add1) *const] + [(eq? e 'sub1) *const] + [(eq? e 'number?) *const] + [else *identifier]))) + +;; Converts a list to an action +(define list-to-action + (lambda (e) + (cond [(atom? (car e)) + (cond [(eq? (car e) 'quote) *quote] + [(eq? (car e) 'lambda) *lambda] + [(eq? (car e) 'cond) *cond] + [else *application])] + [else *application]))) + +(define value + (lambda (e) + (meaning e '()))) + +(define meaning + (lambda (e table) + ((expression-to-action e) e table))) + +(define *const + (lambda (e table) + (cond [(number? e) e] + [(eq? e #t) #t] + [(eq? e #f) #f] + [else (build 'primitive e)]))) + +(define *quote + (lambda (e table) + (text-of e))) + +(define text-of second) + +(define *identifier + (lambda (e table) + (lookup-in-table e table initial-table))) + +(define initial-table + (lambda (name) + (car '()))) + +(define *lambda + (lambda (e table) + (build 'non-primitive + (cons table (cdr e))))) + +(define table-of first) + +(define formals-of second) + +(define body-of third) + +(define evcon + (lambda (lines table) + (cond [(else? (question-of (car lines))) + (meaning (answer-of (car lines)) table)] + [(meaning (question-of (car lines)) table) + (meaning (answer-of (car lines)) table)] + [else (evcon (cdr lines) table)]))) + +(define else? + (lambda (x) + (cond + [(atom? x) (eq? x 'else)] + (else #f)))) + +(define question-of first) + +(define answer-of second) + +(define *cond + (lambda (e table) + (evcon (cond-lines-of e) table))) + +(define cond-lines-of cdr) + +(define evlis + (lambda (args table) + (cond [(null? args) '()] + [else (cons (meaning (car args) table) + (evlis (cdr args) table))]))) + +(define *application + (lambda (e table) + (apply (meaning (function-of e) table) + (evlis (arguments-of e) table)))) + +(define function-of car) + +(define arguments-of cdr) + +(define primitive? + (lambda (l) + (eq? (first l) 'primitive))) + +(define non-primitive? + (lambda (l) + (eq? (first l) 'non-primitive))) + +(define apply + (lambda (fun vals) + (cond [(primitive? fun) (apply-primitive (second fun) vals)] + [(non-primitive? fun) (apply-closure (second fun) vals)]))) + +(define apply-primitive + (lambda (name vals) + (cond [(eq? name 'cons) (cons (first vals) (second vals))] + [(eq? name 'car) (car (first vals))] + [(eq? name 'cdr) (cdr (first vals))] + [(eq? name 'null?) (null? (first vals))] + [(eq? name 'eq?) (eq? (first vals) (second vals))] + [(eq? name 'atom?) (atom? (first vals))] + [(eq? name 'add1) (add1 (first vals))] + [(eq? name'sub1) (sub1 (first vals))] + [(eq? name 'number?) (number? (first vals))]))) + +(define apply-closure + (lambda (closure vals) + (meaning (body-of closure) + (extend-table + (new-entry + (formals-of closure) + vals) + (table-of closure))))) + + +;;********************************************************** +;; Tests +;;********************************************************** + +(module+ test + (require rackunit) + + ;;******************************************************** + ;; Primitives + ;;******************************************************** + + (check-false (atom? (quote ()))) + + (check-false (atom? '())) + + (check-true (s-exp? '())) + + (check-true (s-exp? 'symbol)) + + (check-equal? (cons 'a '()) '(a)) + + (check-equal? (cons 'a '(b)) '(a b)) + + (check-exn exn:fail? (thunk(cons 'a 'b))) + + (check-pred null? '()) + + (check-pred null? (quote ())) + + (check-pred null? empty) + + (check-exn exn:fail? (thunk (null? 'a))) + ) diff --git a/little_schemer/tls.ss b/little_schemer/tls.ss new file mode 100644 index 0000000..4d329df --- /dev/null +++ b/little_schemer/tls.ss @@ -0,0 +1,11 @@ +(define atom? + (lambda (x) + (and (not (pair? x)) (not (null? x))))) + +(define add1 + (lambda (x) + (+ x 1))) + +(define sub1 + (lambda (x) + (- x 1))) diff --git a/yast/hello.scm b/yast/hello.scm index 83d2f17..9c9d45f 100644 --- a/yast/hello.scm +++ b/yast/hello.scm @@ -14,5 +14,16 @@ (lambda (a b c) (+ a b c))) +(define add1 + (lambda (a) + (+ a 1))) + +(define sub1 + (lambda (b) + (- b 1))) +(display(string-append "sub1 to 2 is " (number->string(sub1 2)) "\n")) + + ;; display message on screen (display "Hello World!") + From 50a0eda4a83d7ed4f20c20eaf353227b3d5e307e Mon Sep 17 00:00:00 2001 From: Geir Okkenhaug Jerstad Date: Tue, 20 Aug 2024 19:17:15 +0200 Subject: [PATCH 2/3] a little scheme --- hello | Bin 17328 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 hello diff --git a/hello b/hello deleted file mode 100755 index 012eb1d448706c0c0ef44f59693f2a4b87183e2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17328 zcmeHPdvsjIdB1wu8)Hjr;}@^6j%8{vT1&PhzYttm53caq7~2?!N3K`9D{HNNb$4YX z1GT9LVOcM68%luE)}=YAlcwjWG~p;5Ffs<@(v*mhrfv>(1qHeyV9YDH1hf5pGxM$P zu6BC}=j4yJ8l8K;`F`_#Gv9nOcV_PF9qns#wU?HZXdFtlD>dRGvvmQN#|);53aXTS%1jCW5Y_lJ1x# zS*Ds@@}yTmQN?R^ojCBiAhTx*qA_K;Y>$RkiTzv zEFO;fmaks5x_)(ZPjpvxk6@4^{K^0eevo|*K4KwwPC`z+!C!Mhc8t;L_{E2 zsvF6ZJ_V}63=z|`*`OEUx)9fVTnlk6z*U9oJY47FIu{p}KL;1d&%?#O{SxBm;JN@; zeo$R6AI{;aUro0l+zwnnvY%|N#6@GpYg%usJM=8N{5K_mxzgTQ@z+yOHljs$#rd;#!rUoaAm zx*>zSJUu|7zNpU=aQlNRz;s2!!C1uYL9YIwKMthR?KR!eT^^H?y*^LaOKEXm)Q#+n zj+PB=o6MlwA3`b@WBNkzXg>i_t-1&TwzYYwmGJ{qD{H z>G(si-0w9b(Xhwo?Tr#9OwL+1VJq@QYTO_6MWF}VqP>y0=|Pr=BPG}ycgKBZED)v| z#XM1W+|zCL#@xF^uEG@3CR1YWJwDS7Ta;G-Mcw|GZz5wL-IAk9M}52eF%*MlAP@P? zfG-w{puuQZR}CioLwvX2)8h-#fL>Rp0SHpGkz(F}9Og+%f>*mb*0-3L7wR?3bkgr$ z73%D-@AtU(dUn^<_uRVI>+bLFs$J<{?d=cM2WnIqH4V;{&RUvI)>^c?R@CqH+*;@9 zS`iJbu3h8pY1mWy`~Lpg?&z+bmF|_1npn3l5Xjg1?WZtnnf0~(yY~iHMH_nj4QqOO zde+phSm_Pj+8JEk*taUuj|tG@si|A(T;Z(6w1?Tx--)LQGuIdTgDL{)zJ+Ir=Z_!$ z(F2&GO0^GxQ5d>P7nJ5L1qpuGg40~X;kX5-IgZ1q1*dtB!wCz{a}=eGS#X-eIHWDO zb=*8{!L4)Z84FHxH3x^nX%4l{w@WR!TCxb0S_>}Lw<@F67M$mHO42R3b)GgXIIj&! zezOJVH3s23EVx=a6RhpD;I!u8&~3rFO(`v6!L8$Ip9QD&3Wxm`oYo5*?y=ysp5buN zg4244!-E!_)<+x;S#VlAaX4(jX&uF3(1O$2YAQ^5;D3_`KB)TgC&s|rHX~Vabh)M( zUmuQ_W=4&HXKlwsH8KrvIW;Y_&^&%f@XruWL)Z90!9PJf4O!#+1^*cFG*pd81pj^FX^0x%DfmZ; zry+fOv)~^lo`$M%UGRTQJPqyRwSvEwcp9?C9fJQu;%SHN7u%mg(~@v{9X4>N8+Wg8Hv}7 zf!9xO-quz(T=x&g$jHvwaPPduQ2(&YS#|MU$U+nH$0pc=Lu0zG8BKJLpF2bn)MQ_J znt;q$*TG|56T(#95g~u)DM1pajiaZoGLD`pGfJK}UivIPJDbCFl|#Nh*}K2#M=(n3 zJ@^Jxypwvb@?zZ9dbHm|N{iM9!oi zLS_nt%>a|Nu2j>vkR7V-I6{wxE0J-fywz3dKl>Ecrsmy0Q(ztFFGt9m>5nA70r-)x zP$8*(HX~8737Mq-Ri^!b(kf+|9cgPR?J1Gg&^n9qdl%^Cg#IT`E*GUOh5bl6kCL85 z(#Ax*8abSl9v>pVBUBqBW#syf1l6x%P()j+ZLWmJmTrTZXjRdsXql~O6I9O*pWnF* zg(n-W?R%nb*p&=n5Gpk?$BjfO`t-gTPgCbfFC&YS74=XulCzqK;K5mDuNyXweo}_! zEvfqRVWX_XSn~{8O*9vJ!G3ho^w@9EYKdhX$#%P_>`5chVoUFY`$bJMqryV;IqErZ zJ#2g9GP2ESwJnX3tai;2b{UD@6X|cF03+FZ0`}bxMKUZo>tTvn>?^B!WY|cxYGo5f zzOO8#uC>tYO$M#8XlB(Jv{Bh$$5Mq)D>rQMcZ zgB)Z{Iud88G9S`2v=FsfK&B+WY^@DEol_g-<>x*TUViaX%9m>KbBayW;w;x<8rQ;= zc&#;Y3KhANT-{6h18?gv^+xo3Zx0Tg_(FR(2gWX77bd#vZ4u_H2u@Eql zHiPO*({KEju;&j%1t6aIY5Fj#*)edobl)s;mv}trdFV*Y#AEg5(=_08ByO&@b&RxD z+iAR4?OUJ+W-zRL{vP-}Y0G0!lD-+D*o1FBEu|hJaI_{g|pduToU^gF-$3AB9B4&o7YD~FZ9lc%PRE3FWwrw>1{;$bXXQss$xDqR~qvuGAjSQpt%1E}2x)N_4p-06? z-7#wXm{Jg`@yxrDzEO;-Uj-{*=}Hvf*q8`ZFH}P^iuqG2Ce`#1R!kj<=h8nQHd)ao zDtwZAS%5sBI7js*51iU#w|X>pfF4`&+dLlk$`Zc?C3yM~B4R={k{FJUV`YOWRSwff zjnuZ;@aCvxpzb4IuA(fYFUb+YBd)}Fjz2dhyD*9`##6B{ed|Y59W@_eOmEI?tF}!n zBJzhp`{epyK~bnP9HESp6(iMD2^t3fiDDB^$Juf@nCp{=LGiGMNM8(t6&q=m7rj`t z=){BFg7LiKPechPje%nr?^@2FO!A*Aaa-C*_1V&oQ$DGROE5UN66?^sFJV-eYkYmUbz?(4fUS7iT@E{Ap5WTLy0wljw+BCw;#Z73Jcb`L zg1*IGe=HJk_gfMhis;m?b>!)EnRP4b){5fH6+RTG5mG-1Y0O9JYbPPA@{xu~G7XdR zY0Q;jC*@@I*?LWL7~~Si4dH0OyJ$u`d&Cj$ax^&nv9%7ZS2Klm#^4}-oB`a0;M_cEC?pdY`V$y|sv#zP-uGCHUS^zR7>)?wQtTL^svIFI40bprdzd`zZYdPyvWo-w_jR91KWM(4m9r*EO#0!-} zGPRI-1U~-6DkI8irEEk#+aME#|F?i<^VuNng}Fke4{3+cHZNN9vDB#=_#=?H2JN=W znoqm*P1}KK#sC)Bf|F<64JVzIGcPL6r zCX$tePV6LIhyUGR(#&5%6T%Xls-JIMntio*^x@}$@7N9IZX1H}(6kbK1=NpDj5FHroy&6oJ4 zil-lI3x%s&TGl$2;!EjE9r6pcLP8dd`e(WJ9{u!~6R01T;EUx!^}IS%>KxEQ^7JiG zDc<rsls4-E;c?)86im27;SP~1-@Qxl1-GtC`9lid0806@-^F_|u=uQy|Hb<=Fpt8y9mM-EFu%gt|1X25Ko2X~!|g2Ije+$loZDNx z4+Fam7uCzI>c!*6KH!D?d9TW6Ft7g~Q21CL{uc`8`2nm5^!+vYnZAdhz~j+T5uckK zuSFtmXx_9q zzA}66>k^gGp(6SGJ#Z>FzkRoqQMr{Geau9G*HQFKSRs2}QswgaE%pha_X_Yr{y9}7 zpR+~qO4vjG&$sh@VW%)L=XO~Ud{q(rnj-iOgqNcBc0DKmTZ+hsir}{cFXV>I7%Qs%g=88<7;?6jo{THaq$Je*ny{A z_l8Ef_fGfvRRXD{d!x9o5UKUG_y)d~O7Fzy^dVT_#i<1KVSPMkdII4PzRovIZ`j-w z2zTO4gBL#?;1EG?pXLeUw+3I_=XKT=mN2_u9}Y1@-TmrlLRZus^qJn?V6Y!57EaV8 zM-(>sLSEsM_ASjD+sw92tvG>UwtjU}^Tv)AsAG9xwi%{OHCnf5=GCri*EhS&Yunqm zwrw-FHLrKIK_mY}fNuH1ALkBoP9aP;)Ufe-i_rN~1Jus`nz3O>}&J=Fp6SlE=m^-zb&o+Y948D__|$jIvt;oODKi)8Cz z4m1lv*<%%^H-N4d2z$h_4IJL^d(4Pm9M;G`o?)7uv6wQk&`}NkiSsiNUo_sYpyu@*HS}DIv~G8-TXW*v2=bFO9+fG3e9@Rc9Lix# zq@hvVq@ZGvKwNWDU)7v(Umx!Dq#-RVdZ*LZt)8uJFLarc8uB5N8XQN)?x5d;QgKkn zDf2+zZdSJn zBTnmnYiI;x)#vvCK0oWQ3M0<*H^T-ZH0N^pqpJK-jOP@F#eL#DCYR6ov?3ipD}`B~ z_X`dx0p4fe{Q}lk*=m~*p}hju=lz61rO)4UQ60&5tk3K7?ZC)X*5~~R@r5>U-j6_3 zgna*h4Jf_qvp&Dy?@${WYn2|`&vHzAkWPCC%=7-igG%3_^z-dku(lTwsw(Rb&Co^C zkkUUPxXJ$K`rn0g(qFIScz@)e+JNEx6taIlu6+O92aJ5e^~WB%bheO||xtB%L}WGt_`6|>qQ zrO*E7b*|=+BHldv^Ysts>GOLKpC`XvW|O_=>pz~SKek90vSW*+%89)4x&36Sd_F6| zsK+(?{>SIb^W~Xm`V;6@S@d~-aQJdr0?SEmqW>^X{ge6*m(TBq{Qm-UzX8wz0KEVJ From 733a7c6d93793f14f490b50c8b1f3af1ecfb5dff Mon Sep 17 00:00:00 2001 From: Geir Okkenhaug Jerstad Date: Thu, 22 Aug 2024 19:21:01 +0200 Subject: [PATCH 3/3] a learn scheme in fixum days --- fixum/hello.scm | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 fixum/hello.scm diff --git a/fixum/hello.scm b/fixum/hello.scm new file mode 100644 index 0000000..0b4fa1a --- /dev/null +++ b/fixum/hello.scm @@ -0,0 +1,6 @@ +; The first program + + +(begin + (display "Hello, World!") + (newline))