我最近一直试图用lwjgl库在Clojure中测试OpenGL。我开始使用这段代码:
(ns test.core
(:import [org.lwjgl.opengl Display DisplayMode GL11]))
(defn init-window
[width height title]
(Display/setDisplayMode (DisplayMode. width height))
(Display/setTitle title)
(Display/create))
(defn update
[]
(GL11/glClearColor 0 0 0 0)
(GL11/glClear GL11/GL_COLOR_BUFFER_BIT))
(defn run
[]
(init-window 800 600 "test")
(while (not (Display/isCloseRequested))
(update)
(Display/update))
(Display/destroy))
(defn -main
[& args]
(.start (Thread. run)))
这在emacs中运行良好,使用nREPL插件,我可以启动它并在运行时更改某些内容(例如调用glClearColor
)。
我决定将其拆分为两个单独的文件,因此我可以重用init-window
函数:
(ns copengl.core
(:import [org.lwjgl.opengl Display DisplayMode GL11]))
(defn init-window
[width height title]
(Display/setDisplayMode (DisplayMode. width height))
(Display/setTitle title)
(Display/create))
(defn mainloop
[{:keys [update-fn]}]
(while (not (Display/isCloseRequested))
(update-fn)
(Display/update))
(Display/destroy))
(defn run
[data]
(init-window (:width data) (:height data) (:title data))
(mainloop data))
(defn start
[data]
(.start (Thread. (partial run data))))
然后在一个单独的文件中
(ns test.core
(:import [org.lwjgl.opengl Display DisplayMode GL11])
(:require [copengl.core :as starter]))
(def -main
[& args]
(starter/start {:width 800 :height 600 :title "Test" :update-fn update})
然而,这不允许我在跑步时改变。我必须关闭窗口然后再次执行-main
以查看更改。
到目前为止,我已经尝试将最后两个代码摘录放入一个文件中,但也无效。但是,如果我将调用从update-fn
更改为更新函数的名称(update
),当它们位于同一文件中时,我可以在运行时更改内容。
我猜这是因为当我使用更新函数创建地图时,它会传递实际函数,因此,如果我通过使用nREPL插件重新定义update
来评估它,则没有效果,因为{ {1}}函数正在使用该函数 - 不查找符号mainloop
并使用该函数。
有没有办法让代码在两个文件之间分割,同时仍能在运行时更改代码?
答案 0 :(得分:3)
通过将#'
放在var名称前面,将var更新而不是var update中当前包含的函数传递给它。这将导致每次调用时都会在var中查找更新函数的内容。
(def -main
[& args]
(starter/start {:width 800 :height 600 :title "Test" :update-fn #'update})
性能成本非常低,这就是为什么它不是默认值,虽然它在这种情况下非常有用而且成本很低。