如何在Clojure中定义C++风格函数对象(functor)及读取其参数?
如何读取Clojure闭包中的参数?
针对你提出的问题——如何读取Clojure闭包中保存的参数(比如sin1、sin2里的freq),我整理了几种实用的实现方法,每种都有对应的代码示例:
方法1:让闭包支持查询操作
修改newSinus,让返回的函数既能计算正弦值,也能响应特定的查询请求:
(defn newSinus [freq] (fn [x] (if (= x :get-freq) freq (Math/sin (* freq x))))) (def sin1 (newSinus 2.0)) (println (sin1 1.5)) ; 执行计算,输出对应正弦值 (println (sin1 :get-freq)) ; 查询参数,输出2.0
这种方式简单直接,不需要额外的结构,通过传入的参数区分是计算还是查询。
方法2:返回包含函数与参数的映射
把计算函数和它依赖的参数包装成一个Map,这样可以通过键名直接访问参数,同时保留函数调用的能力:
(defn newSinus [freq] {:calc (fn [x] (Math/sin (* freq x))) :freq freq}) (def sin1 (newSinus 2.0)) (println ((:calc sin1) 1.5)) ; 调用计算逻辑 (println (:freq sin1)) ; 直接读取freq参数
这种方式把数据和行为明确分开,逻辑清晰,适合需要暴露多个参数的场景。
方法3:使用记录类型(Record)
如果需要更结构化的定义,Clojure的记录类型是绝佳选择——它可以定义带字段的类型,同时实现函数调用接口,完美模拟C++ functor的特性:
(defrecord Sinus [freq] clojure.lang.IFn (invoke [this x] (Math/sin (* (:freq this) x)))) (def sin1 (->Sinus 2.0)) (println (sin1 1.5)) ; 像普通函数一样调用记录对象 (println (:freq sin1)) ; 直接读取freq字段
记录类型自带字段访问能力,还能享受Clojure对记录的原生支持(比如解构、友好打印等),是最接近C++ functor体验的方案。
方法4:结合原子实现可变参数(适合动态修改场景)
如果需要参数可以动态修改,可以用原子(Atom)来保存freq,这样既能读取也能更新参数,但对于仅需读取的场景来说稍显过重:
(defn newSinus [freq] (let [freq-atom (atom freq)] (fn ([] @freq-atom) ([x] (Math/sin (* @freq-atom x))) ([new-freq] (reset! freq-atom new-freq))))) (def sin1 (newSinus 2.0)) (println (sin1 1.5)) ; 执行计算 (println (sin1)) ; 读取当前freq (sin1 3.0) ; 更新freq的值 (println (sin1 1.5)) ; 用新的freq执行计算
内容的提问来源于stack exchange,提问作者cibercitizen1
相关产品推荐
相关产品推荐

