How clojure map and keyword can be a function

In clojure, you can use the map data structure or keyword as a function to find the map.

(let [m {:foo "bar"}]
  (get m :foo) ; -> "bar"
  (:foo m)     ; -> "bar"
  (m :foo))    ; -> "bar"

      

All of these expressions return the value "bar". Implementation wisely, how can you use a map or a keyword as a function? Is this a special case built into the clojure interpreter, or is it something I could recreate with the language? What's really going on under the hood?

+2


source to share


2 answers


All this is done with regular java under the hood.

There is an iFn interface that can implement anything in Clojure that wants to be called as a function. It depends on this thing to decide what to do when called.



  • Keywords are selected to search for in the collection passed as the first argument.
  • Maps are chosen to search for an argument passed as a key in itself.
  • Symbols also appear on their own in the collection. Very similar to keywords.
  • Vars makes a function call to whatever function they contain using whatever arguments they passed. And they use the same interface for this.
+4


source


Just to show you how this is possible in any language that has first class functions - the JavaScript example below; run it to see the results!



const map = x => a =>
  a === undefined ? x : a(map(x))

const get = m => a =>
  a(m)

const accessor = k => m =>
  m()[k]

// make accessor
const foo = accessor('foo')

// make map
let m = map({foo: 'bar'})

// test expressions
// get applied to map and accessor:
console.log(get (m) (foo)) // bar

// accessor applied to map:
console.log(foo (m))       // bar

// map applied to accessor:
console.log(m (foo))       // bar
      

Run codeHide result


+2


source







All Articles