clojure如何同时在两个seq的元素上执行函数?
在Clojure中,在两个seq上并发迭代并在两个运行的元素上调用函数的最佳方式是什么? 例如:clojure如何同时在两个seq的元素上执行函数?,clojure,Clojure,在Clojure中,在两个seq上并发迭代并在两个运行的元素上调用函数的最佳方式是什么? 例如: (def a (range 3)) (def b (range 100 103)) (defn my-func [] ...) ;some custom code 代码应执行my func 3次,如下所示: (my-func 0 100) (my-func 1 101) (my-func 2 102) 如何在不定义任何函数或宏的情况下实现这一点?map正是您所需要的,它接受一个函数和任意数量的s
(def a (range 3))
(def b (range 100 103))
(defn my-func [] ...) ;some custom code
代码应执行my func 3次,如下所示:
(my-func 0 100)
(my-func 1 101)
(my-func 2 102)
如何在不定义任何函数或宏的情况下实现这一点?
map
正是您所需要的,它接受一个函数和任意数量的seq,并按您的意愿调用它们
(def a (range 3))
(def b (range 100 103))
user=> a
(0 1 2)
user=> b
(100 101 102)
user=> (defn my-func [a b] (str a ":" b))
#'user/my-func
user=> (my-func 1 2)
"1:2"
user=> (map my-func a b)
("0:100" "1:101" "2:102")
如果您希望函数现在实际运行,则因为map
是惰性的:
(doall (map my-func a b))
你也可以试试
(doseq [[x y] (map list my-list1 my-list2)]
(println x y))
(映射列表列表-2列表-2)
创建一个列表,其中第一个元素是输入列表中第一个元素的列表,第二个元素是第二个元素的列表
然后,我们在列表上迭代,使用Clojure的解构来提取原始列表的元素
通常,如果要使用所应用函数的返回值,则需要
map
。如果您只是执行函数的副作用,我通常使用doseq
。这个例子很复杂,因为map
并行工作,而doseq
迭代给定的列表,所以您需要map
和doseq
来获得我们想要的行为。是(doseq)的替代方案。。。(映射
解决方案,如果您想要成对迭代而不是笛卡尔积,您还可以将分区
与交错
组合,如下所示:
> (def a (range 0 3))
> (def b (range 100 103))
> (interleave a b)
(0 100 1 101 2 102)
> (partition 2 (interleave a b))
((0 100) (1 101) (2 102))
partition
调用提供了一个(惰性)对序列。@viebel:您是否在REPL上运行并使用println
?如果是这样,您的结果会令人困惑。假设您运行了(map#(println%1):“%2)ab)
,那么实际情况是REPL打印了(
,然后println
打印0:100
和1:101
,然后REPL完成地图结果的打印,即nil-nil)
@Arthur Ulfeldt:我的问题的全部目的是寻找一种不创建映射的迭代方法。println只是一个例子。我寻找的代码应该与任何接收2个参数的函数一起工作。我是否应该编辑问题以澄清它?@viebel:map
做了你想做的,但是println
的结果是正确的e与REPL输出交错。(map f a_1 a_2…a_n)
调用f
,参数取自seqsa_1
到a_n
,并以新的seqprintln
返回nil
,因此map
pingprintln(nil-nil…nil)
结果。例如:(map+[1 2 3][6 2 9][9 2 2])
=>(16 6 14)
@YehonathanSharvit:map
是懒惰的(请参阅,或者也有一点),因此它在需要结果之前不会进行计算(这也是REPL内容散布的原因)。它非常方便,但在这种情况下可能会绊倒您。请尝试(doall(map println'(12)'(10 20))
doall
强制对传递给它的seq
进行求值。(范围100 102)只有两个元素-也许您的意思是(范围100 103)?@mikera:谢谢。更新了问题:是否有类似doseq的函数可以并行迭代,而不是笛卡尔积。如果没有,背后的原理是什么?据我所知,没有这样的函数。理想情况下,doseq/for(它们的语法相同)将允许类似于:和的选项允许两个seq并行迭代。不幸的是,这样的选项不存在。