5 ms·
And hashtable lookups are possible by just function-calling the table itself with the key: => ({ :foo 1 :bar 2 } :foo) 1 the common pattern of defaulting
by pmjordan 18y ago
And hashtable lookups are possible by just function-calling the table itself with the key:
=> ({ :foo 1 :bar 2 } :foo)
1
the common pattern of defaulting to a value if the key isn't found is easy too:
=> ({ :foo 1 :bar 2 } :baz 4)
4
The above is a hash map, #{ ... } creates a hash set which otherwise has similar semantics. Sets, being function-callable, can be used directly for checking if something is one of a bunch of values:
(if (#{301 302 303 307} response-code)
; we've been redirected
Maps and sets (you also have sorted maps and sets and a compact struct-map, all of which have identical semantics as the hash variants where appropriate) can additionally be used with most functions accepting a seq (list) or can be converted to a list explicitly using the seq function.
Basically, maps and sets really are first-class citizens in clojure. Some of the flexibility is down to the fact that Clojure is a Lisp-1: these features are therefore hard to replicate in CL. (and yes, hash tables also bothered me somewhat in CL, altough other things probably bothered me more)
- whacked_new 18y agoSomething I find strange about hashes in Clojure, is that you can access them using the key as a function. So instead of ({ :foo 1 :bar 2 } :foo) ;; => 1 You get the equivalent by doing (:foo { :foo 1 :bar 2 }) ;; => 1 For default values: (:baz { :foo 1 :bar 2 } 3) ;; => 3 I vaguely remember this is because keys act as functions, and hashes act as functions as well. Out of habit and similarity to other languages, I never use the key-first notation, nor can I see where it is better to use it.
- tokipin 18y agoit's likely for usage in higher-order functions. i haven't used clojure but i assume you can do something like this: (map :foo hashofhashes) which would get the element :foo of every hash in hashofhashes
- pmjordan 18y agoThat's another good point, although the alternative isn't much longer: (map #(% :foo) hashofhashes) or if % has a chance of being nil: (map #(get % :foo) hashofhashes)
- pmjordan 18y agoYep, the funcall semantics of symbols and keywords are to forward the symbol and key itself along with the arguments to the get function. I do sometimes use this notation, mostly when: - the map could be nil. (get nil :foo) and (:foo nil) will return nil, but (nil :foo) will throw an exception. - dealing with struct-maps, where the key can effectively be seen as an accessor function. (cf structs in CL) - (rarely) when the expression evaluating to the map is long and complex. A keyword in the function position (a) makes it clear that what follows must be a map or set and (b) you don't have to start counting parens.
- jrockway 18y agoClojure definitely has nice data structures. Does anyone do this sort of hash-table-as-function thing in Scheme?