如何在 Clojure 中使用 let 构建数组?
How do I build up an array using let in Clojure?
(test [1 2 3]) 是 returning [],而不是 [1 2 3],为什么?
(defn test [some-array]
(let [x []]
(doseq [i some-array]
(conj x i))
x))
(test [1 2 3])
编辑:下面的评论表明我正在尝试使用函数式语言的命令式方法,这可能是正确的。我想要做的是使用初始值序列(在本例中为向量内部)作为起始数据来构建向量的向量。我想我可以尝试转换向量中的每个值并 return 它,但这在概念上(从命令式思维)似乎比获取起始向量并使用它构建一个新向量和 return 那.
举个例子,假设我有一个接受 1
和 returns "one"
的函数,我想要一个接受 [1 2 3]
和 [=] 的函数21=] [[1 "one"][2 "two"][3 "three"]]
.
Clojure 的重点是不可变数据和函数式编程。您的
那里的代码感觉就像您想在这里做一些命令式风格的想法。
你的 test
也可能是 identity
- 一些不可变的副本
数据结构,就是不可变数据结构本身。
如果你的例子过于简单,你想“追加”一些
x
里面有数据,你可以使用 into
.
编辑
逐个转换序列(例如,每个输入结果
不同的输出),使用 map
(或 mapv
获取向量并制作它
渴望的)。例如
(def numbers
{1 "one"
2 "two"
3 "three"})
(defn test [some-array]
(mapv #(vector % (numbers %)) some-array))
(println (test [1 2 3]))
; → [[1 one] [2 two] [3 three]]
(使用 juxt
作为映射函数的奖励积分)
你真的不想那样做 - 但如果你 做了 :-) 你会想使用 loop
而不是 let
:
(defn arr-test [some-array]
(let [digit-words {1 "one", 2 "two", 3 "three", 4 "four", 5 "five",
6 "six", 7 "seven", 8 "eight", 9 "nine", 0 "zero" }]
(loop [x []
a some-array]
(if (empty? a)
x
(recur (conj x [(first a) (digit-words (first a))]) (rest a))))))
更好的方法是:
(defn arr-test [some-array]
(let [digit-words {1 "one", 2 "two", 3 "three", 4 "four", 5 "five",
6 "six", 7 "seven", 8 "eight", 9 "nine", 0 "zero" }]
(mapv #(vector % (digit-words %)) some-array)))
正如其他人指出的那样,构建结果的某些方法比其他方法更容易。在这种情况下,我们看到结果向量的每个元素都是根据输入向量中的相应元素计算的。这是使用 map
(或 mapv
)的良好指示:
(def nums ["zero" "one" "two" "three" "four" "five"])
(defn arr-test [xs]
(mapv (juxt identity nums) xs))
在核心库中还有一个方便的实用程序 clojure.pprint/cl-format
来获取数字的字符串表示(以及更多!):
user> (def num-str (partial clojure.pprint/cl-format nil "~R"))
#'user/num-str
user> (mapv (juxt identity num-str) [0 1 2 234 2455323 1541524152352356235625])
;;=> [[0 "zero"]
;; [1 "one"]
;; [2 "two"]
;; [234 "two hundred thirty-four"]
;; [2455323
;; "two million, four hundred fifty-five thousand, three hundred twenty-three"]
;; [1541524152352356235625N
;; "one sextillion, five hundred forty-one quintillion, five hundred twenty-four quadrillion, one hundred fifty-two trillion, three hundred fifty-two billion, three hundred fifty-six million, two hundred thirty-five thousand, six hundred twenty-five"]]
(test [1 2 3]) 是 returning [],而不是 [1 2 3],为什么?
(defn test [some-array]
(let [x []]
(doseq [i some-array]
(conj x i))
x))
(test [1 2 3])
编辑:下面的评论表明我正在尝试使用函数式语言的命令式方法,这可能是正确的。我想要做的是使用初始值序列(在本例中为向量内部)作为起始数据来构建向量的向量。我想我可以尝试转换向量中的每个值并 return 它,但这在概念上(从命令式思维)似乎比获取起始向量并使用它构建一个新向量和 return 那.
举个例子,假设我有一个接受 1
和 returns "one"
的函数,我想要一个接受 [1 2 3]
和 [=] 的函数21=] [[1 "one"][2 "two"][3 "three"]]
.
Clojure 的重点是不可变数据和函数式编程。您的 那里的代码感觉就像您想在这里做一些命令式风格的想法。
你的 test
也可能是 identity
- 一些不可变的副本
数据结构,就是不可变数据结构本身。
如果你的例子过于简单,你想“追加”一些
x
里面有数据,你可以使用 into
.
编辑
逐个转换序列(例如,每个输入结果
不同的输出),使用 map
(或 mapv
获取向量并制作它
渴望的)。例如
(def numbers
{1 "one"
2 "two"
3 "three"})
(defn test [some-array]
(mapv #(vector % (numbers %)) some-array))
(println (test [1 2 3]))
; → [[1 one] [2 two] [3 three]]
(使用 juxt
作为映射函数的奖励积分)
你真的不想那样做 - 但如果你 做了 :-) 你会想使用 loop
而不是 let
:
(defn arr-test [some-array]
(let [digit-words {1 "one", 2 "two", 3 "three", 4 "four", 5 "five",
6 "six", 7 "seven", 8 "eight", 9 "nine", 0 "zero" }]
(loop [x []
a some-array]
(if (empty? a)
x
(recur (conj x [(first a) (digit-words (first a))]) (rest a))))))
更好的方法是:
(defn arr-test [some-array]
(let [digit-words {1 "one", 2 "two", 3 "three", 4 "four", 5 "five",
6 "six", 7 "seven", 8 "eight", 9 "nine", 0 "zero" }]
(mapv #(vector % (digit-words %)) some-array)))
正如其他人指出的那样,构建结果的某些方法比其他方法更容易。在这种情况下,我们看到结果向量的每个元素都是根据输入向量中的相应元素计算的。这是使用 map
(或 mapv
)的良好指示:
(def nums ["zero" "one" "two" "three" "four" "five"])
(defn arr-test [xs]
(mapv (juxt identity nums) xs))
在核心库中还有一个方便的实用程序 clojure.pprint/cl-format
来获取数字的字符串表示(以及更多!):
user> (def num-str (partial clojure.pprint/cl-format nil "~R"))
#'user/num-str
user> (mapv (juxt identity num-str) [0 1 2 234 2455323 1541524152352356235625])
;;=> [[0 "zero"]
;; [1 "one"]
;; [2 "two"]
;; [234 "two hundred thirty-four"]
;; [2455323
;; "two million, four hundred fifty-five thousand, three hundred twenty-three"]
;; [1541524152352356235625N
;; "one sextillion, five hundred forty-one quintillion, five hundred twenty-four quadrillion, one hundred fifty-two trillion, three hundred fifty-two billion, three hundred fifty-six million, two hundred thirty-five thousand, six hundred twenty-five"]]