简体   繁体   English

Clojure 从循环中返回值

[英]Clojure return value from a loop

I want to calculate intersection points.我想计算交点。 This works well, but I want to store the points in a vector that the function should return.这很有效,但我想将点存储在函数应该返回的向量中。

Here is my code:这是我的代码:


(defn intersections
  [polygon line]

  (let [[p1 p2] line
        polypoints (conj polygon (first polygon))]

    (doseq [x (range (- (count polypoints) 1))]

      (println  (intersect p1 p2 (nth polypoints x) (nth polypoints (+ x 1))))
)))

Instead of println I want to add the result to a new vector that should be returned.我想将结果添加到应该返回的新向量中,而不是println How can I change it?我怎样才能改变它?

You need to use a for loop.您需要使用for循环。 The doseq function is meant for side-effects only and always returns nil . doseq函数仅用于副作用,并且始终返回nil An example:一个例子:

(ns tst.demo.core
  (:use demo.core tupelo.core tupelo.test))

(defn intersect-1
  [numbers]
  (let [data-vec (vec numbers)]
    (vec
      (for [i (range (dec (count numbers)))]
        {:start (nth data-vec i)
         :stop  (nth data-vec (inc i))}))))

The above way works, as seen by the unit test:如单元测试所示,上述方式有效:

(dotest
  (is= (intersect-1 (range 5))
    [{:start 0, :stop 1}
     {:start 1, :stop 2}
     {:start 2, :stop 3}
     {:start 3, :stop 4}])

However, it is more natural to write it like so in Clojure:然而,在 Clojure 中这样写更自然:

(defn intersect-2
  [numbers]
  (let [pairs (partition 2 1 numbers)]
    (vec
      (for [[start stop] pairs]
        {:start start :stop  stop} ))))

With the same result同样的结果

  (is= (intersect-2 (range 5))
    [{:start 0, :stop 1}
     {:start 1, :stop 2}
     {:start 2, :stop 3}
     {:start 3, :stop 4}]))

You can get more details on my favorite template project (including a big documentation list!).您可以获得有关我最喜欢的模板项目的更多详细信息(包括一个大的文档列表!)。 See especially the Clojure CheatSheet!请特别查看 Clojure CheatSheet!

Side note : The vec is optional in both versions.旁注vec在两个版本中都是可选的。 This just forces the answer into a Clojure vector (instead of a "lazy seq"), which is easier to cut and paste in examples and unit tests.这只是将答案强制转换为 Clojure 向量(而不是“懒惰的 seq”),这样更容易在示例和单元测试中剪切和粘贴。

Instead of for-loop, a map would be more idiomatic.而不是 for 循环, map会更惯用。

(defn intersections
  [polygon line]
  (let [[p1 p2] line]
    (vec (map (fn [pp1 pp2] (intersect p1 p2 pp1 pp2)) polygon (cdr polygon)))))

or:或者:

(defn intersections
  [polygon line]
  (let [[p1 p2] line]
    (vec (map #(intersect p1 p2 %1 %2) polygon (cdr polygon)))))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM