diff --git a/chapter-2/ex-2.73.txt b/chapter-2/ex-2.73.txt new file mode 100644 index 0000000..dc15e5e --- /dev/null +++ b/chapter-2/ex-2.73.txt @@ -0,0 +1,50 @@ +a) The predicates `number?` and `variable?` can't be assimilated because they +are checking the data type of the datum itself, not the value of a specific +symbol which can be found in a table. + +b) Here I'll only write the most basic version of the procedures, since the +more elaborate versions were done in previous exercises. + +(define (install-deriv-package) + (define (deriv-sum operands var) + (let ((addend (car operands)) + (augend (cadr operands))) + (make-sum (deriv addend var) + (deriv augend var)))) + + (define (deriv-product operands var) + (let ((multiplicand (car operands)) + (multiplier (cadr operands))) + (make-sum + (make-product multiplier + (deriv multiplicand var)) + (make-product (deriv multiplier var) + multiplicand)))) + + (put 'deriv '+ deriv-sum) + (put 'deriv '* deriv-product) + 'done) + +c) exponential rule: +... +(define (deriv-expon operands var) + (let ((base (car operands)) + (exponent (cadr operands))) + (if (constant? exponent var) + (make-product (make-product exponent + (make-exponentiation base + (make-sum + exponent + -1))) + (deriv base var)) + (error "non-constant exponents not yet supported: DERIV" exponent)))) +... +(put 'deriv '** deriv-expon) +... + +d) if the dispatch line looked like this: +((get (operator exp) 'deriv) (operands exp) var) + +the only part we would really have to change is the put lines for each of the +functions, like so: +(put 'deriv '+ deriv-sum) -> (put '+ 'deriv deriv-sum) diff --git a/chapter-2/ex-2.74.txt b/chapter-2/ex-2.74.txt new file mode 100644 index 0000000..a0533f8 --- /dev/null +++ b/chapter-2/ex-2.74.txt @@ -0,0 +1,59 @@ +This is a txt file because there's no sense in trying to make it into a proper +runnable scheme file, unless I go out of my way to make several examples of +data structure and record formats, complete with examples in order to actually +run these: + +a) Before any of the data records in the file itself, there should be an +identifier for what type of record it is, so each file should start with a +symbol, number or string that uniquely identifies the file structure/format, +for example: +european-division-format +(...) +(...) +... + +This piece of info should be in the same position in every file, so that a +uniform function, say (get-file-type file) could be used to find the proper +format. If it's not possible to change these division formats at all, then +either this change will be done while loading the file, or, the get-file-type +function will have to be more complicated. + +In any case, once we have solved the format marking issue using any kind of +method, the files and the records could be structured any how, as long as each +record has a unique identifier to the employee. + +These can then be searched with different functions for different formats, all +of which could be organized in a table, and called by a master function, which +will load the record, and then attach it with a tag, which will make record +processing easier too: + +(define (get-record name file) + (let ((file-type (get-file-type file))) + (attach-record-type file-type + ((get 'get-record file-type) name)))) + +We will also assume all these functions return nil if the record doesn't +exist, or a single record if it does. + +b) The way that we've written the get-record function, it doesn't matter how a +particular employee record is structured, because we tag it as the respective +file type ourselves, but of course it must contain the salary field, we must +also define a function which gets the record type, and the rest of the record: +get-record-type and get-record-body + +(define (get-salary record) + ((get 'get-salary (get-record-type record)) (get-record-body record))) + +c) We assume there's only one employee for the given name + +(define (find-employee-record name files) + (let ((returns (filter (lambda (record) (not (null? record))) + (map get-record files)))) + (if (null? returns) + nil + (car returns)))) + +d) All changes could be done in the new company's (or department's) package, +where they would simply define a new format name, add the format name tag to +their records, modify their get-record and get-salary functions appropriately, +and then add these to the updated global function table. diff --git a/chapter-2/ex-2.75.scm b/chapter-2/ex-2.75.scm new file mode 100644 index 0000000..204c9bc --- /dev/null +++ b/chapter-2/ex-2.75.scm @@ -0,0 +1,10 @@ +#lang sicp + +(define (make-from-real-imag r a) + (define (dispatch op) + (cond ((eq? op 'real-part) (* r (cos a))) + ((eq? op 'imag-part) (* r (sin a))) + ((eq? op 'magnitude) r) + ((eq? op 'angle) a) + (else (error "Unknown op: MAKE-FROM-MAG-ANG" op)))) + dispatch) \ No newline at end of file diff --git a/chapter-2/ex-2.76.txt b/chapter-2/ex-2.76.txt new file mode 100644 index 0000000..0afc2e7 --- /dev/null +++ b/chapter-2/ex-2.76.txt @@ -0,0 +1,32 @@ +Explicit dispatch: + New type: A new constructor(s), must be made for the new data type, which + will add the necessary fields and attach a new type tag. Each of the + functions for the type will need to have a new condition line to check for + the new type. + New op: The new op will be written in an explicit dispatch style to process + all of the preexisting types + +Data-directed style: + New type: A new package will be written, complete with all the necessary + functions to process the new type, they will then all be added to a new + row in the table + New op: Each existing package will have the op added to it, and will also + add it to a new column in the table + +Message-passing style: + New type: A new dispatch function will be created, with all of the lines + which exist in functions of previous types + New op: A new line is added into each of the dispatch functions of the + preexisting types + +If new operations are often added, you may prefer the explicit dispatch style, +since it involves only creating/modifying one place in the codebase. + +If new types are often added, you may instead prefer one of the other two +styles, since here, an addition of a new type is done in one place in the +code, while adding a new op requires changes in many places. + +That being said, the data-directed style has the extra advantage that it could +(in principle) be written in a way that's more organized for adding new +operations, since the table structure itself will work equally well in either +case, and it's more of a matter of code organization.