【问题标题】:Clojure Quil: nested loops while drawing linesClojure Quil:绘制线条时的嵌套循环
【发布时间】:2017-01-26 00:36:36
【问题描述】:

我在找出 Clojure Quil 库中的算法时遇到了严重的问题。我一直在尝试使用功能中间件模式制作一些网络/集群模式图,例如this。我的问题是如何在 Quild 中创建一个嵌套的“for 循环”,以便用一条线将任何给定点连接到任何其他点?区别在于一组连接的点 1->2 3->4...etc 和一组连接的点 1->2 1->3 1->4 2->3 2->4...等等

我的程序看起来像这样,尽管出于这个问题的目的,我尝试将其编辑为通用的。

(ns stack-question.core
  (:require [quil.core :as q]
            [quil.middleware :as m]))   

;how to draw the point
(defn draw-points [point]
  (q/point (:x point) (:y point)))

;the main data structure
(defn make-point [num]
  {:name num
   :x (rand 500.0)
   :y (rand 500.0)})    

;draws connections between two objects
(defn connections [p1 p2]
      (q/stroke 200 200 100 150)
      (q/line (:x p1) (:y  p1) (:x p2) (:y p2)))))

(defn setup []
  (q/frame-rate 30)
  {:points (map make-points (take 1000 (range)))})

;this function isn't important to the question 
;but let's just say that the points move position each frame 
(defn update-state [state]
  (update state :points move-group))

;this is the problem function here.
;I'm trying to map over the collection, but with a fixed head
;and do so for each element in the collection
(defn make-conts [coll]
  (loop [x coll]
    (when (not (empty? (rest coll)))
      (map (partial connections (first x)) (rest x))
      (recur (rest x)))))


(defn draw-state [state]
  (do
    ;(q/frame-rate 1)
    (q/background 0)
    (doseq [x (map draw-point (:points state))] x)
    (doseq [x (make-conts (:points state))] x)))

(q/defsketch stack-question
  :title "GL"
  :size [500 500]
  :setup setup
  :update update-state
  :draw draw-state
  :middleware [m/fun-mode]
  :renderer :opengl)

我希望这不是完全不透明的。

【问题讨论】:

    标签: algorithm clojure functional-programming side-effects quil


    【解决方案1】:

    你的代码有两个问题:

    首先是您在when 语句中检查(rest coll) 而不是(rest x),从而导致无限循环。

    第二个是map 返回一个惰性序列,这意味着对connections 的调用没有发生。这可以通过使用doall 包装对map 的调用来解决,但由于您对副作用感兴趣,而不是返回值,您应该改用doseq

    这个版本的函数(多余的loop 也被删除了)应该可以工作:

    (defn make-conts [coll]
        (when (not (empty? (rest coll)))
          (doseq [endpoint (rest coll)]
            (connections (first coll) endpoint))
          (recur (rest coll))))
    

    您可以使用来自clojure.math.combinatoricscombinations,而不是自己编写代码来生成组合:

    (require '[clojure.math.combinatorics :as combi])
    
    (defn make-conts [coll]
       (doseq [[p1 p2] (combi/combinations coll 2)]
         (connections p1 p2)))
    

    【讨论】:

      猜你喜欢
      • 2018-05-03
      • 1970-01-01
      • 2014-09-01
      • 1970-01-01
      • 2019-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-15
      相关资源
      最近更新 更多