diff --git a/README.md b/README.md index 2ffcaec..719825f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Clojure CI](https://github.com/SmetDenis/Clojure-Sicp/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/SmetDenis/Clojure-Sicp/actions/workflows/main.yml) [![Coverage Status](https://coveralls.io/repos/github/SmetDenis/Clojure-SICP/badge.svg?branch=main)](https://coveralls.io/github/SmetDenis/Clojure-SICP?branch=main) -![Progress](https://progress-bar.dev/122/?scale=356&title=Solved&width=500&suffix=) +![Progress](https://progress-bar.dev/123/?scale=356&title=Solved&width=500&suffix=) SICP (Structure and Interpretation of Computer Programs) is the book of Harold Abelson and Gerald Jay Sussman on basics of computer science and software engineering. @@ -43,7 +43,7 @@ Jay Sussman on basics of computer science and software engineering. ### Chapter 2 - Building Abstractions with Data -![Progress](https://progress-bar.dev/76/?scale=97&title=Solved&width=500&suffix=) +![Progress](https://progress-bar.dev/77/?scale=97&title=Solved&width=500&suffix=) * [2.1](https://sarabander.github.io/sicp/html/Chapter-2.xhtml#Chapter-2) Introduction to Data Abstraction - [Code in book](src/sicp/chapter_2/part_1/book_2_1.clj) * [2.1.1](https://sarabander.github.io/sicp/html/2_002e1.xhtml#g_t2_002e1_002e1) Example: Arithmetic Operations for Rational Numbers - [2.1](src/sicp/chapter_2/part_1/ex_2_01.clj) @@ -65,7 +65,7 @@ Jay Sussman on basics of computer science and software engineering. * [2.4.2](https://sarabander.github.io/sicp/html/2_002e4.xhtml#g_t2_002e4_002e2) Tagged data * [2.4.3](https://sarabander.github.io/sicp/html/2_002e4.xhtml#g_t2_002e4_002e3) Data-Directed Programming and Additivity - [2.73](src/sicp/chapter_2/part_4/ex_2_73.clj), [2.74](src/sicp/chapter_2/part_4/ex_2_74.clj), [2.75](src/sicp/chapter_2/part_4/ex_2_75.clj), [2.76](src/sicp/chapter_2/part_4/ex_2_76.clj) * [2.5](https://sarabander.github.io/sicp/html/2_002e5.xhtml#g_t2_002e5) Systems with Generic Operations - [Code in book](src/sicp/chapter_2/part_5/book_2_5.clj) - * [2.5.1](https://sarabander.github.io/sicp/html/2_002e5.xhtml#g_t2_002e5_002e1) Generic Arithmetic Operations + * [2.5.1](https://sarabander.github.io/sicp/html/2_002e5.xhtml#g_t2_002e5_002e1) Generic Arithmetic Operations - [2.77](src/sicp/chapter_2/part_5/ex_2_77.clj) * [2.5.2](https://sarabander.github.io/sicp/html/2_002e5.xhtml#g_t2_002e5_002e2) Combining Data of Different Types * [2.5.3](https://sarabander.github.io/sicp/html/2_002e5.xhtml#g_t2_002e5_002e3) Example: Symbolic Algebra 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 5b9f79a..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,149 +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 new file mode 100644 index 0000000..4300b56 --- /dev/null +++ b/src/sicp/chapter_2/part_5/ex_2_77.clj @@ -0,0 +1,22 @@ +(ns sicp.chapter-2.part-5.ex-2-77 + (:require + [sicp.chapter-2.packages.op-table :as ot])) + +; Exercise 2.77 +; +; Louis Reasoner tries to evaluate the expression (magnitude z) where z is the object shown in +; Figure 2.24. To his surprise, instead of the answer 5 he gets an error message from apply-generic, +; saying there is no method for the operation magnitude on the types (complex). +; +; He shows this interaction to Alyssa P. Hacker, who says “The problem is that the complex-number +; selectors were never defined for complex numbers, just for polar and rectangular numbers. +; All you have to do to make this work is add the following to the complex package:” +; +; (put 'real-part '(complex) real-part) +; (put 'imag-part '(complex) imag-part) +; (put 'magnitude '(complex) magnitude) +; (put 'angle '(complex) angle) + +(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 new file mode 100644 index 0000000..c2856ae --- /dev/null +++ b/test/sicp/chapter_2/part_5/ex_2_77_test.clj @@ -0,0 +1,21 @@ +(ns sicp.chapter-2.part-5.ex-2-77-test + (: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]])) + +(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)))))