有没有简单的方法来忽略不必要的争论?
例如:
(#(+ %1 %2) 1 2)
返回 3
我想强制执行此代码
(#(+ %1 %2) 1 2 3)
也返回 3。但它返回
java.lang.IllegalArgumentException:传递给的 args (3) 数量错误。
如何改变#(+ %1 %2)
?
我希望有一些比#(+ (nth %& 0) (nth %& 1))
.
有没有简单的方法来忽略不必要的争论?
例如:
(#(+ %1 %2) 1 2)
返回 3
我想强制执行此代码
(#(+ %1 %2) 1 2 3)
也返回 3。但它返回
java.lang.IllegalArgumentException:传递给的 args (3) 数量错误。
如何改变#(+ %1 %2)
?
我希望有一些比#(+ (nth %& 0) (nth %& 1))
.
这就是我会去的:
=> ((fn [a b & _] (+ a b)) 1 2 3)
=> 3
这将创建一个匿名函数,它接受任意数量的参数,但只添加前两个。该_
符号没有做任何特别的事情,它只是“我不关心这件事,但我需要以某种方式绑定它”的惯用语。如果你认为你会经常这样做,那么你可能想要定义它:
(defn add-first-two
[a b & _]
(+ a b))
如果您真的很喜欢#()
语法,则必须%&
在定义中包含某处以“意识到”它应该接受任意数量的参数。这并不意味着您必须在显示时对其进行索引,它只需要存在于某个地方即可。这是一个例子:
=> (#(do %& (+ %1 %2)) 1 2 3)
=> 3
另一方面,此解决方案涉及某种处理%&
,您不需要任何处理,并且可能会稍微减慢速度(我对此不确定,也许其他人可以对此提供反馈)。一个相当有趣的解决方案是只停留%&
在一个(comment ...)
块内,该块的计算结果为nil
.
=> (#(do (comment %&) (+ %1 %2)) 1 2 3)
=> 3
一个更奇特的解决方案是使用#_...
,这很像(comment...)
,只是读者实际上将其从评估中删除,就好像您只是在那里没有输入任何内容一样。这样,也许我们可以将其粘贴在 的主体中(+ ...)
以缩短代码。
=> (#(+ %1 %2 #_%&) 1 2 3)
=> 3
你知道吗,它奏效了。实际上,我以前从未尝试过这个,看到它起作用我感到非常惊讶。#_...
显然,在删除该部分之前有一些处理。奇怪的。
如果您不喜欢这些奇怪的评论解决方案中的任何一个,并且do
不是为您做的,您总是可以将它放在一个(if nil ...)
块中:
=> (#(if nil %& (+ %1 %2)) 1 2 3)
=> 3
好吧,毕竟,我仍然最喜欢第一个解决方案(使用(fn ...)
),但其中一些肯定更短。
这适用于任意数量的参数,并且是可读的:
(fn [& args] (apply + args))
如果您只想使用前 2 个参数(根据 Alex 的评论):
(fn [& args] (apply + (take 2 args)))
您可以直接使用它:
((fn [& args] (apply + (take 2 args))) 1 2)
; => 3
或者将函数绑定到这样的符号:
(let [f (fn [& args] (apply + (take 2 args)))]
(f 1 2))
; => 3
或者创建一个变量:
(def f (fn [& args] (apply + (take 2 args))))
或者一个函数:
(defn f [& args] (apply + (take 2 args)))
最佳定义取决于您的用例。
这个怎么样?
(#(apply + (take 2 %&)) 1 2 3 4 5)
;; => 3
user> (#(do %& (+ % %2)) 1 2)
3
user> (#(do %& (+ % %2)) 1 2 3)
3
它不是很优雅,但我认为这是可以接受的。