3 ms·
A thing I have noted is that every time I code in Java I feel handicapped for the lack of proper syntactic sugar for maps (I mostly code in JS/Python where maps
by amix 18y ago
A thing I have noted is that every time I code in Java I feel handicapped for the lack of proper syntactic sugar for maps (I mostly code in JS/Python where maps are used for _all_ kinds of things (and hacks)). Anyway, great post.
- silentbicycle 18y agoDitto with Lisp, actually. Maybe something good could be done with read macros, but |(table 'key) -> (lookup table 'key) just doesn't do it for me. Any ideas? Lisp has alists, but (as noted elsewhere) they search in linear time. Python, Lua, and JS all have syntactic sugar for maps, and I think it makes a really big difference. They're quite versatile. Lua's table.key -> table["key"] sugar for all string keys is particularly nice.
- jimbokun 18y agoClojure has squiggly brace syntax for map literals, and multiple shortcuts for map lookups. E.g. both (map :key) or (:key map) return the value for :key in map (I think). Arc has similar syntax shortcuts for hashes (but sticks with parentheses): http://ycombinator.com/arc/tut.txt http://ycombinator.com/arc/tut.txt arc> (let h (obj x 1 y 2) (h 'y)) 2
- gcv 18y agoDon't know if this will do what you want, but these two reader macros add syntactic sugar for Common Lisp's aref and gethash forms. You should put these definitions in an eval-when. Disclaimer: I haven't used these in a while (not programming in Lisp at the moment, alas), so they may have some limitations which I have forgotten. (set-macro-character #\] (get-macro-character #\))) ;; Array syntax: [array-name array-references] is equivalent to ;; (aref array-name array-references) (set-macro-character #\[ #'(lambda (stream char) (declare (ignore char)) (destructuring-bind (array-name &rest array-references) (read-delimited-list #\] stream t) `(aref ,array-name ,@array-references)))) ;; Hash table syntax: #[hash-table hash-key &optional default] is ;; equivalent to (gethash hash-key hash-table &optional default) (set-dispatch-macro-character #\# #\[ #'(lambda (stream subchar arg) (declare (ignore subchar arg)) (destructuring-bind (hash-name hash-key &optional (default nil)) (read-delimited-list #\] stream t) `(gethash ,hash-key ,hash-name ,default))))
- silentbicycle 18y agoActually, would there be any real problem with keeping the map in a closure, and passing around a function that gets (or, with a second optional argument, sets) the value for a given key? (h 'key) and (h 'key 'new-val) That's not too bad syntax-wise. Or, taking a cue from actor languages: (h 'get 'key) and (h 'set 'key 'new-val)
- amix 18y agoJavaScript also supports obj.id == obj["id"]. Python on the other hand does not support this (which is a shame, because obj.id is more readeable than obj['id']). But it's possible to hack this on dicts ( http://pastie.org/296506 http://pastie.org/296506 ). Syntactic sugar in languages is quite convenient, especially for things that are used a lot. Thought a lot of syntactic sugar (like in Perl) can ruin a language and it's readability.
- silentbicycle 18y agoI think syntactic sugar can make some things so convenient that people find novel uses for them. The ranged slicing operations in Python are really nice, for example; so is templating Lisp code with ` , ,@ once you get used to it. Adding SS also adds to what you need to remember to use the language effectively (and to read other peoples' code), but a little bit of syntactic sugar can go a really long way.
- jimbokun 18y agoThis is a key failing of Java, but you can make it hurt a little less with syntax like: Map<String,Integer> map = new HashMap<String,Integer>() {{ put("x", 1); put("y", 2); }} This abuses the fact that a brace after a constructor invocation indicates the creation of an anonymous inner subclass, and the second brace indicates code to be executed at instantiation time. So this "double brace initialization" has become a Java idiom. Still pretty awful, I know. I'm not sure if anyone has been able to use generics and varargs to create a map generating static function, but it might be possible. Something like: Map<String,Object> m = map("x", 1, "y", 2); I think the trouble is with automatically extracting the key value types from the varargs array. I think I have seen the approach: Map<String,Object> m = map(kv("x", 1), kv("y", 2)); where kv would just create a key value pair. That way you can make the generics inference come out right. All of this does make a pretty good argument for Python, Ruby, Javascript, etc. UPDATE: just found this: http://nicolas.lehuen.com/index.php/post/2006/10/07/113-java-map-literals-continued http://nicolas.lehuen.com/index.php/post/2006/10/07/113-java... // Example usage : import static Literals.map; Map<String,Integer> example = map("hello",1).map("world",2).map("!",3); Pick your poison.
- michaelneale 18y agoCheck out: http://gleichmann.wordpress.com/2008/01/13/building-your-own-literals-in-java-lists-and-arrays/ http://gleichmann.wordpress.com/2008/01/13/building-your-own... for more tricks with varargs, generics and static imports to "pimp" things up a bit.
- JulianMorrison 18y agoAlso Scala: val m = Map('name -> "Bob", 'age -> 30, 'color -> Colors.Red)