Rubyã§é¢æ°åæã¨ããããã®ã§ lambda_driver.gem ã¨ããã®ãä½ã£ã
Rubyã§ãProcãlambdaã§é¢æ°åæã§ããããã«ãããã£ãã®ã§ãlambda_driver.gemã¨ããã®ãä½ã£ãã
å
容çã«ã¯ãã®è¾ºã§æ¸ããã¤ããgemã«ããæãã
- 「関数型Ruby」という病(2) - 関数合成 Proc#compose - ( ꒪⌓꒪) ゆるよろ日記
- 「関数型Ruby」という病(3) - カリー化(Proc#curry, Proc#flip) - ( ꒪⌓꒪) ゆるよろ日記
ãããªé¢¨ã«ãã«ãã³ããã³ã¼ããæ¸ããã
require 'lambda_driver' # [:foo, :bar, :baz].map{|s| s.to_s }.map{|s| s.upcase } # [:foo, :bar, :baz].map(&:to_s).map(&:upcase) [:foo, :bar, :baz].map(&:to_s >> :upcase ) # => ["FOO", "BAR", "BAZ"] # [:foo, :hoge, :bar, :fuga].select{|s| s.to_s.length > 3} # => [:hoge, :fuga] [:foo, :hoge, :bar, :fuga].select(&:to_s >> :length >> 3._(:<)) # => [:hoge, :fuga]
ãã®gemã¯ãå人çã«ãããããé¢¨ã«æ¸ããããããªãã¨ããæè¦ã«åºã¥ãã¦ããã®ã§ãå¯èªæ§ã¨ãã¯ãã¢ã¬ã ãè¨ããããªã
æ¼ç®åã«ã¤ãã¦ãããã§ã«å®ç¾©ããã¦ãããã®ã¯ä¸æ¸ãããªãããã«ãªã£ã¦ãã®ã§å®å
¨ã§ãã?
ãã¨ãååã®ç±æ¥ã¯âªè弦æ¥åå ´çæã·ã¹ãã â«ã§ãã
Proc/lambda/Symbol/Methodã¸ã®æ¡å¼µ
- call
- compose
- with_args
- flip
- curry
Proc#
`Proc#<` 㯠`Proc#call`ã¸ã®aliasãªã®ã§ãProcã®å¼ã³åºãã¯ä»¥ä¸ã®ããã«æ¸ããã
f = lambda{|x| x.to_s } f < :foo # => "foo"
Proc#+@
Proc/lambda/Symbol/Methodã«åé æ¼ç®å+ãé©ç¨ããã¨ãto_procãå¼ã³åºãã
+:to_s # => #<Proc:0x007ff78aadaa78> +:to_s < :foo # => "foo"
Proc#compose
颿°åæã¯`Proc#compose`ã`>>`, `<<` ã§ã§ããã
`f.compose(g)`ã¯ãåæé¢æ°`lambda{|*args| f.call(g.call(*args)) }`ãçæãã¦è¿ãã
f = lambda{|x| x.to_s * 2 } g = lambda{|y| y.length } h = f.compose g # => #<Proc:0x007ff78aa2ab2> h.(:hoge) # => "44" ( == f.call(g.call(:hoge)) )
`Proc#compose`ã¯`<<` ã«aliasããã¦ãã
f << g # => f.compose(g) f << g < :hoge # => "44" ( == f.call(g.call(:hoge)) )
`>>`ã¯ãProc#compseãã¬ã·ã¼ãã¼ãå
¥ãæ¿ãã¦å¼ã³åºããçµæçã«ã`g.call(f.call(x))`ã«ãªã
f >> g # => g.compose(f) f >> g < :hoge # => "8" ( == g.call(f.call(:hoge)) )
Proc#with_args
`Proc#with_args`ã¯ã2弿°ä»¥éã®å¼æ°ãé¨åé©ç¨ãã颿°ãè¿ãã
f = lambda{|x, y, z| [x, y, z]} h = f.with_args(:a, :b) # => #<Proc:0x007ff78a9c5ca0> h.(:c) # => [:c, :a, :b] ( == f.call(:c, :a, :b) )
`Proc#with_args`ã¯`*`ã«aliasããã¦ããã
f = lambda{|x, y| [x, y]} f * :foo # => #<Proc:0x007ff78a987540> (== f.with_args(:foo) ) f * :foo < :bar # => [:bar, :foo] ( == f.with_args(:foo).call(:bar) )
Proc#flip
第1弿°ã¨ç¬¬2弿°ãå ¥ãããã颿°ãè¿ããçµæã®é¢æ°ã¯ã«ãªã¼åãããã
f = lambda{|x, y, z| [x, y, z]} h = f.flip # => #<Proc:0x007ff78a942fa> h.call(:a).call(:b).call(:c) # => [:b, :a, :c] (== f.curry.call(:b).call(:a).call(:b)) h < :a < :b < :c # => [:b, :a, :c] (== f.curry.call(:b).call(:a).call(:b))
`Proc#flip`ãå¼ã³åºãProcãå¯å¤é·å¼æ°ã®å ´åã¯ãæç¤ºçã«arityãæå®ãã¦filpãå¼ã³åºãå¿
è¦ãããã
arityã0ã¾ãã¯1ãªãã°ãä½ãããã«èªèº«ãè¿ãã
p = Proc.new{|*args| args.inspect } p.arity # => -1 p.flip(3).call(:a).(:b).(:c) # => "[:b, :a, :c]" p.flip(4).call(:a).(:b).(:c).(:d) # => "[:b, :a, :c, :d]"
ãã®ã¡ã½ãã㯠`~@` ã«aliaasããã¦ããã®ã§ãProcã«åé
æ¼ç®å`~`ãé©ç¨ãããã¨ã§å¼ã³åºããã¨ãã§ããã
ãã®éã«ã¯ãarityã®æå®ã¯ã§ããªãã
~f # => #<Proc:0x007ff78a8e22c> (== f.filp) ~f < :a < :b < :c # => [:b, :a, :c] (== f.filp.call(:b).call(:a).call(:b))
Symbol extensions
- to_method
Symbol#to_method
`Symbol#to_method`ã¯ã弿°ã®ãªãã¸ã§ã¯ãã«å¯¾ãã¦Object#methodãèªèº«ã弿°ã«å¼ã³åºã颿°ãçæãã¦è¿ãã
åé
æ¼ç®å`-`ã«aliasããã¦ããã
(-:index).call("foobarbaz") # => #<Method: String#index> (-:index).call("foobarbaz").call("bar") # => 3 (== "foobarbaz".index(3) ) -:index < "foobarbaz" # => #<Method: String#index> -:index < "foobarbaz" < "bar" # => 3 (== "foobarbaz".index(3) )
Class extensions
`Class#instance_method`ã `/`æ¼ç®åã§å¼ã³åºããã¨ãã§ãããããã¯ãå°ãclojureãæèããã
String / :index # => #<UnboundMethod: String#index>
UnboundMethod extensions
`UnboundMethod#bind`ã `<`æ¼ç®åã§å¼ã³åºããã¨ãã§ãããä¸è¨ã®`Class#/`ã¨çµã¿åãããã¨ã«ãã³ããæ¸ããã
String / :index # => #<UnboundMethod: String#index> String / :index < "foobarbaz" # => #<Method: String#index> String / :index < "foobarbaz" < "bar" # => 3 (== "foobarbaz".index(3) )
Object extensions
- obj.revapply(|>)
- obj._
- obj.disjunction(f)
Object#revapply
`Object#revapply` ã¯ãèªèº«ã渡ããã颿°ã«é©ç¨ãããScalazã®`|>`ãªã
revapplyã¨ããååã®ç±æ¥ã¯OCamlããã
f = lambda{|x| x * 2 } "foo".revapply(f) # => "fooffoo" (== f.call("foo") )
Object#_
`Object#_`ã¯ããªãã¸ã§ã¯ãããMethodãªãã¸ã§ã¯ããç°¡åã«åãåºãããã®ã·ã§ã¼ãã«ããã
"foobarbaz"._.index # => #<Method: String#index> "foobarbaz"._.index < "bar" # => 3 (== "foobarbaz".index("bar") ) 2._(:>=) # => #<Method: Fixnum#>=> [1, 2, 3].select(&2._(:>=)) # => [1, 2]( = [1, 2].select{|n| 2 >= n})
Object#disjunction
`Object#disjunction`ã¯ã弿°ã®é¢æ°ã«èªèº«ãé©ç¨ããçµæãnilã§ãªããã°ãããè¿ããnilã ã£ããã¬ã·ã¼ãã¼ãªãã¸ã§ã¯ãèªèº«ãè¿ãã
f = lambda{|x| x % 2 == 0 ? nil : x * 2} 2.disjunction(f) # => 2 (disjunction returns reciever object) 3.disjunction(f) # => 6 (disjunction returns f(3) )
