code of SICP and Expression Problem
完整可运行代码
复数的直角坐标实现 by Scheme
#lang racket
(define (square x) (* x x))
(define (average x y)
(/ (+ x y) 2))
(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))
(define (real-part z) (car z))
(define (imag-part z) (cdr z))
(define (magnitude z)
(sqrt (+ (square (real-part z)) (square (imag-part z)))))
(define (angle z)
(atan (imag-part z) (real-part z)))
(define (make-from-real-imag x y) (cons x y))
(define (make-from-mag-ang r a)
(cons (* r (cos a)) (* r (sin a))))
(make-from-real-imag 1 2)
(make-from-mag-ang 1 2)
复数的极坐标实现 by Scheme
#lang racket
(define (square x) (* x x))
(define (average x y)
(/ (+ x y) 2))
(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))
(define (real-part z)
(* (magnitude z) (cos (angle z))))
(define (imag-part z)
(* (magnitude z) (sin (angle z))))
(define (magnitude z) (car z))
(define (angle z) (cdr z))
(define (make-from-real-imag x y)
(cons (sqrt (+ (square x) (square y)))
(atan y x)))
(define (make-from-mag-ang r a) (cons r a))
(make-from-real-imag 1 2)
(make-from-mag-ang 1 2)
复数的数据导向风格的完整实现 by Scheme
#lang racket
(define (square x) (* x x))
(define (average x y)
(/ (+ x y) 2))
(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))
(define (attach-tag type-tag contents)
(cons type-tag contents))
(define (type-tag datum)
(if (pair? datum)
(car datum)
(error "Bad tagged datum -- TYPE-TAG" datum)))
(define (contents datum)
(if (pair? datum)
(cdr datum)
(error "Bad tagged datum -- CONTENTS" datum)))
(define (rectangular? z)
(eq? (type-tag z) 'rectangular))
(define (polar? z)
(eq? (type-tag z) 'polar))
(define (real-part-rectangular z) (car z))
(define (imag-part-rectangular z) (cdr z))
(define (magnitude-rectangular z)
(sqrt (+ (square (real-part-rectangular z))
(square (imag-part-rectangular z)))))
(define (angle-rectangular z)
(atan (imag-part-rectangular z)
(real-part-rectangular z)))
(define (make-from-real-imag-rectangular x y)
(attach-tag 'rectangular (cons x y)))
(define (make-from-mag-ang-rectangular r a)
(attach-tag 'rectangular
(cons (* r (cos a)) (* r (sin a)))))
(define (real-part-polar z)
(* (magnitude-polar z) (cos (angle-polar z))))
(define (imag-part-polar z)
(* (magnitude-polar z) (sin (angle-polar z))))
(define (magnitude-polar z) (car z))
(define (angle-polar z) (cdr z))
(define (make-from-real-imag-polar x y)
(attach-tag 'polar
(cons (sqrt (+ (square x) (square y)))
(atan y x))))
(define (make-from-mag-ang-polar r a)
(attach-tag 'polar (cons r a)))
(define (real-part z)
(cond ((rectangular? z)
(real-part-rectangular (contents z)))
((polar? z)
(real-part-polar (contents z)))
(else (error "Unknown type -- REAL-PART" z))))
(define (imag-part z)
(cond ((rectangular? z)
(imag-part-rectangular (contents z)))
((polar? z)
(imag-part-polar (contents z)))
(else (error "Unknown type -- IMAG-PART" z))))
(define (magnitude z)
(cond ((rectangular? z)
(magnitude-rectangular (contents z)))
((polar? z)
(magnitude-polar (contents z)))
(else (error "Unknown type -- MAGNITUDE" z))))
(define (angle z)
(cond ((rectangular? z)
(angle-rectangular (contents z)))
((polar? z)
(angle-polar (contents z)))
(else (error "Unknown type -- ANGLE" z))))
(define (add-complex z1 z2)
(make-from-real-imag-polar (+ (real-part z1) (real-part z2))
(+ (imag-part z1) (imag-part z2))))
复数的消息传递风格的完整实现 by Scheme
#lang racket
(define (square x) (* x x))
(define (average x y)
(/ (+ x y) 2))
(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))
(define (make-from-real-imag x y)
(define (dispatch op)
(cond ((eq? op 'real-part) x)
((eq? op 'imag-part) y)
((eq? op 'imagnitude)
(sqrt (+ (square x) (square y))))
((eq? op 'angle) (atan x y))
(else
(error "Unkown op -- MAKE-FORM-REAL-IMAG" op))))
dispatch)
(define (apply-generic op arg) (arg op))
(define (real-part z) (apply-generic 'real-part z))
(define (imag-part z) (apply-generic 'imag-part z))
(define (magnitude z) (apply-generic 'magnitude z))
(define (angle z) (apply-generic 'angle z))
(define test (make-from-real-imag 3 4))
(test 'real-part)
(real-part test)
创建二维表格 by Scheme
#lang racket
(require rnrs/mutable-pairs-6)
(define (assoc key records)
(cond ((null? records) false)
((equal? key (car records)) (car records))
(else (assoc key (cdr records)))))
(define (make-table)
(let ((local-table (list '*table*)))
(define (lookup key-1 key-2)
(let ((subtable (assoc key-1 (cdr local-table))))
(if subtable
(let ((record (assoc key-2 (cdr subtable))))
(if record
(cdr record)
false))
false)))
(define (insert! key-1 key-2 value)
(let ((subtable (assoc key-1 (cdr local-table))))
(if subtable
(let ((record (assoc key-2 (cdr subtable))))
(if record
(set-cdr! record value)
(set-cdr! subtable
(cons (cons key-2 value)
(cdr subtable)))))
(set-cdr! local-table
(cons (list key-1
(cons key-2 value))
(cdr local-table)))))
'ok)
(define (dispatch m)
(cond ((eq? m 'lookup-proc) lookup)
((eq? m 'insert-proc!) insert!)
(else (error "Unknown operation -- TABLE" m))))
dispatch))
(define operation-table (make-table))
(define get (operation-table 'lookup-proc))
(define put (operation-table 'insert-proc!))
Expression Problem by OCaml
type exp =
Int of int
| Negate of exp
| Add of exp * exp
let rec eval = function
| Int i -> i
| Negate e -> -(eval e)
| Add(e1, e2) -> (eval e1 ) + (eval e2)
let rec toString = function
| Int i -> string_of_int i
| Negate e -> "-(" ^ (toString e) ^ ")"
| Add(e1, e2) -> "(" ^ (toString e1) ^ "+" ^ (toString e2) ^ ")"
;;
let res = toString (Add ((Negate (Int 5)), (Int 6)));;
let num = eval (Add ((Negate (Int 5)), (Int 6)));;
print_endline res;;
print_endline (string_of_int num);;
OCaml polymorphic variant
exception BadResult of string
type exp =
[`Int of int
| `Negate of exp
| `Add of exp * exp]
let rec eval = function
| `Int i -> i
| `Negate e -> -(eval e)
| `Add(e1, e2) -> (eval e1 ) + (eval e2)
let rec toString = function
| `Int i -> string_of_int i
| `Negate e -> "-(" ^ (toString e) ^ ")"
| `Add(e1, e2) -> "(" ^ (toString e1) ^ "+" ^ (toString e2) ^ ")"
type new_exp = [ exp | `Sub of new_exp * new_exp]
let rec new_eval : new_exp -> int = function
| #exp as exp -> eval exp
| `Sub(e1, e2) -> (new_eval e1) - (new_eval e2)
let rec new_toString : new_exp -> string = function
| `Sub(e1, e2) -> "(" ^ (new_toString e1) ^ "-" ^ (new_toString e2) ^ ")"
| #exp as exp -> toString exp
;;
let a = `Int 10
let b = `Int 6
let c = `Sub(a, b)
let d = new_eval c
;;
print_endline (string_of_int d);;
let res = toString (`Add ((`Negate (`Int 5)), (`Int 6)));;
let num = eval (`Add ((`Negate (`Int 5)), (`Int 6)));;
print_endline res;;
print_endline (string_of_int num);;
Visitor pattern by Java
package siegel.visitor;
public class VisitorPattern {
public static void main(String[] args) {
System.out.println("nice!");
Exp exp1 = new Add(new Literal(1), new Literal(2));
int res = exp1.accept(new ExpEvalVisitor());
String show = exp1.accept(new ExpShowVisitor());
System.out.println("eval reslut:" + res);
System.out.println("show reslut:" + show);
Exp exp2 = new Add(new Literal(2), new Literal(2));
Exp2 exp3 = new Divide(exp1, exp2);
int res4 = exp3.accept(new ExpEvalVisitor2());
System.out.println("divide eval reslut:" + res4);
}
}
interface Exp {
<T> T accept(ExpVisitor<T> visitor);
}
interface ExpVisitor<T> {
public T forLiteral(int v);
public T forAdd(Exp a, Exp b);
}
class Literal implements Exp {
public final int val;
public Literal(int val) {
this.val = val;
}
public <T> T accept(ExpVisitor<T> visitor) {
return visitor.forLiteral(val);
}
}
class Add implements Exp {
public final Exp a;
public final Exp b;
public Add(Exp a, Exp b) {
this.a = a;
this.b = b;
}
public <T> T accept(ExpVisitor<T> visitor) {
return visitor.forAdd(a, b);
}
}
class ExpEvalVisitor implements ExpVisitor<Integer> {
@Override
public Integer forLiteral(int v) {
return v;
}
@Override
public Integer forAdd(Exp a, Exp b) {
return a.accept(this) + b.accept(this);
}
}
class ExpShowVisitor implements ExpVisitor<String> {
@Override
public String forLiteral(int v) {
return v + "";
}
@Override
public String forAdd(Exp a, Exp b) {
return "(" + a.accept(this) + "+" + b.accept(this) + ")";
}
}
interface ExpVisitor2<T> extends ExpVisitor<T> {
public T forDivide(Exp a, Exp b);
}
interface Exp2 {
public abstract <T> T accept(ExpVisitor2<T> visitor);
}
class ExpEvalVisitor2 extends ExpEvalVisitor implements ExpVisitor2<Integer> {
@Override
public Integer forDivide(Exp a, Exp b) {
return a.accept(this) / b.accept(this);
}
}
class Divide implements Exp2 {
public final Exp a;
public final Exp b;
public Divide(Exp a, Exp b) {
this.a = a;
this.b = b;
}
public <T> T accept(ExpVisitor2<T> visitor) {
return visitor.forDivide(a, b);
}
}
Object Algebras by Java
package siegel.objectAlgebras;
public class ObjectAlgebras {
public static void main(String[] args) {
System.out.println("nice!");
Eval e = new Eval();
int res = e.add(e.literal(1), e.literal(2));
System.out.println("result: " + res);
Eval2 e2 = new Eval2();
int res2 = e2.divide(e2.literal(4), e2.literal(2));
System.out.println("2 result: " + res2);
}
}
interface Exp<T> {
public T literal(int v);
public T add(T a, T b);
}
class Eval implements Exp<Integer> {
@Override
public Integer literal(int v) {
return v;
}
@Override
public Integer add(Integer a, Integer b) {
return a + b;
}
}
class Show implements Exp<String> {
@Override
public String literal(int v) {
return v + "";
}
@Override
public String add(String a, String b) {
return "(" + a + "+" + b + ")";
}
}
interface Exp2<T> extends Exp<T> {
public T divide(T a, T b);
}
class Eval2 extends Eval implements Exp2<Integer> {
@Override
public Integer divide(Integer a, Integer b) {
return a / b;
}
}
interpreter by Racket
#lang racket
(define env0 '())
(define ext-env
(lambda (x v env)
(cons `(,x ., v) env)))
(define lookup
(lambda (x env)
(let ([p (assq x env)])
(cond
[(not p) #f]
[else (cdr p)]))))
(struct Closure (f env))
(define interp
(lambda (exp env)
(match exp
[(? symbol? x)
(let ([v (lookup x env)])
(cond
[(not v)
(error "undefined variable" x)]
[else v]))]
[(? number? x) x]
[`(lambda (,x), e)
(Closure exp env)]
[`(let ([,x, e1]), e2)
(let ([v1 (interp e1 env)])
(interp e2 (ext-env x v1 env)))]
[`(,e1, e2)
(let ([v1 (interp e1 env)]
[v2 (interp e2 env)])
(match v1
[(Closure `(lambda (,x), e) env-save)
(interp e (ext-env x v2 env-save))]))]
[`(,op, e1, e2)
(let ([v1 (interp e1 env)]
[v2 (interp e2 env)])
(match op
['+ (+ v1 v2)]
['- (- v1 v2)]
['* (* v1 v2)]
['/ (/ v1 v2)]))])))
(define r2
(lambda (exp)
(interp exp env0)))
(r2 '(+ 1 2))
(r2 '(* (+ 1 2) (+ 3 4)))
(r2
'(let ([x 2])
(let ([f (lambda (y) (* x y))])
(f 3))))
(r2
'(let ([x 2])
(let ([f (lambda (y) (* x y))])
(let ([x 4])
(f 3)))))