Who is this guy? • Mathias Sulser / εϧαʔɾϚςΟΞε @suls github.com/suls • Husband of one, father of two • Living and working in beautiful Sendai, Japan • Speaking: Swiss German, English, a bit Japanese & French
In 30 minutes from now • You will know • why you would want to use scalaz-stream • the basic building blocks of scalaz-stream • iteratively built a small report generation ϨϙʔτੜϓϩάϥϜͷྫΛ௨ͯ͡ scalaz-stream ͷ͍Ͳ͜ΖͱجຊతͳߏཁૉΛղઆ
If your program .. • consumes data (file, db, network, user input, ..) • transforms data • produces data (..) • runs once, repeatedly or infinitely .. then scalaz-streams might be worth looking at. σʔλΛফඅɾมɾੜ͢ΔϓϩάϥϜΛ࡞ΔͳΒ scalaz-stream Λߟྀ͢ΔՁ͕͋Δ
What just happened? • We set up a sequence of computations using Process • Then we “run” it to get its effect • And finally we “run” the effect Process ΛͬͯҰ࿈ͷܭࢉΛ४උ࣮ͯ͠ߦ (run) ͠ ͦΕʹΑͬͯಘͨ࡞༻Λ࠷ऴతʹ࣮ߦ (run) ͢Δ
More Basics • scalaz-stream is pull based • Process won’t produce a value until a Sink requests one • Back-pressure for free • Being lazy allows us to create infinite Processes • Process can be executed multiple times scalaz-stream ϓϧܕͳͷͰɺແݶ Process Λ࡞ͬͨΓɺ Process ΛԿ࣮ߦͨ͠ΓͰ͖Δ
case class TradeReport( datetime: DateTime, contract: String, lots: Int, price: BigDecimal, side: Side ) sealed trait Side case object Buy extends Side case object Sell extends Side Our Domain ചങϨϙʔτͷυϝΠϯ
What I haven’t told you • Process is a deterministic sequence of actions • scalaz-stream provides primitves for non- deterministic operations • merge operator to combine n Process • async.boundedQueue to fan out Process ܾఆੑͷΞΫγϣϯྻ͕ͩ scalaz-stream ඇܾఆੑԋࢉఏڙ͢Δ
> val p = Process("a", "b", "c") .to(q.enqueue) .onComplete(Process eval q.close) p : Process[Task, Unit] > val q = async.boundedQueue[String](1) q: sz.s.async.mutable.Queue[String] > val r = q.dequeue to io.stdOutLines r: Process[Task, Unit] ϑΝϯΞτͷͨΊͷඇಉظ༗ݶΩϡʔ
case class EndOfDayPosition( contract: Contract, position: Int ) val endOfDaySummary = writingTo("summary.csv") { q2.dequeue .pipe(summarize) .map(_.productIterator.mkString(",")) .prepend(Seq("contract,position")) .intersperse("\n") } val summarize = process1.fold( // etc. ) Consume 2/2 ࣍ͷ֓ཁΛੜ͢Δ
In 30 minutes from now • You will know • why you would want to use scalaz-stream • the basic building blocks of scalaz-stream • iteratively built a small report generation ͜ΕͰ͋ͳͨ scalaz-stream Λ͍ͨ͘ͳͬͨͣ