A nifty definition for dictionaries / hashes

For the Compleat Fan
Locked
Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

A nifty definition for dictionaries / hashes

Post by Lutz »

Just discovered this nifty little definition to make dictionary/hash handling more comfortable with less typing:

Code: Select all

(define (myhash:myhash key value) 
   (if value 
       (context 'myhash key value) 
       (context 'myhash key)))
       
(myhash "hello" 123)

(myhash "hello")    => 123
Lutz

ps: also added to the manual

arunbear
Posts: 4
Joined: Wed Aug 09, 2006 10:02 am

Post by arunbear »

Here it is as a module:

Code: Select all

(context 'Dict)

(define (Dict:Dict key value)
   (if value
       (context (context) key value)
       (context (context) key)))

(define (get key) (Dict key))
(define (put key value) (Dict key value))

(define (keys)
    (map name (difference
                (symbols)
                (cons
                    (sym (string (context)) (context))
                    '(Dict get put keys key value values)))))

(define (values)
    (map get (keys)))

(context MAIN)
Usage:

Code: Select all

> (new Dict 'd)
d
> (d "name" "fred")
"fred"
> (d "age" 10)
10
> (d:put "salary" 10000)
10000
> (d:get "salary")
10000
> (d:keys)
("age" "name" "salary")
> (d:values)
(10 "fred" 10000)

arunbear
Posts: 4
Joined: Wed Aug 09, 2006 10:02 am

Post by arunbear »

Hi Lutz, in Perl you can iterate through the (key, value) pairs of a dictionary without loading the whole keyset into memory

e.g.

Code: Select all

my %dict = (name=> 'Aragorn' , alias=> 'Strider');
while(($key, $val) = each %dict) 
{
    print "key = $key, value = $val\n";
}
Python and Ruby have similar constructs.

How can this be done in newlisp? dotree would visit all symbols in the underlying context, even those that are not keys of the dictionary.

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

It is better to use just one function (and not inside a module) to define a Dictionary:

Code: Select all

(define (words:words key value)
   (if value
       (context 'words key value)
       (context 'words key)))

> (words "one" 1)
1
> (words "two" 2)
2
> (words "three" 3)
3
> (words "four" 4)
4
> 
now there is only one symbol to exclude containing the function definition:

Code: Select all

(dotree (w words) 
    (if (not (lambda? (eval w))) 
        (println (name w) "=>" (eval w))))

; will output

four=>4
one=>1
three=>3
two=>2
I think in practice the best is always to define dictionaries explicitely using 'context'

Code: Select all

(context 'words "one" 1)
(context 'words "two" 2)
(context 'words "three" 3)
and then 'dotree' does not need exclude any symbols:

Code: Select all

(dotree (w words) 
        (println (name w) "=>" (eval w))))

; will output

four=>4
one=>1
three=>3
two=>2


Lutz

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

Is this the sort of thing that people can do with macros? I don't know enough about macros yet, but perhaps it could provide you with the more selective route through a context's symbols:

This sort of thing (warning: macro-newbie at work :-)):

Code: Select all

(define-macro (do-keys)
	(letex (v (first (first (args))))
	(dotree (v (last (first (args))))
		(if (not (lambda? (eval v))) 
			(map eval (rest (args)))))))
which might then render arunbear's Dict example module like this:

Code: Select all

(do-keys (s d)
	(println s " " (eval s)))

d:age 10
d:key nil
d:name fred
d:salary 10000
d:value nil
compared with this:

Code: Select all

(dotree (s d)
	(println s " " (eval s)))

d:Dict (lambda (d:key d:value) 
 (if d:value 
  (context (context) d:key d:value) 
  (context (context) d:key)))
d:age 10
d:d (lambda (d:key d:value) 
 (if d:value 
  (context (context) d:key d:value) 
...
But as I said, I'm still trying to understand this stuff...

Locked