【问题标题】:Replicate Java peek stream method in Clojure在 Clojure 中复制 Java peek 流方法
【发布时间】:2021-01-20 07:46:59
【问题描述】:

在 Java 中我可以做到这一点

list.stream().peek(System.out::println).filter(i -> i >= 0).findFirst();

这将找到列表中的第一个正数,打印从开始到第一个正数的所有数字。

我在 Clojure 中需要类似的东西,但我找不到 peek 的等价物。 peek 在 Clojure 中做了一些不同的事情。我需要在不消耗序列的情况下创建副作用,中介。就像元素通过一样,它们应该被传递给函数。 我可以自己实现它,但我不想重新发明现有的东西。似乎是基本功能,我找不到要调用的正确函数。

【问题讨论】:

  • 你可以编一些函数来达到效果,像这样:(defn effect [f] (fn [x] (f x) x))。然后以这种方式使用它:(first (drop-while (comp neg? (effect println)) (range -10 10)))。但是这里有一个陷阱:在某些情况下,clojure 优化了序列的消耗,通过块来实现它们。所以(first (filter (comp pos? (effect println)) (range -10 10))) 会给你比你预期更多的输出。只要您使用 take-while / drop-while 就可以了,但是 filter / map 和其他需要一些去块代码以确保不会发生意外的副作用。

标签: clojure java-stream seq peek


【解决方案1】:

只需将 mapdoto 和传感器结合使用,即可产生副作用,否则将成为传递:

(into []
 (comp
  (map #(doto % println))
  (filter pos?)
  (take 1))
 [-1 -2 -3 4 5])

或者对于您在评论中所说的内容,您可以使用do,例如:

(->>
 (repeatedly #(rand-nth [1 nil nil]))
 (into []
  (comp
   (map #(do (when (nil? %) (Thread/sleep 1000)) %))
   (remove nil?)
   (take 1)))
 first)

我正在使用转换器,因为由于分块,延迟序列不能保证一次只有一个,如果你想避免这种情况,需要特别小心,所以在你的情况下它会更好更容易希望在数据转换管道中混合副作用以使用转换器。

【讨论】:

    【解决方案2】:

    如果你研究the Clojure CheatSheet,你会发现函数split-with 几乎可以满足你的需求:

    (ns tst.demo.core
      (:use demo.core tupelo.core tupelo.test))
    
    (dotest
      (let [[dropped kept] (split-with #(neg? %) (range -10 10))]
        (is= dropped [-10 -9 -8 -7 -6 -5 -4 -3 -2 -1])
        (is= kept [0 1 2 3 4 5 6 7 8 9])
        (is= 0 (first kept))))
    

    如果您将来需要某些东西并且找不到有效的内置函数,您可以随时使用loop/recur 编写简单的循环(或“递归”)。

    另请参阅this list of documentation

    【讨论】:

    • 这只是一个例子,我真正需要知道的是在 Clojure 中是否有接近 Java Stream peek 的东西。这个我可以自己实现,我可以复制map的实现,调用f但不使用结果,让原始元素通过。感觉就像是基本功能:能够窥探一系列传感器。我的实际用法更奇特,如果当前元素在传感器链中的中间步骤为零,我想等待一秒钟。像这样: (->> (repeatedly step) *** (remove nil?) first) where *** 就像 (javapeek sleepOneSecIfNil)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    • 2016-02-11
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    相关资源
    最近更新 更多