【问题标题】:Getting modulus from seq->stream从 seq->stream 获取模数
【发布时间】:2014-05-01 21:43:16
【问题描述】:

下面的代码在整个屏幕上绘制正弦波,甚至更远。 但是,我希望 x 永远不会超过(宽度)。到那时,应该清除窗口,再次绘制波浪,从 0 开始。我试过了

(set-state! :x (mod (seq->stream x) (width)))

但它没有用。我检查了some examples,尝试了一些用于检查(> x (width))的代码,尝试将逻辑放入draw函数中,但它们也不起作用。

我想在有限的显示器上绘制连续波形(如心电图)。我将不胜感激。

(ns soso.core
  (:require [quil.core :refer :all]
            [quil.helpers.seqs :refer [seq->stream range-incl]]))

(defn setup []
  (smooth)
  (frame-rate 100)
  (background 255)
  (let [x (range-incl)]
    (set-state! :x (seq->stream x))))

(defn draw []
  (stroke 0)
  (stroke-weight 2)
  (let [x ((state :x))
        y (round (* 100 (abs (sin x))))]
    (ellipse x y 4 4)))

编辑

在尝试将逻辑放入draw函数时,我在setup函数中写了(set-state! :x 0),并将以下代码放入draw函数中:

(let [x (if (> ((state :x)) 10)
            0
          (inc ((state :x))))])

但它不起作用,并且没有在任何 nrepl 缓冲区中引发任何错误。为了看看发生了什么,我在用户 repl 中尝试了这段代码:

(let [x 0]
  (take 20
        (if (> x 10)
            0
          (inc x))))

即使我通过将 if 语句包装在 (into '()) 中来尝试此代码,该代码仍抱怨:“IllegalArgumentException 不知道如何从:java.lang.Long clojure.lang.RT.seqFrom 创建 ISeq”。与以下相同:

(loop [x 0]
  (if (> x 10)
    0
    (recur (inc x))))

这个 if 语句有什么问题? clojure api 表示 if 测试测试条件,然后相应地评估并产生 then 或 else 分支。如果它产生了,它应该吐出那个整数,然后它会被添加到列表中,我认为它又应该由 take 函数列出。

【问题讨论】:

  • 第三次编辑代码:我希望这会产生一个 0。循环将使用 0、1、2... 等,直到 (> x 10) 时返回 0。
  • 第二次编辑代码:take适用于seq。即(取 3 '(1 2 3 4 5 6))。 (take 3 2) 将给出您的错误 - 您不能“从值 2 中获取前三个项目”,因为它不是一个序列。
  • 第一次编辑代码:quil 提供的“状态”本质上是一张地图。在您的第一个示例中,您在设置中将 :x 设置为 0,然后您尝试将其评估为 ((state :x)) 中的函数 - 我不确定为什么错误不会冒泡到顶部,但是您运行 (0) 应该得到相同的效果 - 即 ClassCastException java.lang.Long 不能强制转换为 clojure.lang.IFn。
  • 最后的想法 - 我认为您可能会从基本的 clojure 教程中受益。你需要弄清楚函数/序列/值之间的差异,否则你会陷入混乱。 (range-incl) 返回一个 seq,seq->stream 返回一个函数,该函数在重复计算时将返回来自 seq 的值。在 ((state :x)) 周围加双括号的原因是 (state :x) 返回一个函数,然后您使用 () 调用该函数。
  • 你说得对。 Thunks 和流是我了解 DrRacket 的最后一部分。当我累了,我开始混淆那些双括号的含义。非常感谢您的澄清。

标签: clojure quil


【解决方案1】:

更像这样的东西似乎可以提供您正在寻找的效果。

(defn draw []
  (stroke 0)
  (stroke-weight 2)
  (let [x ((state :x))
        y (+ 100 (* 100 (sin (/ x 100))))]
    (ellipse (mod x (width)) y 4 4)))

您遇到的几个问题:

  1. sin 的输入是以弧度为单位的浮点值。我在这里除以 100 的技巧只是确保我们得到一个很好的连续输出。实际上,如果您想每 n 个像素循环一次,您需要使用 2 PI / n 来调整 x。
  2. 四舍五入会给你分数,因为 sin 的范围是 1 到 -1。这里我通过增加 100 来调整。
  3. 在哪里使用 x 取决于具体要求。在这里,我只是通过在绘图函数中取其模数来包装您的 x 值。

希望这会有所帮助。

【讨论】:

  • 谢谢。 (mod ((state :x)) (width)) 也有效。我非常投入到让 if 语句起作用,不知何故我想不出它。您能非常介意检查我的编辑并对此发表评论吗?因为我真的希望能够调试这些东西。视觉信息很好,但如果 clojure 不抱怨,什么也不画,它就不起作用。
猜你喜欢
  • 2015-02-02
  • 1970-01-01
  • 2019-11-22
  • 2020-03-07
  • 2019-09-08
  • 2013-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多