Transducers for Rubyists

Kajihiro Kazunori

@k2nr_

kichijojirb #3

Clojure

(let [text "hello, world"]
  (println text))
  • Created by Rich Hickey
  • Runs on Java Virtual Machine
  • Lisp dialect
  • Version 1.7 will be released soon
  • v1.7 includes Transducers

What is Transducers?

;;; before 1.7
(map inc (range 5))
; => (1 2 3 4 5)
(filter odd? (range 5))
; => (1 3)
(take 3 (range 5))
; => (0 1 2)

;;; from 1.7
(def mapping (map inc))
(sequence mapping (range 5))
; => (1 2 3 4 5)
(def filtering (filter odd?))
(sequence filtering (range 5))
; => (1 3)
(def taking (take 3))
(sequence taking (range 5))
; => (0 1 2)

Transducers are a new way to manipulate sequences

1

What is Transducers?

(def mapping (map inc))
(sequence mapping (range 5))
; => (1 2 3 4 5)

(transduce mapping + 0 (range 5)
; => 15

;; Transducers compose with ordinary function composition
(def xform (comp (filter odd?) (map inc)))
(sequence xform (range 5))
; => (2 4)
(transduce xform + 0 (range 5))
; => 6

More examples

 

なんでTransducersが必要なの?

(map inc (range 5))
; => (1 2 3 4 5)

なんでTransducersが必要なの?

(map inc (range 5))
; => (1 2 3 4 5)

output form

mapping function

input

  • 3つの要素が密結合している
  • mapはseqableしかinputにできない

なんでTransducersが必要なの?

(def mapping (map inc)) ; mapping transducer

; `sequence` is a transducible function
(sequence mapping (range 5)
; => (1 2 3 4 5)

; `transduce` is also a transducible function
(transduce mapping + 0 (range 5))
; => 15

コレクションの操作をTransducer と Transducible function に分割する

What is Transducers?

Transducers are independent from the context of their input and output sources [...]. Because transducers are decoupled from input or output sources, they can be used in many different processes - collections, streams, channels, observables, etc.

Transducers for Ruby

 
gem install transducers
require 'transducers'
T = Transducers
T.transduce(T.compose(T.map(:succ), T.filter(:even?)), :<<, [], 0..9)
# => [2, 4, 6, 8, 10]

Transducers for Ruby

 
require 'transducers'
T = Transducers
T.transduce(T.compose(T.map(:succ), T.filter(:even?)), :<<, [], 0..9)
# => [2, 4, 6, 8, 10]

DEMO

 
  • Arrayの代わりにstdinを使うtransducible functionを作る
  • 適用の過程をstdoutに出力するdebugger trasducerをつくる

Transducers for Rubyists

By k2nr

Transducers for Rubyists

  • 258