【发布时间】: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 的最后一部分。当我累了,我开始混淆那些双括号的含义。非常感谢您的澄清。