Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional Ruby

Jichao Ouyang
September 24, 2016

Functional Ruby

- first class function
- pattern matching
- category theory
- pure program in Functional way

Jichao Ouyang

September 24, 2016
Tweet

Other Decks in Programming

Transcript

  1. Ruby 函数式 ? https://cloud.githubusercontent.com/assets/1235045/17933311/321ff7d2-6a46-11e6-903e- 8cc84f3acc78.JPG You might be surprised to

    see Ruby in the list of functional languages because they generally count as object oriented languages. -- Martin Odersky 你可能奇怪我把Ruby 也放到了函数式语言的列表, 这些语言通常会被归到面向对 象语言. -- Scala 之父
  2. 什么是函数式 一等函数 first class function / 入 lambda 纯 purity

    引用透明性 referential transparency 无副作用 side effectless 不可变 immutability 持久化数据结构 persistent data structures ... 当纯到一定程度可能就需要 范畴论 Catergory Theory
  3. 好处呢? 好组合 composible 好推理 easy to reason about 好测试 easy

    to test 好多线程 Multi-thread 好玩 fun 好 高逼格 high bigger elegant
  4. lambda aka 匿名函数 [ 多选题] 请选出所有的 lambda A : {

    } / d o e n d # s u c h a s = [ 1 , 2 , 3 ] . m a p { | x | x + 1 } = B : p l u s 1 = l a m b d a { | x | x + 1 } C : p l u s 1 = - > ( x ) { x + 1 } D : p l u s 1 = P r o c . n e w { | x | x + 1 }
  5. 如果给这个lambda 一个引用, 我们可以跟用 method 一样用 p l u s 1

    = - > ( x ) { x + 1 } p l u s 1 . c a l l ( 3 ) p l u s 1 . ( 3 ) p l u s 1 [ 3 ]
  6. 三等公民 d e f p l u s 1 x

    x + 1 e n d [ 1 , 2 , 3 , 4 ] . m a p & p l u s 1 ` p l u s 1 ' : w r o n g n u m b e r o f a r g u m e n t s ( 0 f o r 1 ) ( A r g u m e n t E r r o r )
  7. 一等公民 Proc p l u s 1 = - >

    ( x ) { x + 1 } [ 1 , 2 , 3 , 4 ] . m a p & p l u s 1
  8. 给三等座升个舱 d e f p l u s 1 x

    x + 1 e n d f i r s t _ c l a s s _ p l u s 1 = m e t h o d ( : p l u s 1 ) [ 1 , 2 , 3 , 4 ] . m a p & f i r s t _ c l a s s _ p l u s 1
  9. 升舱的魔法 # t o _ p r o c m

    e t h o d ( : p l u s 1 ) # = > # < M e t h o d : O b j e c t # p l u s 1 > c l a s s M e t h o d d e f t o _ p r o c l a m b d a { | * a r g s | s e l f . c a l l ( * a r g s ) } e n d e n d
  10. 升舱实例2 - Symbol % w ( o u y a

    n g j i c h a o ) . m a p & : c a p i t a l i z e # = = = % w ( o u y a n g j i c h a o ) . m a p { | x | x . c a p i t a l i z e }
  11. 来 Desugar & % w ( o u y a

    n g j i c h a o ) . m a p & : c a p i t a l i z e . t o _ p r o c % w ( o u y a n g j i c h a o ) . m a p & P r o c . n e w ( | x | x . s e n d ( : c a p i t a l i z e ) )
  12. destructure - 数组 f i r s t , *

    m i d d l e _ a n d _ l a s t = [ ' P h i l l i p ' , ' J a y ' , ' F r y ' ] " f i r s t : # { f i r s t } , m i d d l e _ a n d _ l a s t : # { m i d d l e _ a n d _ l a s t } "
  13. destructure - 哈希 方法的参数会自带 destructure 哈希的功能 aka k e y

    w o r d a r g u m e n t s : f r y = { f i r s t : ' P h i l l i p ' , m i d d l e : ' J a y ' , l a s t : ' F r y ' } d e f p r i n t F i r s t N a m e f i r s t : , * * r e s t p f i r s t , r e s t e n d p r i n t F i r s t N a m e f r y
  14. 值 这个很简单,应该都有用过 m e = ' o u y a

    n g ' c a s e m e w h e n ' o u y a n g ' " h e h e # { m e } " e l s e ' h e h e j i c h a o ' e n d
  15. 类型 c l a s s M e d e

    f i n i t i a l i z e n a m e @ n a m e = n a m e e n d d e f h e h e d a " 呵呵哒 # { @ n a m e } " e n d e n d m e = M e . n e w ' o u y a n g ' c a s e m e w h e n M e m e . h e h e d a e l s e ' 呵呵哒了' e n d
  16. lambda (aka guard ) r e q u i r

    e ' o s t r u c t ' m e = O p e n S t r u c t . n e w ( n a m e : ' j i c h a o ' , f i r s t _ n a m e : ' o u y a n g ' ) c a s e m e w h e n - > ( w h o ) { w h o . n a m e = = ' j i c h a o ' } " h e h e # { m e } " e n d
  17. 正则 c a s e ' j i c h

    a o o u y a n g ' w h e n / o u y a n g / " 呵呵哒" e n d
  18. 但其实只是个简单的语法糖 case when 并不是magic ,其实只是 if else 的语法糖, 比如上面说的正则 i

    f ( / o u y a n g / = = = ' j i c h a o ' ) " h e h e d a " e n d 所以 magic 则是所有 when 的对象都实现了 = = = 方法而已 值: o b j e c t . = = = 会代理到 = = 类型: M o d u l e . = = = 会看是否是其 instance 正则: r e g e x . = = = 如果匹配返回 true 表达式:取决于表达式返回的值的 = = = 方法 lambda : p r o c . = = = 会运行 lambda 或者 proc
  19. 命令式放大象 o p e n e d _ f r

    i d g e = o p e n _ f r i d g e i f o p e n e d _ f r i d g e f r i d g e _ w _ e l e p h e n t = p u t _ e l e p h e n t _ i n o p e n e d _ f r i d g e i f f r i d g e _ w _ e l e p h e n t c l o s e d _ f r i d g e = c l o s e _ f r i d g e i f c l o s e d _ f r i d g e ' y a y ' e l s e ' f a i l t o c l o s e f r i d g e ' e n d e l s e ' f a i l t o p u t e l e p h e n t i n ' e n d e l s e ' f a i l t o o p e n f r i d g e ' e n d
  20. 监控 o p e n e d _ f r

    i d g e = o p e n _ f r i d g e i f o p e n e d _ f r i d g e M o n i t o r i n g . l o g g e r . i n f o ( ' f r i d g e o p e n e d ' ) f r i d g e _ w _ e l e p h e n t = p u t _ e l e p h e n t _ i n o p e n e d _ f r i d g e i f f r i d g e _ w _ e l e p h e n t M o n i t o r i n g . l o g g e r . i n f o ( ' p u t e d a e l e p h e n t i n t o f r i d g e ' ) c l o s e d _ f r i d g e = c l o s e _ f r i d g e i f c l o s e d _ f r i d g e M o n i t o r i n g . l o g g e r . i n f o ( ' f r i d g e c l o s e d ' ) ' y a y ' e l s e M o n i t o r i n g . l o g g e r . e r r o r ( ' n o a b l e t o c l o s e f r i d g e ' ) ' f a i l t o c l o s e f r i d g e ' e n d e l s e M o n i t o r i n g . l o g g e r . e r r o r ( ' e l e p h e n t p u t f a i l e d ' ) ' f a i l t o p u t e l e p h e n t i n ' e n d e l s e M o n i t o r i n g . l o g g e r . e r r o r ( ' f a i l t o o p e n f r i d g e ' ) ' f a i l t o o p e n f r i d g e ' e n d
  21. 或者用更极端的抛异常方式 b e g i n c l o s

    e ( p u t _ e l e p h e n t _ i n o p e n _ f r i d g e ) r e s c u e A = > e . . . r e s c u e B = > e . . . r e s c u e C = > e . . . e n d
  22. 让我们用一个简单的 Either Monad g e m i n s t

    a l l d a t a . e i t h e r r e q u i r e ' d a t a . e i t h e r ' R i g h t . n e w ( 1 ) . f l a t _ m a p d o | x | i f x < 1 L e f t . n e w ( ' m e h ' ) e l s e R i g h t . n e w ( x + 1 ) e n d e n d # = > # < R i g h t 2 >
  23. 来简化控制流 o p e n _ f r i d

    g e . f l a t _ m a p d o | f r i d g e | # < = 1 p u t _ e l e p h e n t _ i n f r i d g e # < = 2 e n d . f l a t _ m a p d o | f r i d g e | c l o s e f r i d g e # < = 3 e n d 这样可以专心构造控制逻辑, 而不需要关心上一步如果错误该怎么办
  24. Either 魔法 https://github.com/jcouyang/cats.rb/blob/master/lib/data.either.rb d e f f l a t

    _ m a p c a s e s e l f w h e n R i g h t y i e l d @ v e l s e s e l f e n d e n d
  25. 控制流不关心失败和监控 d o a < - f e t c

    h A b < - f e t c h B c < - p u t $ b l a h a + + b
  26. d e f f e t c h ( e

    n d p o i n t , d e c o d e r ) r e s p o n s e = s e l f . c l a s s . g e t ( e n d p o i n t , f o r m a t : : j s o n ) c a s e r e s p o n s e . c o d e w h e n 4 1 0 L e f t . n e w ( E x c e p t i o n s : : D a t a F a i l u r e . n e w ( " R e s o u r c e # { e n d p o i n t } w a s d e l e t e d " ) ) w h e n 4 0 4 L e f t . n e w ( E x c e p t i o n s : : D a t a F a i l u r e . n e w ( " R e s o u r c e # { e n d p o i n t } n o t e x i s t " ) ) w h e n 2 0 0 R i g h t . n e w d e c o d e r . f r o m _ j s o n ( r e s p o n s e . b o d y ) e l s e L e f t . n e w ( E x c e p t i o n s : : R e p o s i t o r y E r r o r . n e w ( " F e t c h i n g # { e n d p o i n t } w i t h E r r o r : \ n # { e n d p o i n t } , r e s p o n s e c o d e n d e n d
  27. f a i l u r e _ p r

    o c e s s e d , s u c c e s s _ p r o c e s s e d = E i t h e r . p a r t i t i o n M a p i n a t o r . r u n M o n i t o r i n g . s e n d _ p r o c e s s e d s u c c e s s _ p r o c e s s e d . l e n g t h M o n i t o r i n g . l o g g e r . i n f o ( " P r o c e s s e d s u c c e s s f u l # { s u c c e s s _ p r o c e s s e d . l e n g t h } l i s t i n g s : # { s u c c e s s _ p r o c e s s e d } M o n i t o r i n g . l o g g e r . e r r o r ( " P r o c e s s e d F A I L U R E # { f a i l u r e _ p r o c e s s e d . l e n g t h } w i t h E x c e p t i o n s : " ) u n l e s s f a i l u r e . . .
  28. Q/A

  29. 并发多线程 made easy r e q u i r e

    " c e l l u l o i d / a u t o s t a r t " m o d u l e E n u m e r a b l e d e f p m a p ( & b l o c k ) f u t u r e s = m a p { | e l e m | C e l l u l o i d : : F u t u r e . n e w ( e l e m , & b l o c k ) } f u t u r e s . m a p ( & : v a l u e ) e n d e n d