首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Clojure动态绑定

Clojure动态绑定
EN

Stack Overflow用户
提问于 2012-10-08 20:56:39
回答 2查看 3.2K关注 0票数 8

我意识到以下是一个坏主意,有很多原因。我还意识到,如果我有一个23的堆栈溢出代表,这是自然的假设,我是一个新手学习编程。然而,请幽默我,并专注于“我们如何能做到这一点”而不是“为什么你想这样做/你不想这样做”方面。

我想要的:

代码语言:javascript
复制
(def dog (Dog. ...))
(def cat (Cat. ...))

(with-animal dog
  (println (str "Dog: " (speak) "\n")))
(with-animal cat
  (println (str "Cat: " (speak) "\n")))

到产出:

代码语言:javascript
复制
Dog: woof
Cat: meow

所以,基本上,我希望-动物成为一个宏。所有出现的“call”函数调用都被映射到我正在调用块的对象。

特别是,我不想写:

代码语言:javascript
复制
(let-binding [speak (fn [] "woof")] ...)
(let-binding [speak (fn [] "meow")] ...)

更确切地说,我想让with -动物将want函数映射到我正在调用的对象的某些方法。

有没有一种干净的方法在Clojure中做到这一点?

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-10-08 21:46:53

动态绑定的存在是有原因的,而且它有许多很好的用途,所以不必担心会因为寻求理解它而发火:-)许多旧的Clojure教程在需要添加^:动态元数据之前就出现了一些混乱,您希望动态地重新绑定这些元数据。

第一个示例通过重新绑定现有名称来使用动态绑定。这就消除了宏引入新符号的需要:

首先制作一些动物,我只是在这个例子中使用地图,很多人会使用其他类型的对象:

代码语言:javascript
复制
(def dog {:sound #(str "wooooof")})
(def cat {:sound #(str "mewwww")})

定义我们要重新绑定的函数为动态函数(这允许重新绑定)

代码语言:javascript
复制
(defn :^dynamic speak [] (println "eh?"))

编写一个基本的模板宏来绑定,与动物中的函数对话:

代码语言:javascript
复制
(defmacro with-animal [animal & body] 
    `(binding [speak (:sound ~animal)] 
       ~@body))

并测试它:

代码语言:javascript
复制
(with-animal dog  
  (println (str "Dog: " (speak) "\n")))
Dog: wooooof                                                   

现在,“高级版本”使用了一个let,而不需要动态绑定,它只是在范围内引入了一个符号speak。这并不是说绑定在某种程度上是不好的,它只是更符合您不编写(let-binding [speak (fn [] "meow")] ...)的愿望--这种maco被称为回指(如果您喜欢这么花哨的名字):

重要的部分是在~'符号之前的speak符号,该符号在作用域中显式地引入了一个非限定符号:

代码语言:javascript
复制
user> (defmacro with-animal [animal & body]
    `(let [~'speak (:sound ~animal)] 
        ~@body))
#'user/with-animal

user> (with-animal dog 
        (println (str "Dog: " (speak) "\n")))
Dog: wooooof 

nil

我希望这两个示例之间的对比有助于回答您关于将对象的行为绑定到作用域的问题。第一个示例绑定maco的主体和从该主体调用的任何内容的值。第二个示例只介绍宏主体的名称。

票数 20
EN

Stack Overflow用户

发布于 2015-07-17 15:09:50

如果您真的想让动物类型习惯性地说话,请使用Clojure协议:

代码语言:javascript
复制
(defprotocol ISpeak
  (speak [animal] "make the type say it's thing"))

(deftype Dog []
  ISpeak
  (speak [this] "Woof!"))

(deftype Cat []
  ISpeak
  (speak [_] "Meow!!")) ;;you can "drop" the item if not used using _

(def a-dog (Dog.))
(speak a-dog)
;;=>"Woof!"

(def a-cat (Cat.))
(speak a-cat)
;;=>"Meow!!"

请注意,您可以使用type方法扩展任何类型(类)。

代码语言:javascript
复制
(extend java.util.Random
  ISpeak
  {:speak (fn [_] "I'm throwing dices at you!")})

(speak (java.util.Random.))
;;=>"I'm throwing dices at you!"

Java类的语法略有不同,请参阅协议文档获取更多信息。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12789350

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档