gpt4 book ai didi

clojure - 在 clojure 中使用 'binding' 的好例子是什么?

转载 作者:行者123 更新时间:2023-12-04 02:06:04 25 4
gpt4 key购买 nike

我了解 binding form 允许在 clojure 中重新绑定(bind)动态范围。到目前为止,我看到它的唯一用途是用于 I/O,例如 print在哪里 *out*反弹到你当时想要的任何作家。

我希望看到真正利用 binding 功能的示例其他设施真的不起作用的地方。就我个人而言,我只在将用户提供的对象传递给所有函数非常乏味的情况下使用它。基本上是我试图创建辅助函数使用的上下文的情况。 (类似于这种情况 When should one use the temporarily-rebind-a-special-var idiom in Clojure? )更具体地说,我依靠用户创建到 *db* 的动态绑定(bind)。 var 让数据库函数知道要操作什么。当用户需要编写大量对数据库函数的嵌套调用时,这特别有用。通常,如果我需要编写宏来让自己更轻松,我可以,但要求用户这样做似乎很糟糕。话虽如此,我尽量避免这样做。

我可以复制并合并到我的代码中的“绑定(bind)”还有哪些其他好的用例?

最佳答案

我使用绑定(bind)有两个原因:

  • 运行覆盖常量或其他符号的其他值的测试
  • 使用“全局”资源,例如数据库连接或消息代理 channel

  • 测试

    我正在开发一个分布式系统,该系统具有多个组件,这些组件通过消息交换发送消息来进行通信。这些交易所具有全局名称,我将其定义如下:
    (ns const)
    (def JOB-EXCHANGE "my.job.xchg")
    (def CRUNCH-EXCHANGE "my.crunch.xchg")
    ;; ... more constants

    这些常量在许多地方被用来将消息发送到正确的地方。为了测试我的代码,我的部分测试套件运行使用实际消息交换的代码。但是,我不希望我的测试干扰实际系统。

    为了解决这个问题,我将测试代码包装在 binding 中。覆盖这些常量的调用:
    ;; in my testing code:
    (binding [const/CRUNCH-EXCHANGE (str const/CRUNCH-EXCHANGE (gensym "-TEST-"))
    const/CRUNCH-TASK-QUEUE (str const/CRUNCH-TASK-QUEUE (gensym "-TEST-"))]
    ;; tests here
    )

    这里面 binding函数,我可以调用任何使用常量的代码,它会使用被覆盖的值。

    使用全局资源

    我使用绑定(bind)的另一种方法是“修复”特定范围内的全局或单例资源的值。这是我编写的 RabbitMQ 库的示例,我在其中绑定(bind)了 RabbitMQ Connection 的值到符号 *amqp-connection*以便我的代码可以使用它:
    (with-connection (make-connection opts)
    ;; code that uses a RabbitMQ connection
    )
    with-connection的执行很简单:
    (def ^{:dynamic true} *amqp-connection* nil)

    (defmacro with-connection
    "Binds connection to a value you can retrieve
    with (current-connection) within body."
    [conn & body]
    `(binding [*amqp-connection* ~conn]
    ~@body))

    我的 RabbitMQ 库中的任何代码都可以使用 *amqp-connection* 中的连接并假设它是一个有效的、打开的 Connection .或使用 (current-connection)函数,当您忘记将 RabbitMQ 调用包装在 with-connection 中时会引发描述性异常:
    (defn current-connection
    "If used within (with-connection conn ...),
    returns the currently bound connection."
    []
    (if (current-connection?)
    *amqp-connection*
    (throw (RuntimeException.
    "No current connection. Use (with-connection conn ...) to bind a connection."))))

    关于clojure - 在 clojure 中使用 'binding' 的好例子是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7169671/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com