Clojure编辑代码时运行拆分成不同的文件

时间:2013-02-20 19:55:43

标签: opengl emacs clojure lwjgl nrepl

我最近一直试图用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并使用该函数。

有没有办法让代码在两个文件之间分割,同时仍能在运行时更改代码?

1 个答案:

答案 0 :(得分:3)

通过将#'放在var名称前面,将var更新而不是var update中当前包含的函数传递给它。这将导致每次调用时都会在var中查找更新函数的内容。

(def -main
  [& args]
  (starter/start {:width 800 :height 600 :title "Test" :update-fn #'update})

性能成本非常低,这就是为什么它不是默认值,虽然它在这种情况下非常有用而且成本很低。