首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >修改参数作为multimethod的一部分

修改参数作为multimethod的一部分
EN

Stack Overflow用户
提问于 2018-07-25 21:46:05
回答 3查看 160关注 0票数 3

作为其分派的一部分,编写修改传入参数的multimethod的惯用方法是什么?

在这种情况下,我想删除其中一个论点:

代码语言:javascript
复制
(defmulti do-update ???)

(defmethod do-update :set-cursor [state x y]
  (assoc state :cursor [x y]))

(defn post [action & args]
  (swap! some-state do-update action args))

(post :set-cursor 0 0)

这里的dispatch-fn将负责读取action关键字,并将(cons state args)作为方法的参数转发。

这种方法的另一种选择是创建调度图。

代码语言:javascript
复制
(defn set-cursor [state x y])

(def handlers
  {:set-cursor set-cursor})

(defn dispatch [action & args]
  (let [handler (action handlers)]
    (apply swap! some-state handler args)))

但是在没有映射的情况下,根据相应的操作自动注册这些处理程序将是很好的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-07-26 02:17:22

作为多方法设计的一部分,这些方法接收与调度函数相同的参数。如果这些方法对仅用于分派的某些参数不感兴趣,那么在方法实现中忽略它们是非常好的--而且一点也不奇怪:

代码语言:javascript
复制
(def some-state (atom {:cursor [-1 -1]}))

(defmulti do-update
  (fn [state action x y]
    action))

;; ignoring the action argument here:
(defmethod do-update :set-cursor [state _ x y]
  (assoc state :cursor [x y]))

;; added apply here to avoid ArityException in the call to do-update:
(defn post [action & args]
  (apply swap! some-state do-update action args))

(post :set-cursor 0 0)

@some-state
;= {:cursor [0 0]}

请注意,为了方便do-updateswap!的使用,调度参数位于第二位。

票数 5
EN

Stack Overflow用户

发布于 2018-07-26 01:02:05

您不能直接询问该方法是什么输入到调度函数,从而导致它选择调用此方法,这是可以的,因为调度方法只是函数!

您可以在分派给它的方法中再次调用调度函数。只要您的调度函数是纯函数,这将是坚实的。如果不是..。

因此,如果您将yoru yes函数定义为??? (是的?)是有效的函数名)

代码语言:javascript
复制
user=> (defn ??? [x] (inc x))
#'user/???

你的多重方法是这样的

代码语言:javascript
复制
user=> (defmulti foo ???)

然后在方法中再次调用调度函数:

代码语言:javascript
复制
 (defmethod foo 1 [x] 
    (str "I was dispatched from " x 
         " and i will use " (??? x) 
         " to do my good work"))

您可以重构调度函数的操作,而不必维护一个独立的函数/map/thing。

代码语言:javascript
复制
user=> (foo 0)
"I was dispatched from 0 and i will use 1 to do my good work"
票数 1
EN

Stack Overflow用户

发布于 2018-07-26 02:14:49

虽然核心语言不支持这一点,但您可以使用一些“重写”宏来对所需的语义进行分层:

代码语言:javascript
复制
(defmacro defupdatemulti [name] 
  `(defmulti ~name (fn [state# action# & args#] action#)))

(defmacro defupdatemethod [name action [state & args] & body] 
  `(defmethod ~name ~action 
    [~state _# [~@args]] 
    ~@body))

并利用这一点:

代码语言:javascript
复制
(defupdatemulti do-update)

(defupdatemethod do-update :set-cursor [state x y] 
  (assoc state :cursor [x y]))

在此基础上

代码语言:javascript
复制
(def some-state (atom {}))

(defn post [action & args]
  (swap! some-state do-update action args))

(post :set-cursor 0 0)

产生的结果如下:

代码语言:javascript
复制
{:cursor [0 0]}

注:虽然上面的工作,它肯定不是惯用的。

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

https://stackoverflow.com/questions/51528140

复制
相关文章

相似问题

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