From 6ed98820e7729ce9dd7a86d337000e41bb2bb3c2 Mon Sep 17 00:00:00 2001 From: Denis Smet Date: Sun, 18 Feb 2024 21:57:54 +0400 Subject: [PATCH] Refactor parts of SICP chapter 2's code The code refactor focused on the parts related to packages in chapter 2 of SICP. It included separating different packages into their own files, implementing a generic operation system, and standardizing the function interface. This has resulted in cleaner, more maintainable, and more understandable code. --- project.clj | 2 +- .../chapter_2/packages/install_complex.clj | 45 ++++++ src/sicp/chapter_2/packages/install_polar.clj | 24 +++ .../chapter_2/packages/install_rational.clj | 44 ++++++ .../packages/install_rectangular.clj | 25 ++++ .../packages/install_scheme_number.clj | 17 +++ src/sicp/chapter_2/packages/op_table.clj | 36 +++++ src/sicp/chapter_2/part_4/book_2_4.clj | 13 +- src/sicp/chapter_2/part_5/book_2_5.clj | 139 ++---------------- src/sicp/chapter_2/part_5/ex_2_77.clj | 14 +- test/sicp/chapter_2/part_5/book_2_5_test.clj | 47 +++--- test/sicp/chapter_2/part_5/ex_2_77_test.clj | 23 ++- 12 files changed, 257 insertions(+), 172 deletions(-) create mode 100644 src/sicp/chapter_2/packages/install_complex.clj create mode 100644 src/sicp/chapter_2/packages/install_polar.clj create mode 100644 src/sicp/chapter_2/packages/install_rational.clj create mode 100644 src/sicp/chapter_2/packages/install_rectangular.clj create mode 100644 src/sicp/chapter_2/packages/install_scheme_number.clj create mode 100644 src/sicp/chapter_2/packages/op_table.clj diff --git a/project.clj b/project.clj index ab1046e..b5ea37e 100644 --- a/project.clj +++ b/project.clj @@ -7,7 +7,7 @@ :source-paths ["src"] :test-paths ["test"] :main ^:skip-aot sicp - :target-path "build/%s" + :target-path "target/%s" :plugins [[lein-cloverage "1.2.2"]] :profiles {:dev {:dependencies [[org.clojure/clojure "1.11.1"] [io.github.noahtheduke/splint "1.12"]]} diff --git a/src/sicp/chapter_2/packages/install_complex.clj b/src/sicp/chapter_2/packages/install_complex.clj new file mode 100644 index 0000000..bd4ca54 --- /dev/null +++ b/src/sicp/chapter_2/packages/install_complex.clj @@ -0,0 +1,45 @@ +(ns sicp.chapter-2.packages.install-complex + (:require + [sicp.chapter-2.packages.op-table :as ot] + [sicp.chapter-2.part-4.book-2-4 :as b24])) + +(defn install-complex-package + [] + ; Imported procedures from rectangular and polar packages + (letfn [(make-from-real-imag [x y] ((ot/get :make-from-real-imag :rectangular) x y)) + (make-from-mag-ang [r a] ((ot/get :make-from-mag-ang :polar) r a)) + ; Internal procedures + (add-complex + [z1 z2] + (make-from-real-imag (+ (b24/real-part z1) (b24/real-part z2)) + (+ (b24/imag-part z1) (b24/imag-part z2)))) + (sub-complex + [z1 z2] + (make-from-real-imag (- (b24/real-part z1) (b24/real-part z2)) + (- (b24/imag-part z1) (b24/imag-part z2)))) + (mul-complex + [z1 z2] + (make-from-mag-ang (* (b24/magnitude z1) (b24/magnitude z2)) + (+ (b24/angle z1) (b24/angle z2)))) + (div-complex + [z1 z2] + (make-from-mag-ang (/ (b24/magnitude z1) (b24/magnitude z2)) + (- (b24/angle z1) (b24/angle z2)))) + ; Interface to rest of the system + (tag [z] (ot/attach-tag :complex z))] + ; Putting functions in a map or registry + (ot/put :add [:complex :complex] (fn [z1 z2] (tag (add-complex z1 z2)))) + (ot/put :sub [:complex :complex] (fn [z1 z2] (tag (sub-complex z1 z2)))) + (ot/put :mul [:complex :complex] (fn [z1 z2] (tag (mul-complex z1 z2)))) + (ot/put :div [:complex :complex] (fn [z1 z2] (tag (div-complex z1 z2)))) + (ot/put :make-from-real-imag :complex (fn [x y] (tag (make-from-real-imag x y)))) + (ot/put :make-from-mag-ang :complex (fn [r a] (tag (make-from-mag-ang r a)))) + :done)) + +(defn make-complex-from-real-imag + [x y] + ((ot/get :make-from-real-imag :complex) x y)) + +(defn make-complex-from-mag-ang + [r a] + ((ot/get :make-from-mag-ang :complex) r a)) diff --git a/src/sicp/chapter_2/packages/install_polar.clj b/src/sicp/chapter_2/packages/install_polar.clj new file mode 100644 index 0000000..2987594 --- /dev/null +++ b/src/sicp/chapter_2/packages/install_polar.clj @@ -0,0 +1,24 @@ +(ns sicp.chapter-2.packages.install-polar + (:require + [sicp.chapter-2.packages.op-table :as ot])) + +(defn install-polar-package + [] + (letfn [(magnitude [z] (first z)) + (angle [z] (second z)) + (make-from-mag-ang [r a] (list r a)) + (real-part [z] (* (magnitude z) (Math/cos (angle z)))) + (imag-part [z] (* (magnitude z) (Math/sin (angle z)))) + (make-from-real-imag + [x y] + (list (Math/sqrt (+ (Math/pow x 2) (Math/pow y 2))) + (Math/atan2 y x))) + (tag [x] (cons :polar x))] + ; interface to the rest of the system + (ot/put :real-part :polar real-part) + (ot/put :imag-part :polar imag-part) + (ot/put :magnitude :polar magnitude) + (ot/put :angle :polar angle) + (ot/put :make-from-real-imag :polar (fn [x y] (tag (make-from-real-imag x y)))) + (ot/put :make-from-mag-ang :polar (fn [r a] (tag (make-from-mag-ang r a)))) + :done)) diff --git a/src/sicp/chapter_2/packages/install_rational.clj b/src/sicp/chapter_2/packages/install_rational.clj new file mode 100644 index 0000000..9602856 --- /dev/null +++ b/src/sicp/chapter_2/packages/install_rational.clj @@ -0,0 +1,44 @@ +(ns sicp.chapter-2.packages.install-rational + (:require + [sicp.chapter-2.packages.op-table :as ot] + [sicp.misc :as m])) + +(defn install-rational-package + [] + ; Internal procedures + (letfn [(numer [x] (first x)) + (denom [x] (second x)) + (make-rat + [n d] + (let [g (m/gcd n d)] + (m/pair (/ n g) (/ d g)))) + (add-rat + [x y] + (make-rat (+ (* (numer x) (denom y)) + (* (numer y) (denom x))) + (* (denom x) (denom y)))) + (sub-rat + [x y] + (make-rat (- (* (numer x) (denom y)) + (* (numer y) (denom x))) + (* (denom x) (denom y)))) + (mul-rat + [x y] + (make-rat (* (numer x) (numer y)) + (* (denom x) (denom y)))) + (div-rat + [x y] + (make-rat (* (numer x) (denom y)) + (* (denom x) (numer y)))) + ; Interface to rest of the system + (tag [x] (ot/attach-tag :rational x))] + (ot/put :add [:rational :rational] (fn [x y] (tag (add-rat x y)))) + (ot/put :sub [:rational :rational] (fn [x y] (tag (sub-rat x y)))) + (ot/put :mul [:rational :rational] (fn [x y] (tag (mul-rat x y)))) + (ot/put :div [:rational :rational] (fn [x y] (tag (div-rat x y)))) + (ot/put :make :rational (fn [n d] (tag (make-rat n d)))) + :done)) + +(defn make-rational + [n d] + ((ot/get :make :rational) n d)) diff --git a/src/sicp/chapter_2/packages/install_rectangular.clj b/src/sicp/chapter_2/packages/install_rectangular.clj new file mode 100644 index 0000000..5dcad64 --- /dev/null +++ b/src/sicp/chapter_2/packages/install_rectangular.clj @@ -0,0 +1,25 @@ +(ns sicp.chapter-2.packages.install-rectangular + (:require + [sicp.chapter-2.packages.op-table :as ot])) + +(defn install-rectangular-package + [] + ; internal procedures + (letfn [(real-part [z] (first z)) + (imag-part [z] (second z)) + (make-from-real-imag [x y] (list x y)) + (magnitude + [z] + (Math/sqrt (+ (Math/pow (real-part z) 2) + (Math/pow (imag-part z) 2)))) + (angle [z] (Math/atan2 (imag-part z) (real-part z))) + (make-from-mag-ang [r a] (list (* r (Math/cos a)) (* r (Math/sin a)))) + (tag [x] (ot/attach-tag :rectangular x))] + ; interface to the rest of the system + (ot/put :real-part '(:rectangular) real-part) + (ot/put :imag-part '(:rectangular) imag-part) + (ot/put :magnitude '(:rectangular) magnitude) + (ot/put :angle '(:rectangular) angle) + (ot/put :make-from-real-imag :rectangular (fn [x y] (tag (make-from-real-imag x y)))) + (ot/put :make-from-mag-ang :rectangular (fn [r a] (tag (make-from-mag-ang r a)))) + :done)) diff --git a/src/sicp/chapter_2/packages/install_scheme_number.clj b/src/sicp/chapter_2/packages/install_scheme_number.clj new file mode 100644 index 0000000..bc5fa74 --- /dev/null +++ b/src/sicp/chapter_2/packages/install_scheme_number.clj @@ -0,0 +1,17 @@ +(ns sicp.chapter-2.packages.install-scheme-number + (:require + [sicp.chapter-2.packages.op-table :as ot])) + +(defn install-scheme-number-package + [] + (letfn [(tag [x] (ot/attach-tag :scheme-number x))] + (ot/put :add [:scheme-number :scheme-number] (fn [x y] (tag (+ x y)))) + (ot/put :sub [:scheme-number :scheme-number] (fn [x y] (tag (- x y)))) + (ot/put :mul [:scheme-number :scheme-number] (fn [x y] (tag (* x y)))) + (ot/put :div [:scheme-number :scheme-number] (fn [x y] (tag (/ x y)))) + (ot/put :make :scheme-number (fn [x] (tag x))) + :done)) + +(defn make-scheme-number + [n] + ((ot/get :make :scheme-number) n)) diff --git a/src/sicp/chapter_2/packages/op_table.clj b/src/sicp/chapter_2/packages/op_table.clj new file mode 100644 index 0000000..ffb5f9a --- /dev/null +++ b/src/sicp/chapter_2/packages/op_table.clj @@ -0,0 +1,36 @@ +(ns sicp.chapter-2.packages.op-table + (:refer-clojure :exclude [get]) + (:require + [clojure.pprint :as pp])) + +(comment "Custom helper functions. Made myself, just for testing ---------------------------------") + +(def operation-table (atom {})) + +(defn attach-tag + [tag value] + {:tag tag, :contents value}) + +(defn put + [operation types procedure] + (swap! operation-table assoc-in [operation types] procedure)) + +(defn get + [operation types] + (get-in @operation-table [operation types])) + +(defn apply-generic + [op & args] + (let [type-tags (map #(-> % :tag) args) + operation (get op type-tags)] + (if operation + (apply operation (map #(:contents %) args)) + (throw (IllegalArgumentException. (str "No method for: " op)))))) + +(defn inspect + [] + (->> @operation-table + (map (fn [item] + {:operation (first item) + :types (first (first (into '() (second item))))})) + (pp/print-table))) diff --git a/src/sicp/chapter_2/part_4/book_2_4.clj b/src/sicp/chapter_2/part_4/book_2_4.clj index d0cece0..aa5cf2e 100644 --- a/src/sicp/chapter_2/part_4/book_2_4.clj +++ b/src/sicp/chapter_2/part_4/book_2_4.clj @@ -91,15 +91,15 @@ (defn type-tag [datum] - (if (sequential? datum) - (first datum) - (throw (Exception. (str "Bad tagged datum: TYPE-TAG " datum))))) + (cond (sequential? datum) (first datum) + (map? datum) (get datum :tag) + :else (throw (Exception. (str "Bad tagged datum: TYPE-TAG " datum))))) (defn contents [datum] - (if (sequential? datum) - (rest datum) - (throw (Exception. (str "Bad tagged datum: CONTENTS " datum))))) + (cond (sequential? datum) (rest datum) + (map? datum) (get datum :contents) + :else (throw (Exception. (str "Bad tagged datum: CONTENTS " datum))))) (defn rectangular? [z] @@ -215,6 +215,7 @@ ; * 2.76 (defn apply-generic + "Just a wrapper for the dispatch table. It's a bit more verbose than the original, I don't use it" [op & args] (let [type-tags (map type-tag args) proc (get op type-tags)] diff --git a/src/sicp/chapter_2/part_5/book_2_5.clj b/src/sicp/chapter_2/part_5/book_2_5.clj index 5b7b070..1d1fd1e 100644 --- a/src/sicp/chapter_2/part_5/book_2_5.clj +++ b/src/sicp/chapter_2/part_5/book_2_5.clj @@ -1,145 +1,30 @@ (ns sicp.chapter-2.part-5.book-2-5 (:require - [sicp.chapter-2.part-4.book-2-4 :as b24] - [sicp.misc :as m])) + [sicp.chapter-2.packages.op-table :as ot])) (comment "2.5 Systems with Generic Operations ----------------------------------------------------") (comment "2.5.1 Generic Arithmetic Operations ----------------------------------------------------") -; Custom helper functions. Made myself, just for testing ------------------------------------------- - -(def operation-table (atom {})) - -(defn attach-tag - [tag value] - {:tag tag, :contents value}) - -(defn put-op - [operation types procedure] - (swap! operation-table assoc-in [operation types] procedure)) - -(defn get-op - [operation types] - (get-in @operation-table [operation types])) - -(defn apply-generic - [op & args] - (let [type-tags (map #(-> % :tag) args) - operation (get-op op type-tags)] - (if operation - (apply operation (map #(:contents %) args)) - (throw (IllegalArgumentException. (str "No method for: " op)))))) - -; -------------------------------------------------------------------------------------------------- - (defn add [x y] - (apply-generic :add x y)) + (ot/apply-generic :add x y)) (defn sub [x y] - (apply-generic :sub x y)) + (ot/apply-generic :sub x y)) (defn mul [x y] - (apply-generic :mul x y)) + (ot/apply-generic :mul x y)) (defn div [x y] - (apply-generic :div x y)) - -(defn install-scheme-number-package - [] - (letfn [(tag [x] (attach-tag :scheme-number x))] - (put-op :add [:scheme-number :scheme-number] (fn [x y] (tag (+ x y)))) - (put-op :sub [:scheme-number :scheme-number] (fn [x y] (tag (- x y)))) - (put-op :mul [:scheme-number :scheme-number] (fn [x y] (tag (* x y)))) - (put-op :div [:scheme-number :scheme-number] (fn [x y] (tag (/ x y)))) - (put-op :make :scheme-number (fn [x] (tag x))) - :done)) - -(defn install-rational-package - [] - ; Internal procedures - (letfn [(numer [x] (first x)) - (denom [x] (second x)) - (make-rat - [n d] - (let [g (m/gcd n d)] - (m/pair (/ n g) (/ d g)))) - (add-rat - [x y] - (make-rat (+ (* (numer x) (denom y)) - (* (numer y) (denom x))) - (* (denom x) (denom y)))) - (sub-rat - [x y] - (make-rat (- (* (numer x) (denom y)) - (* (numer y) (denom x))) - (* (denom x) (denom y)))) - (mul-rat - [x y] - (make-rat (* (numer x) (numer y)) - (* (denom x) (denom y)))) - (div-rat - [x y] - (make-rat (* (numer x) (denom y)) - (* (denom x) (numer y)))) - ; Interface to rest of the system - (tag [x] (attach-tag :rational x))] - (put-op :add [:rational :rational] (fn [x y] (tag (add-rat x y)))) - (put-op :sub [:rational :rational] (fn [x y] (tag (sub-rat x y)))) - (put-op :mul [:rational :rational] (fn [x y] (tag (mul-rat x y)))) - (put-op :div [:rational :rational] (fn [x y] (tag (div-rat x y)))) - (put-op :make :rational (fn [n d] (tag (make-rat n d)))) - :done)) - -(defn install-complex-package - [] - ; Imported procedures from rectangular and polar packages - (letfn [(make-from-real-imag [x y] ((get-op :make-from-real-imag :rectangular) x y)) - (make-from-mag-ang [r a] ((get-op :make-from-mag-ang :polar) r a)) - ; Internal procedures - (add-complex - [z1 z2] - (make-from-real-imag (+ (b24/real-part z1) (b24/real-part z2)) - (+ (b24/imag-part z1) (b24/imag-part z2)))) - (sub-complex - [z1 z2] - (make-from-real-imag (- (b24/real-part z1) (b24/real-part z2)) - (- (b24/imag-part z1) (b24/imag-part z2)))) - (mul-complex - [z1 z2] - (make-from-mag-ang (* (b24/magnitude z1) (b24/magnitude z2)) - (+ (b24/angle z1) (b24/angle z2)))) - (div-complex - [z1 z2] - (make-from-mag-ang (/ (b24/magnitude z1) (b24/magnitude z2)) - (- (b24/angle z1) (b24/angle z2)))) - ; Interface to rest of the system - (tag [z] (attach-tag :complex z))] - ; Putting functions in a map or registry - (put-op :add [:complex :complex] (fn [z1 z2] (tag (add-complex z1 z2)))) - (put-op :sub [:complex :complex] (fn [z1 z2] (tag (sub-complex z1 z2)))) - (put-op :mul [:complex :complex] (fn [z1 z2] (tag (mul-complex z1 z2)))) - (put-op :div [:complex :complex] (fn [z1 z2] (tag (div-complex z1 z2)))) - (put-op :make-from-real-imag :complex (fn [x y] (tag (make-from-real-imag x y)))) - (put-op :make-from-mag-ang :complex (fn [r a] (tag (make-from-mag-ang r a)))) - :done)) - -(defn make-scheme-number - [n] - ((get-op :make :scheme-number) n)) - -(defn make-rational - [n d] - ((get-op :make :rational) n d)) - -(defn make-complex-from-real-imag - [x y] - ((get-op :make-from-real-imag :complex) x y)) - -(defn make-complex-from-mag-ang - [r a] - ((get-op :make-from-mag-ang :complex) r a)) + (ot/apply-generic :div x y)) + +(comment + "See also:" + "sicp.chapter-2.packages.install-scheme-number" + "sicp.chapter-2.packages.install-rational" + "sicp.chapter-2.packages.install-rectangular" + "sicp.chapter-2.packages.install-complex") diff --git a/src/sicp/chapter_2/part_5/ex_2_77.clj b/src/sicp/chapter_2/part_5/ex_2_77.clj index b351624..4300b56 100644 --- a/src/sicp/chapter_2/part_5/ex_2_77.clj +++ b/src/sicp/chapter_2/part_5/ex_2_77.clj @@ -1,6 +1,6 @@ (ns sicp.chapter-2.part-5.ex-2-77 - (:require [sicp.chapter-2.part-4.book-2-4 :as b24] - [sicp.chapter-2.part-5.book-2-5 :as b25])) + (:require + [sicp.chapter-2.packages.op-table :as ot])) ; Exercise 2.77 ; @@ -17,10 +17,6 @@ ; (put 'magnitude '(complex) magnitude) ; (put 'angle '(complex) angle) - -(b25/install-complex-package) -(b25/put-op :real-part '(:complex) b24/real-part) -(b25/put-op :imag-part '(:complex) b24/imag-part) -(b25/put-op :magnitude '(:complex) b24/magnitude) -(b25/put-op :angle '(:complex) b24/angle) -(b24/magnitude (b25/make-complex-from-real-imag 3 4)) +(defn magnitude + [z] + (ot/apply-generic :magnitude z)) diff --git a/test/sicp/chapter_2/part_5/book_2_5_test.clj b/test/sicp/chapter_2/part_5/book_2_5_test.clj index ab09e5e..23413a2 100644 --- a/test/sicp/chapter_2/part_5/book_2_5_test.clj +++ b/test/sicp/chapter_2/part_5/book_2_5_test.clj @@ -1,41 +1,38 @@ (ns sicp.chapter-2.part-5.book-2-5-test (:require [clojure.test :refer [deftest is]] + [sicp.chapter-2.packages.install-rational :as rational] + [sicp.chapter-2.packages.install-scheme-number :as scheme] + [sicp.chapter-2.packages.op-table :as ot] [sicp.chapter-2.part-5.book-2-5 :as b25] [sicp.misc :as m])) -(b25/install-scheme-number-package) -(b25/install-rational-package) -(b25/install-complex-package) - -(deftest install-test - (is (= :done (b25/install-scheme-number-package))) - (is (= :done (b25/install-rational-package))) - (is (= :done (b25/install-complex-package)))) +(scheme/install-scheme-number-package) +(rational/install-rational-package) (deftest add-test - (is (= (b25/make-scheme-number 3) (b25/add (b25/make-scheme-number 1) (b25/make-scheme-number 2)))) - (is (= (b25/make-scheme-number 4) (b25/add (b25/make-scheme-number 2) (b25/make-scheme-number 2)))) - (is (= (b25/make-rational 4 1) (b25/add (b25/make-rational 2 1) (b25/make-rational 2 1)))) - (is (= (b25/make-rational 1 1) (b25/add (b25/make-rational 2 3) (b25/make-rational 1 3))))) + (is (= (scheme/make-scheme-number 3) (b25/add (scheme/make-scheme-number 1) (scheme/make-scheme-number 2)))) + (is (= (scheme/make-scheme-number 4) (b25/add (scheme/make-scheme-number 2) (scheme/make-scheme-number 2)))) + (is (= (rational/make-rational 4 1) (b25/add (rational/make-rational 2 1) (rational/make-rational 2 1)))) + (is (= (rational/make-rational 1 1) (b25/add (rational/make-rational 2 3) (rational/make-rational 1 3))))) (deftest sub-test - (is (= (b25/make-scheme-number 1) (b25/sub (b25/make-scheme-number 4) (b25/make-scheme-number 3)))) - (is (= (b25/make-scheme-number -6) (b25/sub (b25/make-scheme-number 4) (b25/make-scheme-number 10)))) - (is (= (b25/make-rational 0 1) (b25/sub (b25/make-rational 2 1) (b25/make-rational 2 1)))) - (is (= (b25/make-rational 1 3) (b25/sub (b25/make-rational 2 3) (b25/make-rational 1 3))))) + (is (= (scheme/make-scheme-number 1) (b25/sub (scheme/make-scheme-number 4) (scheme/make-scheme-number 3)))) + (is (= (scheme/make-scheme-number -6) (b25/sub (scheme/make-scheme-number 4) (scheme/make-scheme-number 10)))) + (is (= (rational/make-rational 0 1) (b25/sub (rational/make-rational 2 1) (rational/make-rational 2 1)))) + (is (= (rational/make-rational 1 3) (b25/sub (rational/make-rational 2 3) (rational/make-rational 1 3))))) (deftest mul-test - (is (= (b25/make-scheme-number 12) (b25/mul (b25/make-scheme-number 4) (b25/make-scheme-number 3)))) - (is (= (b25/make-scheme-number -40) (b25/mul (b25/make-scheme-number -4) (b25/make-scheme-number 10)))) - (is (= (b25/make-rational 4 1) (b25/mul (b25/make-rational 2 1) (b25/make-rational 2 1)))) - (is (= (b25/make-rational 2 9) (b25/mul (b25/make-rational 2 3) (b25/make-rational 1 3))))) + (is (= (scheme/make-scheme-number 12) (b25/mul (scheme/make-scheme-number 4) (scheme/make-scheme-number 3)))) + (is (= (scheme/make-scheme-number -40) (b25/mul (scheme/make-scheme-number -4) (scheme/make-scheme-number 10)))) + (is (= (rational/make-rational 4 1) (b25/mul (rational/make-rational 2 1) (rational/make-rational 2 1)))) + (is (= (rational/make-rational 2 9) (b25/mul (rational/make-rational 2 3) (rational/make-rational 1 3))))) (deftest div-test - (is (= (b25/make-scheme-number 20) (b25/div (b25/make-scheme-number 100) (b25/make-scheme-number 5)))) - (is (= (b25/make-scheme-number 1/2) (b25/div (b25/make-scheme-number 3) (b25/make-scheme-number 6)))) - (is (= (b25/make-rational 1 1) (b25/div (b25/make-rational 2 1) (b25/make-rational 2 1)))) - (is (= (b25/make-rational 2 1) (b25/div (b25/make-rational 2 3) (b25/make-rational 1 3))))) + (is (= (scheme/make-scheme-number 20) (b25/div (scheme/make-scheme-number 100) (scheme/make-scheme-number 5)))) + (is (= (scheme/make-scheme-number 1/2) (b25/div (scheme/make-scheme-number 3) (scheme/make-scheme-number 6)))) + (is (= (rational/make-rational 1 1) (b25/div (rational/make-rational 2 1) (rational/make-rational 2 1)))) + (is (= (rational/make-rational 2 1) (b25/div (rational/make-rational 2 3) (rational/make-rational 1 3))))) (deftest apply-generic-test - (is (= true (m/is-exception? ((b25/apply-generic :undefined 1 2)) "No method for: :undefined")))) + (is (= true (m/is-exception? ((ot/apply-generic :undefined 1 2)) "No method for: :undefined")))) diff --git a/test/sicp/chapter_2/part_5/ex_2_77_test.clj b/test/sicp/chapter_2/part_5/ex_2_77_test.clj index c23aa04..c2856ae 100644 --- a/test/sicp/chapter_2/part_5/ex_2_77_test.clj +++ b/test/sicp/chapter_2/part_5/ex_2_77_test.clj @@ -1,6 +1,21 @@ (ns sicp.chapter-2.part-5.ex-2-77-test - (:require [clojure.test :refer [deftest is]] - [sicp.chapter-2.part-5.ex-2-77 :refer [fix-complex-nimbers]])) + (:require + [clojure.test :refer [deftest is]] + [sicp.chapter-2.packages.install-complex :as complex] + [sicp.chapter-2.packages.install-polar :as polar] + [sicp.chapter-2.packages.install-rectangular :as rectangular] + [sicp.chapter-2.packages.op-table :as ot] + [sicp.chapter-2.part-4.book-2-4 :as b24] + [sicp.chapter-2.part-5.ex-2-77 :refer [magnitude]])) -(deftest fix-complex-nimbers-test - (is (= 5 (fix-complex-nimbers)))) +(rectangular/install-rectangular-package) +(polar/install-polar-package) +(complex/install-complex-package) + +(ot/put :real-part '(:complex) b24/real-part) +(ot/put :imag-part '(:complex) b24/imag-part) +(ot/put :magnitude '(:complex) b24/magnitude) +(ot/put :angle '(:complex) b24/angle) + +(deftest magnitude-test + (is (= 5.0 (magnitude (complex/make-complex-from-real-imag 3 4)))))