2024 年 Clojure 状态调查! 分享您的想法。

欢迎!请参阅 关于 页面,了解如何工作的更多信息。

+1

嗨大家,我正在尝试使用 Integrant 库进行状态管理。在管理(启动/停止)服务器方面,它相当直观,但我在某个用例上感到困惑。

我想使用 integrant 来实例化和销毁一个对象。像往常一样,我定义了 init-keyhalt-key! 方法。问题是我想从 init-key 获取初始化对象的引用。有没有惯用的方法来做这件事?我应该只在 init-key 期间把它存放在一个 atom 中吗?

(defmethod ig/init-key :my-space/my-key [_ opts]
  (let [account-id (:account-id opts)
        license-key (:license-key opts)]
    (MyObject. account-id license-key)))

;;How do I use the instantiated my object?

2 个回答

+1

当你调用 (ig/init config) 时,它会根据你的配置图依赖顺序调用 ig/init-key,并返回一个映射,其中每个键都是定义了的一个 init-key。在你这个用例中,它将返回 {:my-space/my-key #<MyObject…>}。根据你如何结构化你的应用,你可以把这个映射存放在一个 var 或 atom 中,或者你可以将其作为参数传递给你的 ring 中间件,以便每个请求都有一个引用等等。

要调用 MyObject 的方法,你可以这样写 (.someMethod (:my-space/my-key system))

0
by

您使用该 :my-space/my-key 作为另一个组件的参数,该组件将接收由 MyObject 创建的实例。

例如,如果您使用 Integrant 与 Aero,它将类似于以下这样

;; my_space.clj
(defmethod ig/init-key ::my-key [_ opts]
  (let [account-id (:account-id opts)
        license-key (:license-key opts)]
    (MyObject. account-id license-key)))

(defmethod ig/init-key ::other-key [_ {:keys [my-object]}]
  (println "Got object" my-object))

;; config.edn
{:ig/system
 {:my-space/my-key    {:account-id  1
                       :license-key 2}
  :my-space/other-key {:my-object #ig/ref :my-space/my-key}}}
by
我想在 defmethod 之外使用它。我想在常规函数中使用 `MyObject`。
by
那么这将是对 Integrant 的误用,您几乎可以将其整个扔出窗外。您可以为这些常规函数提供额外的参数,该参数来自某个地方并具有该对象,您可以在 `::other-key` 组件中将其作为闭包创建这些函数,您可以将它们作为协议的一部分,并从 `::other-key` 组件返回一个实现对象。所以,您的问题有解决方案,创建一个全局单例不是一个合适的方法。
by
我不确定我是否理解了关于“带有额外参数的常规函数...可以创建为闭包...”的解决方案。你能给我一个例子吗?
每个函数都有一个调用者。你不必依赖某个全局可用的单例,可以为每个调用者传递一个额外的参数,将 `MyObject` 的实例传递给需要它的函数。闭包是一种不同的方法,其中你封装一个值,例如在 `(let [x 1] (fn [] x))` 中,`fn` 是 `x` 的闭包。在 `::other-key` 组件中,你可以创建封装该 `MyObject` 实例的函数,而无需将其作为参数传递。
我知道闭包是什么,但在这里我无法连接这些点。因此,我想使用作为 integrant 的 `init-key` 部分实例化的 `MyObject` 对象的方法。如果写得过长,请见谅。我会尝试阅读更多关于“组件”如何工作的内容。非常感谢您的耐心!
...