我想知道为什么使用defmulti和defmethod?有什么好处?你怎么用它?请解释代码中发生的事情.
Ank*_*kur 32
在"一般术语"中,你会称它为类固醇的if/else,并且在"令人印象深刻"的风格中,你会用"动态调度","运行时多态性"等命名它.
假设您要定义一个函数"Add",它应该适用于各种数据类型,例如在Int的情况下它应该添加数字,如果是字符串,它应该连接字符串.现在使用if else实现它非常简单,基本上你检查参数的类型,如果它们是整数然后添加它们,如果它们是字符串然后连接它们,否则抛出异常.但问题是,如果您想在Add函数中添加对新数据类型的支持,您需要修改 Add函数,这在您不控制Add的来源时可能无法实现,例如它在某些库等中定义
defmulti并defmethod允许您解决此问题,即在不修改其代码的情况下向现有函数添加新案例.
(defmulti add (fn [a b] [(type a) (type b)]))
add是函数名,匿名函数是你的if/else,基本上会在你的add参数上调用,如果有任何实现,将检查这个函数的返回值.现在让我们为Integer实现它.
(defmethod add [Integer Integer] ([a b] (+ a b)))
[Integer Integer]是关于我们定义的匿名函数的返回值defmulti然后执行的sort switch case .
同样我们可以为字符串做
(defmethod add [String String] ([a b] (str a b)))
用整数调用它
(add (int 1) (int 2))
用字符串调用它
(add "hello" "world")
使用与我们的if/else不匹配的东西调用它,即尚未实现的情况将导致异常
Phi*_*hil 10
根据我在阅读答案后所观察到的(并使用上面提供的示例),以下内容也有助于理解:
执行命令时:
(add (int 5) (int 2))
Run Code Online (Sandbox Code Playgroud)
会发生什么'执行'add defmulti'从而产生一个列表:
[Integer Integer]
Run Code Online (Sandbox Code Playgroud)
使用生成的,它会查找上面列出的任何"添加defmethod",即:
(add [Integer Integer])
Run Code Online (Sandbox Code Playgroud)
并传递它收到的论据.
定义多方法以便明确传递参数的另一种方法是:
(defmulti add (fn [a b] [(type a) (type b)]))
(defmethod add [Integer Integer] [a b] (+ a b))
(defmethod add [String String] [a b] (str a b))
Run Code Online (Sandbox Code Playgroud)
然后运行以下函数:
(add 12 73)
Run Code Online (Sandbox Code Playgroud)
要么
(add "thank" "you")
Run Code Online (Sandbox Code Playgroud)