Clojure 从循环中返回值

1 clojure

我想计算交点。这很有效,但我想将点存储在函数应该返回的向量中。

这是我的代码:


(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))))
)))

Run Code Online (Sandbox Code Playgroud)

而不是println我想将结果添加到应该返回的新向量中。我怎样才能改变它?

Ala*_*son 6

您需要使用for循环。该doseq函数仅用于副作用,并且始终返回nil。一个例子:

(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))}))))
Run Code Online (Sandbox Code Playgroud)

如单元测试所示,上述方式有效:

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

然而,在 Clojure 中这样写更自然:

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

同样的结果

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

您可以获得有关我最喜欢的模板项目的更多详细信息(包括一个大的文档列表!)。请特别查看 Clojure CheatSheet!

旁注vec在两个版本中都是可选的。这只是将答案强制转换为 Clojure 向量(而不是“懒惰的 seq”),这样更容易在示例和单元测试中剪切和粘贴。