[patch] set setter for array-ref to array-set!

Jamison Hope jrh@theptrgroup.com
Sat Mar 7 06:30:00 GMT 2015


On Mar 6, 2015, at 2:15 PM, Per Bothner <per@bothner.com> wrote:

> On 03/04/2015 11:54 PM, Jamison Hope wrote:
>> What do you think about doing similar things for hash tables?
>> 
>> This works (even though RNRS hashtable-ref takes a third argument):
>> 
>> (import (rnrs hashtables))
>> (set! (setter hashtable-ref) hashtable-set!)
>> 
>> (define h (make-eq-hashtable))
>> (set! (hashtable-ref h 'year) 2015)
>> h => {year=2015}
> 
> It's a little ugly because of the weirdness with the default parameter -
> i.e. that (hashtable-ref h 'year) is not a valid call, even after the set!.
> Plus it doesn't make the code any more compact or readable.

The mandatory default parameter does make it weird, yeah.  It's kind of
unfortunate that it breaks symmetry with the other TYPE-ref / TYPE-set!
pairs.

>> It seems like function call notation would be nice for java.util.Map
>> instances, too:
>> 
>> (set! (h k) v) => (h:put k v)
>> (h k) => (h:get k)
>> 
>> Thoughts?  Part of a GSoC project, perhaps?
> 
> Too small for a GSoC project.

That's why I said "part of".  Or perhaps as a small introductory project
for a student who wants to get a taste of Kawa hacking before the summer.

> Using function call notation seems reasonable, but I think I had some concerns
> I can't quite remember.  One minor issue is the "conflict" with colon notation
> when it comes to string or symbol keys.  Should we prefer:
>  (my-table "foo")
> or:
>  my-table:foo
> That issue is probably a distraction.

My vote would be for (my-table "foo"), since I tend to think of hash tables
as being like arrays with arbitrary objects as indices.  It would work with
non-string/symbol keys, too, and with non-literal keys.  If my-table is the
Map {1=I, 5=V, 10=X}, then

(let ((a 5)) (my-table a)) => "V"

Also note that C++ std::unordered_map uses operator[] for array-like syntax,
as in
 map["key"] = value;

> Another issue to note: If we support function call notation, I'd like
> it to work for any java.util.Map, not just those returned by make-hash-table
> or make-hashtable.

Yes, absolutely.

> Finally there is the issue of defaults.  If a key isn't in my-table what should
> be the result of this?
>  (my-table key)
> Arguably this should throw an exception as key isn't in its domain.
> The other alternative is to return #!null, for simplicity and compatibility
> with the Java Map interface.

I think I would prefer for it to return #!null.  Now that Kawa treats #!null
as false, this would not only be compatible with the Java Map API, it would
also be consistent with how assoc works for association lists and SRFI-1's
find works for regular lists.

> My inclination would be to throw an exception, and also introduce:
>  (my-table key default: default-value)
> If default-value is #!null this should be compiled to a call to the Map get routine.
> If default-value is non#!null it should be compiled to the getOrDefault method
> if either the target is Java 8 or if my-table is known to be a sub-class of
> AbstractHashTable; otherwise we call a static helper method.
> 
> (Of course if my-table isn't known to be a Map at compile-time we have to check
> if it's a Map at run-time.)

I like that.  Are there any other examples of having a keyword in function-call
notation (other than actual functions)?  Maybe also support a throw:

(my-table key throw: bool)
If bool is true, then throw an exception if key is not in my-table.
If bool is false, same as (my-table:get key) (i.e. the value or #!null).


It might also be nice to have a syntax for hash table literals.  Racket has
#hash(), #hasheqv(), and #hasheq(), we could do something like that, maybe with
#{} as sugar for #hash()?


So putting all these ideas together, we might have something like:

(define h1 #{(year . 2015) (bttf . ii) (car . delorean)})

(map h1 '(car truck year)) => (delorean #!null 2015)

(define h2 (java.util.HashMap))
(set! (h2 'apple) "red")

(cond ((h2 'apple) => (lambda (c) &{apples are &[c]}))) => "apples are red"

(h2 'banana default: "yellow") => "yellow"
(h2 'orange throw: #t) => exception

--
Jamison Hope
The PTR Group
www.theptrgroup.com





More information about the Kawa mailing list