相关疑难解决方法(0)

与doseq(或for)并行处理集合的有效方法?

(doseq [e coll1]
  (myfunc e))
Run Code Online (Sandbox Code Playgroud)

非常快,如果你关心的都是副作用.如果我想myfunc"并行"从多个集合中获取元素,即应用于myfunc每个集合的第一个元素,然后应用于所有第二个元素,然后应用于所有第三个元素等,该怎么办?请注意,这同样是关于foras 的功能的问题doseq,但是如果想要一个序列作为输出,那么map就会做所需的事情,所以for没有必要.

(doseq [e1 coll1
        e2 coll2]
   (myfunc e1 e2))
Run Code Online (Sandbox Code Playgroud)

将改为应用于myfunc两个集合中所有可能的元素组合.如果我事先知道集合的元素是什么,我可以使用:when测试来仅合并某些元素,但是假设我不知道这个?

一种解决方案是创建ntuples以避免使用笛卡尔积,但这非常耗时,从而消除doseq了首先使用的速度优势:

(let [argvecs (map vector coll1 coll2)] ; seq of ntuples of interleaved vals
  (doseq [args argvecs]
     (apply myfunc args))))
Run Code Online (Sandbox Code Playgroud)

(这可能比单个集合慢大约8 doseq倍.查看此问题的时间domap1domap17结尾.)

clojure

5
推荐指数
1
解决办法
428
查看次数

Clojure可变参数宏迭代在&extra参数中收集的序列

问题:如何&在宏中处理catch-all参数,当要传递的参数是序列时,catch-all变量需要作为序列序列处理?catch-all变量中列出的内容是文字表达式.

这是一个宏,它的目的是大致使用Common Lisp mapc,即执行Clojure的map功能,但用于副作用,并且没有懒惰:

(defmacro domap [f & colls] 
      `(dotimes [i# (apply min (map count '(~@colls)))]
         (apply ~f (map #(nth % i#) '(~@colls)))))
Run Code Online (Sandbox Code Playgroud)

我已经意识到这不是一个好的写作方式domap- 我在这个问题上得到了很好的建议.但是,我仍然想知道我在这个过程中遇到的棘手的宏问题.

如果集合作为文字传递,则此方法有效:

user=> (domap println [0 1 2])
0
1
2
nil
Run Code Online (Sandbox Code Playgroud)

但是在这样的其他情况下不起作用:

user=> (domap println (range 3))
range
3
nil
Run Code Online (Sandbox Code Playgroud)

或者这一个:

user=> (def nums [0 1 2])
#'user/nums
user=> (domap println nums)
UnsupportedOperationException count not supported on this type: Symbol clojure.lang.RT.countFro (RT.java:556)
Run Code Online (Sandbox Code Playgroud)

问题是它是文字表达式colls …

macros clojure

3
推荐指数
1
解决办法
433
查看次数

标签 统计

clojure ×2

macros ×1