【发布时间】:2013-08-06 23:48:59
【问题描述】:
在 Ruby 中,有 Kernel#Array 方法,作用如下:
Array([1, 2, 3]) #=> [1, 2, 3]
Array(1..5) #=> [1, 2, 3, 4, 5]
Array(9000) #=> [9000]
Array(nil) #=> []
换句话说,它将 nil 转换为空数组,将非集合转换为单例数组,并将各种类似集合的对象(即响应 #to_ary 或 #to_a 的对象)转换为数组。
我想在 Clojure 中有类似的东西:
(to-seq [1 2 3]) ;=> (1 2 3)
(to-seq (range 1 5)) ;=> (1 2 3 4)
(to-seq 9000) ;=> (9000)
(to-seq nil) ;=> nil; () is ok too
这就是我到目前为止所得到的:
(defn to-seq [x] (if (seqable? x) (seq x) '(x)))
但我不喜欢它,因为:
-
seqable?函数在单体 clojure-contrib 的 the explosion 期间消失了。我不想仅仅为了一个功能在我的项目中包含庞大的、不再受支持的库。 - 我感觉在clojure.core 或clojure.contrib.whatever 中一定有一个内置函数。或者还有更惯用的方法。
to-seq 的确切输出类型并不重要。主要是我想在列表推导中使用它的输出:
(for [person (to-seq person-or-people)] ...)
所以如果将是一个向量 - 没关系。如果它是一个向量、一个 Java 数组、一个列表或 nil,取决于输入 - 这也很好。
==== UPD ====
几乎最终版:
(defn to-seq [x] (if (or (nil? x) (coll? x)) x [x]))
最终版本:
(defn to-seq ..blabla..)
我不需要to-seq,它看起来不吸引人。
【问题讨论】:
-
附带说明,
'(x)计算为包含符号x的单例列表;你会想用(list x)或[x]代替。