Hi Neil and Racket-users,<div><br></div><div>Thanks for the good inputs.  Using your help I rewrote Euler #14:</div><div><br></div><div><div>; recursive function that returns the chain length of the passed argument</div><div>
; invoked as (collatz-length hash-table-instance n)</div><div>(define (collatz-length ht n)</div><div>  (define colval (hash-ref ht n #f))</div><div>  (unless colval</div><div>      (if (even? n) </div><div>          (set! colval (add1 (collatz-length ht (/ n 2))))</div>
<div>          (set! colval (add1 (collatz-length ht (add1 (* 3 n))))))</div><div>      (hash-set! ht n colval))</div><div>  colval)</div><div><br></div><div>; same function with a different syntax</div><div>(define (collatz-length2 ht n)</div>
<div>  (cond [(hash-ref ht n #f) =&gt; (lambda (colval) colval)]</div><div>        [else</div><div>         (define colval 0)</div><div>         (if (even? n) </div><div>             (set! colval (add1 (collatz-length2 ht (/ n 2))))</div>
<div>             (set! colval (add1 (collatz-length2 ht (add1 (* 3 n))))))</div><div>         (hash-set! ht n colval)</div><div>         colval]))</div><div><br></div><div>; ProjectEuler problem #14 </div><div>(define (euler14)</div>
<div>  (define ht (make-hash (list &#39;(1 . 1))))</div><div>  (define start-of-longest-chain 1)</div><div>  (define longest-chain 1)</div><div>  (for ([i (in-range 2 1000000)])</div><div>    (define col-len (collatz-length2 ht i))</div>
<div>    (when (&lt; longest-chain col-len)</div><div>      (set! longest-chain col-len)</div><div>      (set! start-of-longest-chain i)))</div><div>  (values start-of-longest-chain longest-chain))</div><div><br></div><b>The good news</b>: it is simpler, more idiomatic and faster</div>
<div><br></div><div><b>The bad news</b>: it still feels a little clunky.  It has a lot of imperative statements and the memoization in the hash table feels too much like a side-effect to me.</div><div><br></div><div>Any more help?</div>
<div><br></div><div>Thanks again!</div><div>-Joe</div><div><br><div class="gmail_quote">On Mon, Apr 2, 2012 at 12:37 AM, Neil Van Dyke <span dir="ltr">&lt;<a href="mailto:neil@neilvandyke.org">neil@neilvandyke.org</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Joe Gilray wrote at 04/02/2012 12:44 AM:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
1) [,,,]<div class="im"><br>
&gt; (define ggg (make-hash (list &#39;(1 4))))<br>
</div></blockquote>
<br>
Instead of  &#39;(1 4) , which is a list, you want a pair, &#39;(1 . 4)) .<br>
<br>
If you&#39;re not yet familiar with pairs, you might want to soon take a detour from the numerical Project Euler problems, to play a bit with making your own pairs and lists.  They&#39;re still pretty fundamental.  Maybe try making some recursive procedures that build lists in different ways.  (Don&#39;t use Hashes, nor the &quot;do&quot; form, nor &quot;map&quot;, nor any of the &quot;for&quot;-something forms.  Just you, recursive procedures, and &quot;cons&quot;.)<div class="im">
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
2) My use of hash-has-key? feels clunky, Could I better use hash-ref? especially here:<br>
<br>
        (if (hash-has-key? ht col)<br>
            (let ([colval (hash-ref ht col)]) ...<br>
</blockquote>
<br></div>
Good eye.  One way to do this is to use an optional argument to &quot;hash-ref&quot;, to supply a default value that would never be returned if &quot;col&quot; were in &quot;ht&quot;, and then to test against that default value.  When possible, use #f for this default value, so that it works nicely as a Boolean, such as with &quot;if&quot;.<br>

<br>
(let ((my-value-from-ht (hash-ref ht col #f)))<br>
  (if my-value-from-ht<br>
      [...do something with my-value-from-ht...]<br>
      [...do something else...]))<br>
<br>
Even better, you can do this with &quot;cond&quot; &quot;=&gt;&quot;, like so:<br>
<br>
(cond ((hash-ref ht col #f)<br>
       =&gt; (lambda (my-value-from-ht)<br>
            [...do something with my-value-from-ht...]))<br>
      (else [...do something else...]))<br>
<br>
This code pattern with the &quot;=&gt;&quot; thing looks cryptic to someone who&#39;s never seen it before, but it has a couple advantages: (1)  you can&#39;t accidentally use &quot;my-value-from-ht&quot; in the ``do something else&#39;&#39; part; and (2) your code might be cleaner, if ``do something else&#39;&#39; part can become additional clauses for the &quot;cond&quot;, rather than just the &quot;else&quot; clause.<br>

<br>
BTW, remember that &quot;(lambda (my-value-from-ht) ...)&quot; is just defining a procedure.  In the &quot;cond&quot; example above, you might be able to put a variable identifier for a procedure instead, so &quot;=&gt; (lambda ...)&quot; would look something like &quot;=&gt; my-proc&quot;, and somewhere else there would something like &quot;(define (my-proc val) ...)&quot;.  This is perhaps most useful when &quot;my-proc&quot; is more general than just that one &quot;cond&quot; clause.<br>

<br>
Neil V.<span class="HOEnZb"><font color="#888888"><br>
<br>
-- <br>
<a href="http://www.neilvandyke.org/" target="_blank">http://www.neilvandyke.org/</a><br>
<br>
____________________<br>
 Racket Users list:<br>
 <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/<u></u>users</a><br>
</font></span></blockquote></div><br></div>