问题
In clojure, you can use map data structure or the keyword as a function to look up the map.
(let [m {:foo "bar"}]
(get m :foo) ; -> "bar"
(:foo m) ; -> "bar"
(m :foo)) ; -> "bar"
All of these expression returns the value "bar". Implementation wise, how is it possible to use map or the keyword as a function? Is this a special case built into a clojure interpreter, or is it something I could re-create with the language? What is actually happening under the hood?
回答1:
It's all done with normal java under the hood.
There is an interface called iFn that anything in Clojure that wants to be called as a function can implement. It's up to that thing to decide what to do when called.
- Keywords choose to look them selves up in a collection passed as the first argument.
- Maps choose to look up the argument passed as a key in themselves.
- Symbols also look them selves up in a collection. Much like keywords.
- Vars make a function call to whatever function they contain, using whatever arguments they where passed. And they use this same interface to do it.
回答2:
Just to show you how this is possible in any language that has first class functions -- 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
来源:https://stackoverflow.com/questions/43861384/how-clojure-map-and-keyword-could-be-a-function