newLISP Fan Club

Forum => newLISP in the real world => Topic started by: hartrock on June 30, 2015, 04:37:16 AM

Title: [bof?] ++ nil val in hashmap fails -> feature
Post by: hartrock on June 30, 2015, 04:37:16 AM

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.
Title: Re: [bof?] ++ nil val in hashmap fails
Post by: xytroxon on June 30, 2015, 08:52:20 AM
Just use this direct form, no need for (new Tree 'hm), it is created auto-magically ;o)



> (++ iter:baz)
> 1


-- xytroxon
Title: Re: [bof?] ++ nil val in hashmap fails
Post by: TedWalther on June 30, 2015, 11:08:18 PM
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.
Title: Re: [bof?] ++ nil val in hashmap fails
Post by: hartrock on July 01, 2015, 06:14:47 PM
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.
Title: Re: [bof?] ++ nil val in hashmap fails
Post by: TedWalther on July 01, 2015, 06:31:57 PM
Yes, the way I do it is to override the default functor.



(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?
Title: Re: [bof?] ++ nil val in hashmap fails
Post by: xytroxon on July 01, 2015, 11:42:59 PM
You could also use newLISP eval-string.



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

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



-- xytroxon