如何在 Clojure 中为函数参数创建默认值
我的想法是:
(defn string->integer [str & [base]]
(Integer/parseInt str (if (nil? base) 10 base)))
(string->integer "10")
(string->integer "FF" 16)
但这一定是更好的方法。
I come with this:
(defn string->integer [str & [base]]
(Integer/parseInt str (if (nil? base) 10 base)))
(string->integer "10")
(string->integer "FF" 16)
But it must be a better way to do this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果签名的数量不同,则一个函数可以有多个签名。您可以使用它来提供默认值。
请注意,假设
false
和nil
都被视为非值,(if (nil? base) 10 base)
可以缩短为(如果基数为 10)
,或进一步到(或基数 10)
。A function can have multiple signatures if the signatures differ in arity. You can use that to supply default values.
Note that assuming
false
andnil
are both considered non-values,(if (nil? base) 10 base)
could be shortened to(if base base 10)
, or further to(or base 10)
.从 Clojure 1.2 开始,您还可以将
rest
参数解构为映射 [ref ]。这使您可以命名并提供函数参数的默认值:现在您可以调用
或
您可以在此处查看其实际效果:https://github.com/Raynes/clavatar/blob/master/src/clavatar/core.clj (例如)
You can also destructure
rest
arguments as a map since Clojure 1.2 [ref]. This lets you name and provide defaults for function arguments:Now you can call
or
You can see this in action here: https://github.com/Raynes/clavatar/blob/master/src/clavatar/core.clj (for example)
这个解决方案更接近原始解决方案的精神,但稍微干净
一点类似模式,可以方便地使用
或
与let
虽然在这种情况下更详细,但如果您希望默认值依赖于其他输入值,它可能会很有用。例如,考虑以下函数:
这种方法也可以轻松扩展以使用命名参数(如 M. Gilliar 的解决方案):
或者使用更多的融合:
This solution is the closer to the spirit of the original solution, but marginally cleaner
A similar pattern which can be handy uses
or
combined withlet
While in this case more verbose, it can be useful if you wish to have defaults dependent on other input values. For example, consider the following function:
This approach can easily be extended to work with named arguments (as in M. Gilliar's solution) as well:
Or using even more of a fusion:
您可能需要考虑另一种方法:部分函数。这些可以说是一种更“实用”且更灵活的指定函数默认值的方式。
首先创建(如有必要)一个函数,该函数具有您想要提供的默认参数作为前导参数:
这样做是因为 Clojure 的
partial
版本允许您仅按照它们在函数定义中出现的顺序提供“默认”值。根据需要对参数进行排序后,您可以使用partial
函数创建该函数的“默认”版本:为了使该函数可多次调用,您可以使用以下命令将其放入 var 中:
def
:您还可以使用
let
创建“本地默认值”:与其他方法相比,部分函数方法有一个关键优势:消费者的消费者函数仍然可以决定默认值,而不是函数的生产者,无需修改函数定义。这在
hex
示例中进行了说明,其中我确定默认函数decimal
不是我想要的。这种方法的另一个优点是您可以为默认函数分配不同的名称(十进制、十六进制等),这可能更具描述性和/或不同的范围(var、local)。如果需要,部分函数也可以与上述一些方法混合使用:(
请注意,这与 Brian 的答案略有不同,因为由于本响应顶部给出的原因,参数的顺序已被颠倒)
There is another approach you might want to consider: partial functions. These are arguably a more "functional" and more flexible way to specify default values for functions.
Start by creating (if necessary) a function that has the parameter(s) that you want to provide as default(s) as the leading parameter(s):
This is done because Clojure's version of
partial
lets you provide the "default" values only in the order they appear in the function definition. Once the parameters have been ordered as desired, you can then create a "default" version of the function using thepartial
function:In order to make this function callable multiple times you could put it in a var using
def
:You could also create a "local default" using
let
:The partial function approach has one key advantage over the others: the consumer of the function can still decide what the default value will be rather than the producer of the function without needing to modify the function definition. This is illustrated in the example with
hex
where I have decided that the default functiondecimal
is not what I want.Another advantage of this approach is you can assign the default function a different name (decimal, hex, etc) which may be more descriptive and/or a different scope (var, local). The partial function can also be mixed with some of the approaches above if desired:
(Note this is slightly different from Brian's answer as the order of the parameters has been reversed for the reasons given at the top of this response)
您还可以查看
(fnil)
https://clojuredocs.org/clojure。核心/fnilYou might also look into
(fnil)
https://clojuredocs.org/clojure.core/fnil与 Matthew 的建议非常相似的方法是不执行
&
剩余参数,而是要求调用者提供灵活(和可选)键的单个额外映射参数。这样做的一个好处是,选项是单个参数映射,调用者不必如此小心地传递偶数个额外参数。另外,短绒可以用这种风格做得更好。编辑器还应该在映射键值表格对齐(如果您喜欢的话)方面做得比每行参数对更好。
轻微的缺点是,当在没有选项的情况下调用时,仍然必须提供一个空地图。
位置参数部分(Code Smells 文章)对此进行了讨论。
更新: Clojure 1.11 现在支持 传入可选参数的映射(使用
&
)。A very similar approach to Matthew's suggestion is to not do the
&
rest args, but require that callers provide the single extra map argument of flexible (and optional) keys.There is a benefit to this in that the options are a single argument map and the caller doesn't have to be so careful about passing an even number of extra args. Plus, linters can do better with this style. Editors should also do better with map key-value tabular alignment (if you're into that) than pairs of args per line.
The slight down-side is that when called with no options, an empty map must still be provided.
This is touched on in this Positional Arguments section (Code Smells article).
UPDATE: There is now support in Clojure 1.11 for passing in a map for optional args (using
&
).