[racket] First try with hashes in Racket

From: Neil Van Dyke (neil at neilvandyke.org)
Date: Mon Apr 2 03:37:52 EDT 2012

Joe Gilray wrote at 04/02/2012 12:44 AM:
> 1) [,,,]
> > (define ggg (make-hash (list '(1 4))))

Instead of  '(1 4) , which is a list, you want a pair, '(1 . 4)) .

If you'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're still pretty fundamental.  
Maybe try making some recursive procedures that build lists in different 
ways.  (Don't use Hashes, nor the "do" form, nor "map", nor any of the 
"for"-something forms.  Just you, recursive procedures, and "cons".)

> 2) My use of hash-has-key? feels clunky, Could I better use hash-ref? 
> especially here:
>         (if (hash-has-key? ht col)
>             (let ([colval (hash-ref ht col)]) ...

Good eye.  One way to do this is to use an optional argument to 
"hash-ref", to supply a default value that would never be returned if 
"col" were in "ht", 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 "if".

(let ((my-value-from-ht (hash-ref ht col #f)))
   (if my-value-from-ht
       [...do something with my-value-from-ht...]
       [...do something else...]))

Even better, you can do this with "cond" "=>", like so:

(cond ((hash-ref ht col #f)
        => (lambda (my-value-from-ht)
             [...do something with my-value-from-ht...]))
       (else [...do something else...]))

This code pattern with the "=>" thing looks cryptic to someone who's 
never seen it before, but it has a couple advantages: (1)  you can't 
accidentally use "my-value-from-ht" in the ``do something else'' part; 
and (2) your code might be cleaner, if ``do something else'' part can 
become additional clauses for the "cond", rather than just the "else" 

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

Neil V.


Posted on the users mailing list.