clojure
最近,我写了一些有趣的功能Kotlin来解决FizzBuzz测试 。 我要求提供一些反馈,而我收到的答案之一是Clojure :
在Clojure中,有一种经典的方式,即condp和mod。
— Alexandre Grison🇫🇷(@algrison) 2018年5月25日
我几年前看到的还有另一种使用循环的方式。 范围和2个周期将产生嘶嘶声和嗡嗡声,其余仅决定要打印的内容。
高亮显示语法->屏幕截图pic.twitter.com/wOPJD0BpGM对您来说会更容易
左侧的代码如下:
(defn div-by? [n d]
(zero? (mod n d)))
(defn fizz-buzz [n]
(condp = [(div-by? n 3) (div-by? n 5)]
[true true] "FizzBuzz"
[true false] "Fizz"
[false true] "Buzz"
(str n)))
(->> (range 1 100)
(map (comp println fizz-buzz)))
我对Clojure一无所知,但这只是一种功能性语言。 我认为尝试理解以上摘录是一个有趣的练习,尤其是因为它的大小非常有限。 在本文中,我将采用Java开发人员的观点。
括号,到处都有括号
如果您只熟悉C语言家族(例如我自己),那么此代码段看起来就很晦涩。 首先要知道Clojure属于Lisp语言家族。 后者在每个表达式,语句,调用等周围加上括号:
(str n) ; returns n.toString()
没有静态类型检查
Clojure没有静态类型检查。 没有。 零。 齐尔奇 您可以在上面的解决方案中检查是否缺少类型。
如果真的对此感到不舒服,可以使用一个子项目将类型引入Clojure。
没有返回关键字
Clojure是一种功能语言。 因此,它会尽最大努力来强制编写函数:
函数是将集合X的每个元素x(函数的域)与另一个集合Y的单个元素y相关联的过程或关系。
https://zh.wikipedia.org/wiki/功能_(数学)
这意味着每个函数都应该返回。 因此,如上述片段所示, return
关键字是隐式的。
不应该返回值的函数-不纯函数, 例如 println
无论如何都返回nil
。
前缀表示法
Clojure需要先编写方法名称,然后再编写参数(如果需要)。 这与Java非常相似,但是Clojure甚至在算术上都将这种模式应用于所有地方 :
(mod n d) ; returns the reminder of n divided by d
编码约定
- Clojure标识符使用连字符,而不是像Java中那样使用驼峰式大小写
(div-by? n 3) ; calls the div-by? function with arguments n and 3
- 返回
boolean
值的函数应以?
结尾
定义功能
defn
宏允许定义一个新函数。 宏的参数为:
- 函数名称
- 参数列表,指定为可选的空数组
- 功能体
(defn
div-by? (1)
[n d] (2)
(zero? (mod n d))) (3)
- 功能名称
- 函数参数,包装在数组中
- 功能体
链接功能
函数链接是通过comp
宏实现的:
(def times-inc (comp inc *)) (1)
(times-inc 2 3) (2)
- 组成乘和加一的函数
- 用参数
2
和3
调用定义的函数,返回7
开关
condp
宏代替了传统的switch
语句,但功能更强大。 它更类似于Kotlin和Scala中的模式匹配功能。
(condp = [(div-by? n 3) (div-by? n 5)] ; a two-elements array of boolean
[true true] "FizzBuzz"
[true false] "Fizz"
[false true] "Buzz"
(str n)) ; if no other match, this is the default
摘要
总结一下,这是上述代码片段的Java等效项(或Java不够用时的Kotlin):
Clojure | Java /科特琳 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
去做
我仍然需要进一步深化一些细微之处:
- 宏和函数之间的区别
-
→>
宏 -
def
和defn
之间的区别
之后,可能的后续步骤包括:
- 解码原始推文右侧显示的代码
- 潜入收藏
- 了解Clojure / Java互操作性
- 尝试开发基本的Spring Boot应用程序
- 检查“经典”堆栈的Java框架的等效形式, 例如 Web开发,持久性,日志记录,构建等。
clojure