curry 和数学中定义各种符号一样,主要是用来抽取公用部分,简化代码。
比如高中数学中的累加符号Σ
对应到 Ruby 代码,我们可以定义一个 sigma lambda
sigma = -> (f, a, b) { a.upto(b).map{|n| f.(n)}.inject(:+)}
然后用 curry 定义数字累加操作和平方累加操作:
sum_of_number = sigma.curry.(-> (n) {n})
sum_of_square = sigma.curry.(-> (n) {n * n})
sum_of_number.(1,10)
sum_of_square.(1,10)
可以用相同的代码来定义累乘符号∏
pi = -> (f, a, b) { a.upto(b).map{|n| f.(n)}.inject(:*)}
更进一步,Σ和∏都是范围操作,我们可以用 curry 抽取出来:
range = -> (x, f, a, b) { x.(a.upto(b).map{|n| f.(n)})}
sigma = range.curry.(-> (r) {r.inject(:+)})
pi = range.curry.(-> (r) {r.inject(:*)})
products_of_number = pi.curry.(-> (n) {n})
products_of_number.(1,10)
cool.受教了 之前不知道还有
2.3.3 :016 > Proc.instance_methods.grep /curry/
=> [:curry]
这个方法可以用。
@alixiaomiao @lanzhiheng 不要看《计算的本质 - 深入剖析程序和计算机》啦,看 SICP 吧,SICP 才是圣经级别读物。
《计算的本质 - 深入剖析程序和计算机》展现的只是 SICP 的冰山一角 ... ...
我打算看完《计算的本质》就去看 SICP 了 。Clojure 的头像...... 看来是 FP 粉。
我也是因为 读《计算的本质 - 深入剖析程序和计算机》,才知道背后 有这么 牛 B 的 SICP, 作者 Tom 只是借鉴 SICP 思想而已,然后用 Ruby 语言表达。
SICP 这本书改变了我,让我转向了 Clojure 开发,释放 Lisp 函数式强大的原力。
Lisp 语言里面一般都是用 partial, 函数式数据分析,还有在线数据流机器学习,实在是太方便了。
(def sigma
(fn [sf f a b]
(->> (range a (inc b))
(map #(f %))
(reduce sf))))
(def sum-of-number (partial sigma + (fn [n] n)))
(def sum-of-square (partial sigma + #(* % %)))
(sum-of-number 1 10) ;;=> 55
(sum-of-square 1 10) ;;=> 385
(def pi (partial sigma *))
(pi (fn [n] n) 1 3) ;;=> 6
(defn ratings->matrix [data]
(let [cardinality (-> data
(spark/map #(.product %))
(spark/reduce max)
(inc))]
(->> data
(spark/group-by #(.user %))
(spark/values)
(spark/map (to-sparse-vector cardinality))
(to-matrix))))
这是函数式圣经级别读物,我第一次看到这部著作的时候,也直接丢掉了。
Jim Weirich 的演讲, 让我深度思考了函数式,使得我重新读完这部书的前面四章,被 SICP 震惊了,发现我错了。才知道邱奇是多么的伟大,Lisp 是多么伟大。
吃透了 SICP, 一般的程序员的功力就干不过你了。所以它不是那么容易吃透的呀。
->
& ->>
的区别是 :
(macroexpand-1 '(-> 100 (+ 1) (+ 2) (+ 3))) ;;=> (+ (+ (+ 100 1) 2) 3)
(macroexpand-1 '(->> 100 (+ 1) (+ 2) (+ 3))) ;;=> (+ 3 (+ 2 (+ 1 100)))
为什么选择 clojure?我之前花了很大的力气装了 clisp,不过感觉它的 REPL 用起来不算太舒服,安装也比较麻烦。也有试过 scheme 感觉还不错。现在用的比较多是 elisp,平时会用来改一下 emacs 的配置。
Clojure 除了具备了 Lisp 开发的 最佳体验 (Emacs + REPL) 开发,没有比这个开发体验更好的,我用过如此多的语言里面。
而且 Clojure 的资源几乎是无限的,Java 资源轻易封装使用,如我自己封装的一些 : 讯飞 Clojure 的 SDK, Hanlping, 阿里云 aliyun-oss-clj 等等。
而且 ClojureScript 函数式来写复杂前端都轻易搞定:https://github.com/chanshunli/clojurescript-study, https://github.com/clojurescript-scope-games/flappy-bird-demo 等等。也是 Lisp 的开发体验,甚至不需要离开编辑器就完成了复杂单页面或者游戏。
还有我用 Clojure 调用 Spark 数据分析,机器学习等:如 https://github.com/clojure-spark/sparkling-streaming-ml
我还用 Clojure 来写安卓 APP 收集传感器数据,做流式数据在线学习 等,
Java 能做的,Clojure 一样能做,而且速度快的 惊人,曾经我认为 Ruby 是最好的语言,但是我错了,能够开发 Clojure 是我命运的眷顾,让我知道 什么才是程序员的幸福 , Clojure 给我的感觉是,优美的极点 + 无穷的强大几乎没有它干不了的事情。
@lanzhiheng ClojureScript 安装相对容易,直接用 Brew 或者 npm 就能装好。REPL 环境现在有 Lumo 和 Planck, 启动很快,不知道你需要什么功能,应该是有常用功能的。ClojureScript 社区比较注重工程化的实用性,不过也难说,毕竟 js 生态有些坑,Lisp 社区放不下身段,也就跟着坑了。
感谢您的推荐,我是之前装 cLisp 感觉有点折腾,要编译安装跟 homebrew 一起用才行。ClojureScript 还没了解过,说实在干了大半年前端,感觉完全跟不上前端的节奏。自从小程序这种东西出来之后这种感觉更强烈。我也就没花太多时间去折腾前端的事情了。平时就上班时间好好写样式,写 JavaScript 框架看需要,业余有时间就去搞搞 Ruby 或者看看你们所说的 Lisp。
@Peter 如果你们学习 Lambda 演算,连 它的 鼻祖都 不知道,那有何意义呢?
Ruby 社区很多高手,比如 @luikore 等,都是修炼过 SICP 的,如果你不知道他们为什么这么厉害,只能说你们在社区白混了。
今年的RubyConf China 2017, 都已经有三个主题是 关于函数式的了,难道你们还要停留在学习的舒适区吗?
嗯 Lisp 的正统是 Scheme, Scheme 的正统是 Racket ...
Racket 不仅开箱即 R5RS, R6RS, R7RS... 现在还能跑在 Chez Scheme 上了,Chez Scheme 那代码库克隆下来都上 G 了咯。
小心莫走进 Clojure 或者 Common Lisp 的邪路呀!
还是这个 Elixir 更吸引 ruby 圈子吧。对比一下,没有@变量的耦合,是不是觉得更清楚些呢?
defmodule DrawShapes do
def areas(shapes) do
for shape <- shapes do
area(shape)
end
end
def area(shape) do
module = shape.__struct__
apply(module, :area, [shape])
end
end
defmodule Circle do
defstruct radius: nil
def new(radius), do: %Circle{radius: radius}
def area(circle) do
(circle.radius * :math.pi) |> :math.pow(2)
end
end
defmodule Square do
defstruct side: nil
def new(side), do: %Square{side: side}
def area(square) do
square.side |> :math.pow(2)
end
end
shapes = [Circle.new(3), Square.new(4)]
DrawShapes.areas(shapes)
虽然这么说,现在和业界结合比较紧密的 Lisp 方言还是腰酸 Clojure 啊。再说 Lisp 本身不是就已经算邪路了吗 - -
是啊,Common Lisp 你一个 Lisp 搞什么 Object, Meta-Object Protocol?
你跟别人讲我用 Common Lisp 啦,下了一个世界最快的编译器 sbcl ! 别人说好牛哦那你能 call/cc 吗?玩不了这些花为什么不用 Java? 你就 sb 了...
讲真 Racket 的社区比 CL 更活跃,Scheme 也更纯粹简单,装个 Racket 什么都有了,何苦搞 CL?
Clojure 和 Racket 还算相似... 不过你干点什么事情都得找 Java 的库看 Java, 这不仅是一门语言...
Common Lisp 不是有。。。Common Lisp Object System (CLOS) 嘛。。。像 Scheme 上的 Gauche、Meroon,还有 Guile 上的 GOOPS 都可以看作是受这玩意的启发在其它语言上的实践。call/cc
是真痛。。。很多时候只能靠 handler-bind
苟活一下
@luikore Scheme 和 Racket, 是 Lisp 界的标准,这一点不容置疑,学透 SICP 可以完全升级一个程序员的 内功。
但 Scheme 的问题是停留在教育层面的,虽然 Racket 尝试生产方面,毕竟还没成功。
Scheme 和 Clojure 是很像的,但是 Clojure 的生产效率是非常高的,它和 Java 之间的互操作,都是简单得让你惊奇。而且 Ruby 底子好的人,看 Java 代码是不难的。
Clojure 后端开发 非常成熟,ClojureScript 前端开发体验也是一流的,而且 Clojure 在大数据和数据分析领域也是非常成熟的,如 Storm, Cascalog, 包括 Clojure 调用 Spark 也是非常容易的。
Common Lisp 已经是混合多范式了,虽然根植于 Lisp, 我不想用它的原因是,CLOS 不应该继承到 它的核心里面,使得 Clisp 过度复杂。
还真是有这个问题... 主要是我对 js 生态已经熟悉了,觉得作为低级语言被 ClojureScript 这个高级语言调用就当是平台 API 了 - -