Ruby 用 Ruby 简单模拟 Lambda 演算

lanzhiheng · 2017年08月29日 · 最后由 jiyinyiyong 回复于 2017年09月04日 · 4331 次阅读
本帖已被设为精华帖!

之前有用 lambda 实现 FizzBuzz 的, 可惜因为 ruby 的 proc 没有尾递归, 只能循环到 50...

shinkxw 回复

尾递归这个了解不多,我稍后去看看。

quakewang 回复

cool.受教了 👏 之前不知道还有

2.3.3 :016 > Proc.instance_methods.grep /curry/
 => [:curry]

这个方法可以用。

昨天刚看了计算的本质中的 lambda 演算😁

@alixiaomiao @lanzhiheng 不要看《计算的本质 - 深入剖析程序和计算机》啦, 看 SICP 吧, SICP 才是圣经级别读物.

《计算的本质 - 深入剖析程序和计算机》展现的只是 SICP 的冰山一角 ... ...

我打算看完《计算的本质》就去看 SICP 了🐭 。 Clojure 的头像...... 看来是 FP 粉。

lanzhiheng 回复

我也是因为 读《计算的本质 - 深入剖析程序和计算机》,才知道背后 有这么 牛 B 的 SICP, 作者 Tom 只是借鉴 SICP 思想而已, 然后用 Ruby 语言表达.

SICP 这本书改变了我, 让我转向了 Clojure 开发, 释放 Lisp 函数式强大的原力.

quakewang 回复

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

Lisp 用于 Spark 数据分析:

(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))))

SICP 比较难,能看懂部分。刚卖掉了。

这本书稍后会读一读,一年前有看过一部分,后来觉得用不上就没看了。现在觉得这些才是有意思的地方。

partial 的可读性明显比 ruby 好。->, ->>有什么区别呢?

lanzhiheng 回复

这是函数式圣经级别读物, 我第一次看到这部著作的时候,也直接丢掉了.

Jim Weirich 的演讲, 让我深度思考了函数式, 使得我重新读完这部书的前面四章, 被 SICP 震惊了, 发现我错了. 才知道邱奇是多么的伟大, Lisp 是多么伟大.

chenge 回复

吃透了 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 的配置。

lanzhiheng 回复

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 社区放不下身段, 也就跟着坑了.

jiyinyiyong 回复

感谢您的推荐,我是之前装 cLisp 感觉有点折腾,要编译安装跟 homebrew 一起用才行. ClojureScript 还没了解过,说实在干了大半年前端,感觉完全跟不上前端的节奏。自从小程序这种东西出来之后这种感觉更强烈。我也就没花太多时间去折腾前端的事情了。平时就上班时间好好写样式,写 JavaScript 框架看需要,业余有时间就去搞搞 Ruby 或者看看你们所说的 Lisp。

你这有很严重的广告嫌疑啊,说的我都想试试了。传销!😜

传销~

先做个记号

hemengzhi88 回复

@Peter 如果你们学习 Lambda 演算, 连 它的 鼻祖都 不知道, 那有何意义呢?

Ruby 社区很多高手, 比如 @luikore 等, 都是修炼过 SICP 的, 如果你不知道他们为什么这么厉害, 只能说你们在社区白混了.

今年的RubyConf China 2017, 都已经有三个主题是 关于函数式的了, 难道你们还要停留在学习的舒适区吗?

嗯 Lisp 的正统是 Scheme, Scheme 的正统是 Racket ...

Racket 不仅开箱即 R5RS, R6RS, R7RS... 现在还能跑在 Chez Scheme 上了, Chez Scheme 那代码库克隆下来都上 G 了咯.

小心莫走进 Clojure 或者 Common Lisp 的邪路呀!

luikore 回复

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 和 Erlang 到底哪个好啊,急,在线等。

Rei 回复

我给你 💯

luikore 回复

虽然这么说, 现在和业界结合比较紧密的 Lisp 方言还是腰酸 Clojure 啊. 再说 Lisp 本身不是就已经算邪路了吗 - -

lanzhiheng 回复

是啊, Common Lisp 你一个 Lisp 搞什么 Object, Meta-Object Protocol?

你跟别人讲我用 Common Lisp 啦, 下了一个世界最快的编译器 sbcl ! 别人说好牛哦那你能 call/cc 吗? 玩不了这些花为什么不用 Java? 你就 sb 了...

讲真 Racket 的社区比 CL 更活跃, Scheme 也更纯粹简单, 装个 Racket 什么都有了, 何苦搞 CL?

luikore 回复

多谢推荐,会抽时间看看 scheme。

jiyinyiyong 回复

Clojure 和 Racket 还算相似... 不过你干点什么事情都得找 Java 的库看 Java, 这不仅是一门语言...

luikore 回复

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 过度复杂.

jasl 将本帖设为了精华贴 09月03日 18:57
luikore 回复

还真是有这个问题... 主要是我对 js 生态已经熟悉了, 觉得作为低级语言被 ClojureScript 这个高级语言调用就当是平台 API 了 - -

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册