newLISP Fan Club

Forum => Anything else we might add? => Topic started by: Lutz on September 07, 2006, 06:37:34 AM

Title: A nifty definition for dictionaries / hashes
Post by: Lutz on September 07, 2006, 06:37:34 AM
Just discovered this nifty little definition to make dictionary/hash handling more comfortable with less typing:


(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
Title:
Post by: arunbear on October 16, 2006, 01:46:59 PM
Here it is as a module:



(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:

> (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)
Title:
Post by: arunbear on October 20, 2006, 02:35:13 PM
Hi Lutz, in Perl you can iterate through the (key, value) pairs of a dictionary without loading the whole keyset into memory



e.g.
my %dict = (name=> 'Aragorn' , alias=> 'Strider');
while(($key, $val) = each %dict)
{
    print "key = $key, value = $valn";
}


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.
Title:
Post by: Lutz on October 21, 2006, 01:46:17 AM
It is better to use just one function (and not inside a module) to define a Dictionary:



(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:


(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'


(context 'words "one" 1)
(context 'words "two" 2)
(context 'words "three" 3)


and then 'dotree' does not need exclude any symbols:


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

; will output

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






Lutz
Title:
Post by: cormullion on October 21, 2006, 07:49:56 AM
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 :-)):


(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:


(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:


(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...