Page 1 of 1
A nifty definition for dictionaries / hashes
Posted: Thu Sep 07, 2006 1:37 pm
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
Posted: Mon Oct 16, 2006 8:46 pm
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)
Posted: Fri Oct 20, 2006 9:35 pm
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.
Posted: Sat Oct 21, 2006 8:46 am
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
Posted: Sat Oct 21, 2006 2:49 pm
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...