Here's a different comparison of let-vs-internal-define, using your code.

Your internal define example (hopefully whitespace doesn't get mangled by however you're reading this message):

(define (partial-tree elts n)
  (cond [(= n 0)
         (values EMPTY-TREE elts)]
        [else
         (define left-size (quotient (- n 1) 2))
         (define-values (left-tree non-left-elts)
           (partial-tree elts left-size))

         (define this-entry (first non-left-elts))

         (define right-size (- n (+ left-size 1)))
         (define-values (right-tree remaining-elts)
           (partial-tree (rest non-left-elts) right-size))

         (values (tree this-entry left-tree right-tree)
                 remaining-elts)]))

Simply transliterated to a let syntax, and with a more readable zero test (which you'd need a "begin" to do with internal define, incidentally):

(define (partial-tree elts n)
  (if (zero? n)
      (values empty-tree elts)
      (let* ((left-size                   (quotient (- n 1) 2))
             ((left-tree non-left-elts)   (partial-tree elts left-size))
             (this-entry                  (first non-left-elts))
             (right-size                  (- n (+ left-size 1)))
((right-tree remaining-elts) (partial-tree (rest non-left-elts)
                                                        right-size)))
        (values (tree this-entry left-tree right-tree)
                remaining-elts))))

Which is better is subjective, but in the "let" example, I can instantly see that there is an ordered sequence of bindings, and what the names are, in a visually regular format.

In the define example, I have to first see that there's an extent consisting solely of a bunch of define forms in it with no non-define code hidden, then look for the names, then examine the code for ordering (e.g., are there recursive/forward references?), and tread carefully so that I don't get scrod by a toplevel-like idiosyncrasy.

This is a simple example. I think let can sometimes win slightly more when the examples get more complicated. (And there are other examples, such as with huge nested definitions, in which I sometimes think internal define might be more readable, but overall I usually find let to be more readable.)

In summary: You can make "let*-values" be unnecessarily awkward, and you can cherry-pick throwaway problem set code from SICP, and you can tell people they have to type ugly square brackets when they don't, but the people of Let will not be intimidated! Long live Let! :)

Neil V.

____________________
 Racket Users list:
 http://lists.racket-lang.org/users

Reply via email to