Clojure atom在网络爬虫中的惯用用法

Clojure atom在网络爬虫中的惯用用法,clojure,Clojure,例如,在网络爬虫中,它维护一组全局访问的URL。工作人员开始处理URL或完成URL后,其他工作人员不应使用相同的URL。在Java中实现这一点的一种方法是将访问的URL放入ConcurrentHashMap(一组可能更好)。每个工作人员在访问URL之前都会查看地图 if (visited.putIfAbsent(url, true) == null) { crawl(url); } else { // do nothing } 在Clojure中,我使用原子中的集合。每次我准备用最近访

例如,在网络爬虫中,它维护一组全局访问的URL。工作人员开始处理URL或完成URL后,其他工作人员不应使用相同的URL。在Java中实现这一点的一种方法是将访问的URL放入
ConcurrentHashMap
(一组可能更好)。每个工作人员在访问URL之前都会查看地图

if (visited.putIfAbsent(url, true) == null) {
  crawl(url);
} else {
  // do nothing
}
在Clojure中,我使用原子中的集合。每次我准备用最近访问的URL交换一个新的集合时,交换函数应该检查集合是否已经有这个URL。如果URL存在,则工作程序应从此处停止。为了能够告诉工作者交换是否成功,我必须在全局状态下保存返回值,如
[上次交换成功时访问的URL]

(def state (atom [#{} nil]))
(defn f [state key] (let [[visited-urls l] state] (if (visited-urls key) [visited-urls false] [(conj (visited-urls key) true]))))
工人应该这样做

(when (second (swap! state f url)) (crawl url))

它很管用,但在我看来很难看。问题是swap函数不允许向callsite返回值。在Clojure有更好的方法吗?

参考文献是为这类事情设计的。这里有一个简单的方法

(when (dosync (when-not (@visited-urls-ref url-to-visit)
                (alter visited-urls-ref conj url-to-visit)))
  ; continue crawling url-to-visit
  )
我无法想象这会给网络爬虫增加任何显著的开销


就个人而言,假设访问URL的顺序不重要,我会创建一个带有重复数据消除传感器的core.async通道,并让所有工作人员将URL放入/取出。

参考文献就是为这类事情制作的。这里有一个简单的方法

(when (dosync (when-not (@visited-urls-ref url-to-visit)
                (alter visited-urls-ref conj url-to-visit)))
  ; continue crawling url-to-visit
  )
我无法想象这会给网络爬虫增加任何显著的开销


就个人而言,假设URL的访问顺序不重要,我会创建一个带有
重复数据消除
传感器的core.async通道,并让所有工作人员将URL放到/从中取出。

这是refs where的制作目的:-)这是refs where的制作目的:-)