序员喜欢写函数式风格的代码.函数式风格的代码,主要遵循下面三条规则:
只读取函数传递的参数或在函数内创建的变量
不改变已经被设值的变量的值
除了返回值,不去影响函数外的任何内容
你也许会怀疑在这种限制下你还能写代码吗?答案是:可以!为什么很对这些规则感到疑惑呢?一个很重要的原因是:遵循此种风格的代码更加的引用透明(referential transparency):这意味着,对于给定的代码,你传入相同的参数,永远返回相同的结果---这能减少程序的错误,也能提高程序的生产力!
当然了,你也会有一些非函数式风格的代码,因为不这么做,你无法和其它用户或外部内容进行交互.教程后面会有这些函数,他们不遵循上面的规则.
describe-location函数的另一个问题是,它没告诉我们怎么进入一个位置或者怎么从某个位置出来.让我们来编写这样的函数:
(defn describe-path [path]
`(there is a ~(second path) going ~(first path) from here -))
这个函数看起来很明了:它看起来更像是数据而不是函数.我们先来尝试调用它,看它做了些什么:
(describe-path '(west door garden))user=> (describe-path '(west door garden))
(user/there user/is user/a door user/going west user/from user/here clojure.core/-)
这是什么?!结果看起来很乱,包含了很多的/和一些其它的文字!这是因为Clojure会将命名空间的名字添加到表达式的前面.我们这里不深究细节,只给你提供消除这些内容的函数:
(defn spel-print [list] (map (fn [x] (symbol (name x))) list))
修改调用方式
(spel-print (describe-path '(west door garden)))user=> (spel-print (describe-path '(west door garden)))
(there is a door going west from here -)
现在结果很清晰了:这个函数接收一个描述路径的list然后将其解析到一个句子里面.我们回过头来看这个函数,这个函数和它产生的数据非常的像:它就是拼接第一个和第二个list的元素到语句中!它是怎么做到的?使用语法quote!
还记得我们使用quote来从代码模式切换到数据模式吗?语法quote的功能类似,但是还不只这样.在语法quote里,我们还能使用'~'再次从数据模式切换回代码模式.
语法quote是List的一个很强大的功能!它能使我们的代码看起来像它创建的数据.这在函数式编码中很常见:创建这种样子的函数,使得我们的代码更易读也更稳健:
只要数据不变,函数就不需要修改.想象一下,你能否在VB或C中编写类似的代码?你可能需要将文字切成小块,然后在一点点的组装-这和数据本身看起来差距很大,更别说代码的稳健性了!
现在我们能描述一个路径,但是一个地点可能会有多个路径,所以让我们来创建一个函数叫做describe-paths:
(defn describe-paths [location game-map]
(apply concat (map describe-path (rest (get game-map location)))))
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/shumachanpin/article-41579-3.html
具有领海和专属经济区
旅沪比这条船舰龄大点