通过关键字查找惯用语的clojure地图

gre*_*ier 30 clojure

假设我有一个使用关键字作为其键的clojure地图:

(def my-car {:color "candy-apple red" :horsepower 450})
Run Code Online (Sandbox Code Playgroud)

我知道我可以通过使用关键字或map作为函数而另一个作为参数来查找与关键字关联的值:

(my-car :color)
; => "candy-apple red"
(:color my-car)
; => "candy-apple red"
Run Code Online (Sandbox Code Playgroud)

我意识到这两种形式在某些情况下都可以派上用场,但是其中一种形式被认为是如上所示的直接使用的惯用语?

ama*_*loy 42

(:color my-car)是相当标准的.这有几个原因,我不会涉及所有这些原因.但这是一个例子.

因为:color是一个常量,而my-car不是,热点可以完全内联动态调度color.invoke(m),它无法做到m.invoke(color)(在某些java伪代码中).

如果my-car碰巧有时候是带有color字段而不是普通地图的记录,那就更好了:clojure编译器可以发出代码来检查"嘿,如果my-car是CarType的实例,那么只返回my-car.color;否则做所有复杂,慢, hashmap查找."

  • 对我来说,最令人信服的原因是:(:color nil)返回nil,而(nil:color)抛出异常. (24认同)
  • @ user100464但是可以对另一个表格做出相同的论证!如果你正在动态访问键,`({:color"red"} nil)`返回`nil`而``(nil {:color"red"})`抛出异常. (2认同)

kot*_*rak 24

图书馆编码标准:

  • 你能解释"类似对象的地图"和"类似集合的地图"之间的区别吗? (2认同)

Cha*_*ann 8

我列出了支持和反对这两种形式的论据清单.(编辑:添加第三个选项 - (get map :key)这是我最喜欢的,尽管有点冗长)

(:键映射)的参数

1)要求编码标准

http://dev.clojure.org/display/community/Library+Coding+Standards

2)当地图为零时仍然有效

> (:a nil)
  nil
> (nil :a)
  ERROR: can't call nil
Run Code Online (Sandbox Code Playgroud)

---反驳---如果关键可能是零,其他形式更好

> ({:a "b"} nil)
  nil
> (nil {:a "b"})
  ERROR: can't call nil
Run Code Online (Sandbox Code Playgroud)

3)更好地用于对象集合的线程化和映射

(-> my-map
  :alpha
  fn-on-alpha
  :beta
  fn-on-beta
  :gamma

> (def map-collection '({:key "values"} {:key "in"} {:key "collection"}))
> (map :key map-collection)
  ("values" "in" "collection")
Run Code Online (Sandbox Code Playgroud)

---反驳 - 线程的代码结构与平常不同,因此在需要时可以应用不同的惯用倾向进行地图访问

4)潜在的优化效益?(需要验证)

参数(map:key)

1)当key为非关键字或nil时,不会抛出错误

> ({:a "b"} nil)
  nil
> (nil {:a "b"})
  ERROR: can't call nil
> ({"a" "b"} "a")
  "b"
> ("a" {"a" "b"})
  ERROR: string cannot be cast to IFn
Run Code Online (Sandbox Code Playgroud)

2)在Clojure中与列表访问的一致性

> ([:a :b :c] 1)
  :b
> (1 [:a :b :c])
  ERROR: long cannot be cast to IFn
Run Code Online (Sandbox Code Playgroud)

3)与其他形式的对象访问相似

java>         my_obj  .alpha  .beta  .gamma  .delta
clj >     ((((my-map  :alpha) :beta) :gamma) :delta)
clj > (get-in my-map [:alpha  :beta  :gamma  :delta])
cljs> (aget   js-obj  "alpha" "beta" "gamma" "delta")
Run Code Online (Sandbox Code Playgroud)

4)从同一个地图访问多个键时的对齐(单独的行)

> (my-func
    (my-map :un)
    (my-map :deux)
    (my-map :trois)
    (my-map :quatre)
    (my-map :cinq))
> (my-func
    (:un my-map)
    (:deux my-map)
    (:trois my-map)
    (:quatre my-map)
    (:cinq my-map))
Run Code Online (Sandbox Code Playgroud)

---反驳 - 当从多个地图访问相同的密钥时,对齐更糟糕

> (my-func
    (:key map-un)
    (:key map-deux)
    (:key map-trois)
    (:key map-quatre)
    (:key map-cinq)
> (my-func
    (map-un :key)
    (map-deux :key)
    (map-trois :key)
    (map-quatre :key)
    (map-cinq :key)
Run Code Online (Sandbox Code Playgroud)

(get map:key)的参数

1)如果arg1是map/vector/nil且arg2是key/index/nil,则不会导致错误

> (get nil :a)
  nil
> (get nil nil)
  nil
> (get {:a "b"} nil)
  nil
> (get {:a "b"} :q)
  nil
> (get [:a :b :c] nil)
  nil
> (get [:a :b :c] 5)
  nil
Run Code Online (Sandbox Code Playgroud)

2)形式与其他Clojure功能的一致性

> (get {:a "b"} :a)
  :b
> (contains? {:a "b"} :a)
  true
> (nth [:a :b :c] 1)
  :b
> (conj [:a :b] :c)
  [:a :b :c]
Run Code Online (Sandbox Code Playgroud)

3)地图优先的协调优势

> (my-func
    (get my-map :un)
    (get my-map :deux)
    (get my-map :trois)
    (get my-map :quatre)
    (get my-map :cinq))
Run Code Online (Sandbox Code Playgroud)

4)Get-in可以通过一次调用用于嵌套访问

> (get-in my-map [:alpha  :beta  :gamma  :delta])
> (aget   js-obj  "alpha" "beta" "gamma" "delta")
Run Code Online (Sandbox Code Playgroud)

来源:在http://tryclj.com/上测试