最近,我写了一些有趣的功能Kotlin来解决FizzBu??zz测试 。 我要求提供一些反馈,我收到的答案之一是Clojure :
在Clojure中,有一种经典的方式,即condp和mod。
我几年前看到的还有另一种使用循环的方式。 范围和2个周期将产生嘶嘶声和嗡嗡声,其余仅决定要打印的内容。通过语法高亮显示->屏幕截图pic.twitter.com/wOPJD0BpGM将使您更加轻松
— Alexandre Grison????(@algrison) 2018年5月25日
左侧的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 | ( 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语言家族。 后者在每个表达式,语句,调用等周围加上括号:
1 | ( str n ) ; returns n.toString() |
没有静态类型检查
Clojure没有静态类型检查。 没有。 零。 齐尔奇 您可以在上面的解决方案中检查是否缺少类型。
| 如果真的对此感到不舒服,则有一个子项目将类型引入Clojure。 |
没有返回关键字
Clojure是一种功能语言。 因此,它会尽最大努力来强制编写函数:
函数是将集合X的每个元素x(函数的域)与另一个集合Y的单个元素y相关联的过程或关系。
—维基百科
https://zh.wikipedia.org/wiki/功能_(数学)
这意味着每个函数都应该返回。 因此,如上述片段所示,
不应该返回值的函数-不纯函数( 例如
前缀表示法
Clojure需要先编写方法名称,然后再编写参数(如果需要)。 这与Java非常相似,但是Clojure将该模式应用于所有地方 ,甚至用于算术:
1 | ( mod n d ) ; returns the reminder of n divided by d |
编码约定
- Clojure标识符使用连字符,而不是像Java中那样使用驼峰式大小写
1( div-by? n 3 ) ; calls the div-by? function with arguments n and 3
- 返回
boolean 值的函数应以? 结尾
定义功能
- 函数名称
- 参数列表,指定为可选的空数组
- 功能体
1 2 3 4 | ( defn div-by? <i class="conum" data-value="1"></i> <b class="raw_b_node">(1)</b> [ n d ] <i class="conum" data-value="2"></i> <b class="raw_b_node">(2)</b> ( zero? ( mod n d ))) <i class="conum" data-value="3"></i> <b class="raw_b_node">(3)</b> |
| 1个 | 功能名称 |
| 2 | 函数参数,包装在数组中 |
| 3 | 功能体 |
链接功能
函数链接是通过
1 2 | ( def times-inc ( comp inc * )) <i class="conum" data-value="1"></i> <b class="raw_b_node">(1)</b> ( times-inc 2 3 ) <i class="conum" data-value="2"></i> <b class="raw_b_node">(2)</b> |
| 1个 | 组成乘和加一的函数 |
| 2 | 用参数 |
开关
1 2 3 4 5 | (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编程语言
- 通过示例Clojure
- Clojure-JVM的函数式编程
关注@nicolas_frankel
翻译自: https://blog.frankel.ch/decoding-clojure-code/