;;; 6.945 Problem Set #3 Comments ;;; 02/25/2009 ;;; Bryan Newbold Note: I loaded the attached file bnewbold_work.scm load.scm and load-general.scm after everything else, if that helps you run things! Problem 3.1 ------------------------ Ugh! This was super tricky because compound-procedure? and vector? are not mutually exclusive... this took hours to figure out, the solution of writing my own predicate was easy once I knew what the problem was. Of course rereading the hints that were emailed out I can see where I went wrong. Stupid! I should have just asked! [see bnewbold_work.scm] Problem 3.2 ------------------------ It would probably make more sense to have some symbols and functions as tagged lists with 'self-evaluating-symbol and 'self-evaluating-function or some such, but I just went with it. I only did binary operations because I got the comment "Don't worry about arity!" on my last problem set ;) For the literal-functions I went a bit over board and only allowed single character names and required registration with declare-literal-function. [see bnewbold_work.scm] Problem 3.3 ------------------------ a. KONS is good enough on it's own because it creates an actual list that can be understood by CAR and CDR. The final un-delaying and memoization logic in eval and apply are what are doing the heavy lifting. CAR and CDR just choose which path evaluation should continue down. b. We have to delay the integrand call even further than kons does; fortunately we have good syntax for this now! [see bnewbold_work.scm] Problem 3.4 ------------------------ a. I will answer with a quick program (see code). [see bnewbold_work.scm] b. CONS wants a list as it's second argument (at least most schemes, MIT/GNU seems a little looser?), (dy lazy memo) would have to get checked sooner rather than later. c. KONS creates some real headache lexical scoping issues which could be hard to debug. It's prevalent use could also effectively tie up every potential object created, blocking garbage collection. Problem 3.5 ------------------------ I implemented crude profiling: after evaluating an expression, a table can be printed out showing the number of procedure and primitive calls. A pair of eq-based hash tables are used to store the running call counts. Performance does seem to be negatively effected (eg (fib 12) took 10+ seconds using a very crude algorithm vs. almost instant in the top level repl), but that might just be the generic dispatch stuff. I put in code for an enable/disable flag but i'm not sure it's even necessary. The most-needed-change is to print just the primitive/compound procedure name symbols, not their string representations. I wanted to make sure that the same procedure by different names would be counted together, but in the end it looks like a big mess. My scmutils-enabled version of MIT Scheme has a procedure-name method that does the trick, but it doesn't seem to be in the default distribution so I left it out. [see bnewbold_work.scm]