【问题标题】:Return a map from within a Clojure function从 Clojure 函数中返回一个映射
【发布时间】:2015-07-21 08:07:17
【问题描述】:

我已经学习 Clojure 几个星期了。我知道数据结构和一些功能的基础知识。 (我正在阅读 Clojure 编程书)。

我坚持以下。我正在编写一个函数,它将小写提供的地图的键。

(defn lower-case-map [m]
  (def lm {})
  (doseq [k (keys m)]
    (assoc lm (str/lower-case k) (m k))))

这是我想要的,但我如何返回地图? def 正确吗?

我知道这行得通

(defn lower-case-map [m]
  (assoc {} :a 1))

但上面的doseq 似乎造成了问题。

【问题讨论】:

  • 你不应该在 Clojure 的函数内部使用defdef 只能在顶层使用。改用let 来定义局部变量。

标签: clojure


【解决方案1】:

在函数体中,您应该使用 let 定义局部变量,但这段代码看起来很像您试图将其转变为命令式思维方式(def tempvar = new Map; foreach k,v in m do tempvar[k.toLower] = v; return tempvar)。另请注意,doseq 的文档明确指出,它返回nil

函数式方法是在输入上使用mapreduce 直接返回结果。例如。 map 的简单方法(迭代元素序列,解构键/值元组,发出修改后的元组,将它们转回映射):

user=> (into {} (map (fn [[k v]] [(.toLowerCase k) v]) {"A" 1 "B" 2}))
{"a" 1, "b" 2}

对于您的用例(修改地图中的所有键)已经是一个不错的核心功能:reduce-kv:

user=> (doc reduce-kv)
-------------------------
clojure.core/reduce-kv
([f init coll])
  Reduces an associative collection. f should be a function of 3
  arguments. Returns the result of applying f to init, the first key
  and the first value in coll, then applying f to that result and the
  2nd key and value, etc. If coll contains no entries, returns init
  and f is not called. Note that reduce-kv is supported on vectors,
  where the keys will be the ordinals.

user=> (reduce-kv (fn [m k v] (assoc m (.toLowerCase k) v)) {} {"A" 1 "B" 2})
{"a" 1, "b" 2}

【讨论】:

  • 当然,多年的命令式编程让我着迷。努力进入函数式编程。
猜你喜欢
  • 2019-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多