Page 1 of 1

[bof?] ++ nil val in hashmap fails -> feature

PostPosted: Tue Jun 30, 2015 11:37 am
by hartrock
Code: Select all
sr@mad:~$ newlisp
newLISP v.10.6.2 64-bit on Linux IPv4/6 UTF-8 libffi, options: newlisp -h

> (new Tree 'hm)
hm
> (hm "foo" (+ (or $it 0) 1))
1
> (++ (hm "foo"))
2
> ; OK, but:
> (++ (hm "bar"))

ERR: invalid parameter in function ++
>

Is this a bug, or is there a reason for this behavior?

It would be nice, if checking for nil could be avoided here.

Re: [bof?] ++ nil val in hashmap fails

PostPosted: Tue Jun 30, 2015 3:52 pm
by xytroxon
Just use this direct form, no need for (new Tree 'hm), it is created auto-magically ;o)

Code: Select all
> (++ iter:baz)
> 1


-- xytroxon

Re: [bof?] ++ nil val in hashmap fails

PostPosted: Wed Jul 01, 2015 6:08 am
by TedWalther
That is a surprising (until you think about it) difference in behavior.

(ctx "bar") returns a setf-able place, or nil. but referencing an unbound symbol always returns a setf-able place.

Re: [bof?] ++ nil val in hashmap fails

PostPosted: Thu Jul 02, 2015 1:14 am
by hartrock
Thanks for clearifying the difference between symbols and Tree or (ctxt "someKey") hashmap values.

My usecase is a state machine modeled by a hash map with string state IDs as keys, where I want to count state changes. So I have two Tree hash maps: one for the states, another for the counters; both with same string keys.
Best solution I think is to init the corresponding counter hash map val with 0, just with adding a new state to state machine hashmap (which will be done by a func); so above check for nil can be omitted.

Using symbol keys for states like sm:someState would be possible, too; but then there could be a conflict with funcs like sm:add-state, located in same context as state hashmap.

Re: [bof?] ++ nil val in hashmap fails

PostPosted: Thu Jul 02, 2015 1:31 am
by TedWalther
Yes, the way I do it is to override the default functor.

Code: Select all
(context 'ctx)
;; override default functor
(define (ctx:ctx a)
  (let (b (sym (string "_" a)))
    (if (args)
      (set b (first (args)))                   ; set the value
      (if (eval b) (eval b) (set b 0))))) ; retrieve the value
(context MAIN)


Now references to an unbound symbol will be automatically set to 0, and setf-able. With this default functor, now your original code, (++ (hm "foo")) will properly return "1", as you expected.

This seems like it might be a useful design pattern, perhaps suitable for the CodePatterns document if it isn't in there already; I similarly changed the default functor to use a database as a backing store, if a symbol is unbound, it looks it up with SQL and stores it client-side, references thereafter are very speedy.

The way contexts work in newlisp, with this idiom, you still get all the speed advantages of redblack trees that contexts have. Right Lutz?

Re: [bof?] ++ nil val in hashmap fails

PostPosted: Thu Jul 02, 2015 6:42 am
by xytroxon
You could also use newLISP eval-string.

Code: Select all
> (setq id "bar")
> (eval-string (string "(++ hm:" id ")")))
> 1

> (define (++hm id) (eval-string (string "(++ hm:" id ")")))
> (++hm "foo"))
> 1



-- xytroxon