<HTML><BODY style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space; "><BR><DIV><DIV>On Jan 20, 2007, at 2:20 PM, Danny Yoo wrote:</DIV><BR class="Apple-interchange-newline"><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">On Fri, 12 Jan 2007, Gregory Woodhouse wrote:</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV> <BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">I'm trying to write an evaluator in the style of SICP that I hope will be at least somewhat idiomatic.</DIV> </BLOCKQUOTE><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">Hi Greg,</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">Did you get any responses about this yet?<SPAN class="Apple-converted-space">  </SPAN></DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Actually, i thought the question hadn't made it to the list, but in a response to a separate posting, Matthew Flatt did show me how to use exn-message to display the message associated with the user exception:</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>;; safe-eval-strict: expression environment -&gt; value</DIV><DIV>  (define (safe-eval-strict input-val evn)</DIV><DIV>    (with-handlers</DIV><DIV>        ((exn:fail:user? (lambda (exn)</DIV><DIV>                           ((error-display-handler)</DIV><DIV>                            (exn-message exn)</DIV><DIV>                            exn))))</DIV><DIV>      (eval-strict input-val evn)))</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>I don't know how I missed it, because I had been searching for a way to display that message. I was able to find information on the error display handler, but that was the missing piece.</DIV><DIV><BR class="khtml-block-placeholder"></DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">Let's take a look.</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">... ok.<SPAN class="Apple-converted-space">  </SPAN>You may be able to avoid mutation here.<SPAN class="Apple-converted-space">  </SPAN>Let's look at a portion of the code:</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">     </SPAN>(let loop ()</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">       </SPAN>(with-handlers ...</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">         </SPAN>(printf "~a " main-prompt)</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">         </SPAN>(set! input-val (read))</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">         </SPAN>...))</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">Here is a let loop here with no variables being bound.<SPAN class="Apple-converted-space">  </SPAN>Every time through the loop, though, we're rebinding input-val.<SPAN class="Apple-converted-space">  </SPAN>This idea can be captured by making the input-val a part of the loop's variables:</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">     </SPAN>(let loop ([input-val (begin (printf "~a " main-prompt)</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">                                  </SPAN>(read))])</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">       </SPAN>(with-handlers (...)</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">         </SPAN>...))</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Yes, I ws trying to get the sequencing right and if I had only factored out read prompt, as you do below, then this would have been more obvious (I hope!)</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">Since we're going to be doing prompting quite a bit, we can then pull that prompting code up as a separate function.<SPAN class="Apple-converted-space">  </SPAN>I'll just call it READ-PROMPT for now:</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">  </SPAN>(define (read-prompt)</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">    </SPAN>(printf "~a " main-prompt)</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">    </SPAN>(read))</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Now, WHY I didn't do this...well, that's a mystery!</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">After this, the program looks a little bit more like:</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">...<BR></DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "></DIV> <BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">1. I don't want to break out of the loop when evaluating an expression like (/ 1 0) but instead report the error and then give the user an opportunity to enter another expression, leaving the environment intact. But, of course, I do want to break out of the loop in case of a programming error on my part, so my handler for exn:fail:user includes (loop) (where loop is the label in named let). I've never encountered code like this, and I wonder if it's even safe, much less idiomatic scheme.</DIV> </BLOCKQUOTE><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">It looks ok to me.<SPAN class="Apple-converted-space">  </SPAN>I think it can be better, though.<SPAN class="Apple-converted-space">  </SPAN>You could probably push the exception handling closer to the expression that's likely to cause havoc, the eval-strict function.</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Yes, I think I realized that after my next iteration, but getting the syntax right was a challenge.</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">Let's wrap eval-strict with a helper function SAFE-EVAL-STRICT, which we'll introduce within the LOOP definition.</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">    </SPAN>(let loop ([input-val (read-prompt)])</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">      </SPAN>(define (safe-eval-strict input-val evn)</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">        </SPAN>(with-handlers</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">            </SPAN>((exn:fail:user? (lambda (exn) (printf "Error!~n")</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">                               </SPAN>(loop (read-prompt)))))</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">          </SPAN>(eval-strict input-val env)))</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">      </SPAN>...)</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">....<BR></DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Ah! I'll bet that I didn't think of this because read-prompt is a function.</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">...<BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV> <BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">2. The second question involves the environment, which I anticipate storing as a list or perhaps a hash table.<SPAN class="Apple-converted-space">  </SPAN>To me, it makes more sense for the evaluator to return an updated environment as a value than to have it modify a global value.</DIV> </BLOCKQUOTE><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">Yes.<SPAN class="Apple-converted-space">  </SPAN>Also, just as in the case with INPUT-VAL, the environment is a value that's probably going to follow along in the looping: it might be appropriate to pass that around as well.<SPAN class="Apple-converted-space">  </SPAN>The structure of RUN can turn into:</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">  </SPAN>(define (run)</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">    </SPAN>(printf "~a (version ~a)~n" evaluator-name evaluator-version)</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">    </SPAN>(let loop ([input-val (read-prompt)]</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">               </SPAN>[env '()])</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">      </SPAN>...))</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>What I had been trying to do is maintain a kind of a "global" (or maybe top-level) environment, so that the user could type in a series of (define....) statements, so I don't really want a fresh environment for every evaluation. But this may be overloading the term environment a bit, because when evaluating an expression, you really do want a fresh environment. </DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">And now LOOP is actually starting to look a little bit like, well...</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><A href="http://download.plt-scheme.org/doc/360/html/r5rs/r5rs-Z-H-9.html#%_idx_600">http://download.plt-scheme.org/doc/360/html/r5rs/r5rs-Z-H-9.html#%_idx_600</A></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Hmm...This link doesn't work for me, but I'm sure I can chase it down.</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV> <BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">But it also seems that this style could involve a lot of unnecessary copying.</DIV> </BLOCKQUOTE><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">It really depends on how you define environments and how you extend them. It's possible to define them so that you take advantage of shared structure.<SPAN class="Apple-converted-space">  </SPAN>That is, rather than a mutable hashtable, you can choose a representation that reuses the existing environment structure.</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Actually, I started thinking about this after reading the first two sections of ch. 4 of SICP. That being said, my impression was that the environments in SICP were basically auxiliary data structures used during the evaluation of a single expression and then discarded. Maybe I need to take another look.</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Actually, there are two other reasons why I'm interested in avoiding copying -- One is that a potential application I have in mind involves potentially huge numbers of bindings being "in effect" (tens of thousands), a small subset of which may actually be uzed in any one computation. The other is that I'm thinking about sharing some of these bindings between different threads. (Yes, I know that doesn't sound very functional!)  To be a bit less mysterious about it, I've been working for some years on a MUMPS based medical information system known as VistA.  I've been unhappy about the lack of clear semantics for the system, but then I re(?)-discovered Scheme by picking up a copy of "The Little Schemer", and I was, well, hooked.</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "></DIV> </BLOCKQUOTE><BR></DIV><DIV>As always, thank you for your help!</DIV><BR><DIV> <SPAN class="Apple-style-span" style="border-collapse: separate; border-spacing: 0px 0px; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: auto; -khtml-text-decorations-in-effect: none; text-indent: 0px; -apple-text-size-adjust: auto; text-transform: none; orphans: 2; white-space: normal; widows: 2; word-spacing: 0px; "><SPAN class="Apple-style-span" style="border-collapse: separate; border-spacing: 0px 0px; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: auto; -khtml-text-decorations-in-effect: none; text-indent: 0px; -apple-text-size-adjust: auto; text-transform: none; orphans: 2; white-space: normal; widows: 2; word-spacing: 0px; "><DIV>Gregory Woodhouse</DIV><DIV><A href="mailto:gregory.woodhouse@sbcglobal.net">gregory.woodhouse@sbcglobal.net</A></DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>There's a fine line between optimization</DIV><DIV>and not being stupid. -- R. Kent Dybvig</DIV><DIV><BR class="khtml-block-placeholder"></DIV><BR class="Apple-interchange-newline"></SPAN></SPAN> </DIV><BR></BODY></HTML>