Iteratee explained.

1,337 views

Published on

Presentation from hotcode 2013 (http://www,hotcode.org)

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,337
On SlideShare
0
From Embeds
0
Number of Embeds
11
Actions
Shares
0
Downloads
6
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Iteratee explained.

  1. 1. Iteratee: функциональная потоковая обработкаРуслан Шевченко.
  2. 2. Iterateeструктуры данных (Iteratee, Enumerator, Iteratee)которые определяют состояние процессингапотока.●Разобраться что это такое●Построить с нуля подобные интерфейсы●Язык scala как псевдокод●Показать использование как OO- паттернаhttps://github.com/rssh/iteratee-article
  3. 3. IterateeEng. (ee) => rus (уемый)Trainee – тот кого тренируютIteratee – то, что итерируют
  4. 4. Tрадиционный подходtrait Iterator[A]{def next: Adef hasNext: Boolean}val s = initialStatewhile(it.hasNext) {s = doSomething(s,it.next)}
  5. 5. Наоборот:trait Iteratee[A,S]{def doSomething(whenNext: A,S => S)}
  6. 6. Наоборот:trait Iteratee0[A,S]{def doSomething(whenNext: A,S => S)}Fold: - есть в стандартной библиотекеtrait Collection[A] {...def foldLeft(x:S)(f:(S,A)=>S)...}
  7. 7. Наоборот:trait Iteratee[A,S]{def doSomething(whenNext: A,S => S)}Fold: - есть в стандартной библиотекеtrait Collection[A] {...def foldLeft(x:S)(f:(S,A)=>S)...}
  8. 8. Fold - свертка1. Отредуцировать все элементы коллекциис помощью какой-то операцииCollection[A]: def foldLeft[S](s0:S)((S,A)=>S)(1 to 10) foldLeft ( _ + _)2. Произвести разбор случаев и вернуть значениеодного типа:Either[A,B]: def fold[X](fa: A=>X, fb: B=>X)Left(“problem x”).fold[String]( “error:” + _ ,“ok:” + _ )
  9. 9. Fold - свертка1. Отредуцировать все элементы коллекциис помощью какой-то операцииCollection[A]: def foldLeft[S](s0:S)((S,A)=>S)(1 to 10) foldLeft ( _ + _)2. Произвести разбор случаев и вернутьзначение одного типа:Either[A,B]: def fold[X](fa: A=>X, fb: B=>X)Left(“problem x”).fold[String]( “error:” + _ ,“ok:” + _ )
  10. 10. Коллекция – это то, что дает нам foldtrait Iteratee1[A,S]{def fold( whenNext: (S, A) => S,whenEof: S => S)}
  11. 11. Коллекция – это то что, дает нам foldtrait Iteratee1[A,S]{def fold( whenNext: (S, A) => S,whenEof: S => S)}def run(input,state) =if (!input.isEmpty && state.isDone) {state = whenNext(state, input.readElement)run(input, state)} else {whenEof(state)}
  12. 12. Коллекция – это то, что дает нам foldtrait Iteratee1[A,S]{def fold( whenNext: (S, A) => S,whenEof: S => S)}def run(input,state) =if (!input.isEmpty && !state.isDone) {state = whenNext(state, input.readElement)run(input, state)} else {whenEof(state)}
  13. 13. trait Iteratee2[A,S]{def fold(whenNext: A => (Iteratee[A,S],S),whenEnd: S => S)}Переходом в следующее состояние управляетkлиент (тот, кто вызывает fold)
  14. 14. trait Iteratee3[A,S]{def fold(whenNext: (A => Iteratee[A,S]) => S),whenEnd: S => S)}Переходом в следующее состояние управляетколлекция
  15. 15. trait Iteratee3[A,S]{def fold(whenNext: (A => Iteratee[A,S]) => S),whenEnd: S => S)}
  16. 16. trait Iteratee4[A,S]{def fold[B](whenNext: (A => Iteratee[A,S]) => B),whenEnd: S => B)}
  17. 17. trait Iteratee4[A,S]{def fold[B](whenNext: (A => Iteratee[A,S]) => B),whenEnd: S => B)}
  18. 18. def nextStep = fold( identity // f => f,(s:S) => Function1.constant(this));def isDone = fold( f => false,(s:S) => true)
  19. 19. trait Iteratee4[A,S]{def fold[B](whenNext: (A => Iteratee[A,S]) => B),whenEnd: S => B)}Секунду – давайте введем еще одно преобразование:В текущем интерфейсаВведем условное получение следующего элемента
  20. 20. trait Iteratee5[A,S]{def fold[B](whenNext: (Input[A]Input[A] => Iteratee[A,S]) => B),whenEnd: S => B)}sealed trait Input[+A]case class El[+A] extends Input[A]case object Eol extends Input[Nothing]+ ....
  21. 21. sealed trait Input[+A]case class El[+A] extends Input[A]case object Eof extends Input[Nothing]+ ....
  22. 22. case class Done[A,S](s:S) extends Iteratee4[A,S]{Def fold[B] ( whenNext: (Input[A] => Iteratee4[A,S])=>B,whenDone: S => S) =whenDone(s)}
  23. 23. sum first N [collect]
  24. 24. case class Collect[A](s:String) extends Iteratee[A,String]{def fold[B](onNext: (Input[A] => Iteratee[A,String])=>B,onDone: String => B) =onNext { case Input.El(a) => Collect(s + a.toString)case Input.EOF => Done(s)}}
  25. 25. case class Collect[A](s:String) extends Iteratee[A,String]{def fold[B](onNext: (Input[A] => Iteratee[A,String])=>B,onDone: String => B) =onNext { case Input.El(a) => Collect(s + a.toString)case Input.EOF => Done(s)}}
  26. 26. case class Collect[A](s:String) extends Iteratee[A,String]{def fold[B](onNext: (Input[A] => Iteratee[A,String])=>B,onDone: String => B) =onNext { case Input.El(a) => Collect(s + a.toString)case Input.EOF => Done(s)}}
  27. 27. EnumeratorГенератор элементов
  28. 28. EnumeratorГенератор элементов
  29. 29. Enumerator:trait Enumerator[A]{def apply[S] (it: Iteratee[S,A]): Iteratee[S,A]}Сгенерировать элемент == вызвать его обработчик (fold)
  30. 30. case class ListEnumerator[A](l:List[A]) extends MyEnumerator[A]{def apply(it: MyIteratee4[S,A]) =l.foldLeft(it)( (it,e) => it.fold( step => step(Input.El(e)),Function.const(it)))}
  31. 31. ComposeEnumerator(сгенерировать 10 елемент, а потом еще 10)Iteratee(принять заголовок пакета, а потом сам пакет)
  32. 32. ComposeEnumerator(сгенерировать 10 елемент, а потом еще 10)def compose(x: Enumerator[A], y:Enumerator[A]) =new Enumerator[A] {def apply[S](it: Iteratee[A,S]) = y(x(it))}
  33. 33. ComposeEnumerator(сгенерировать 10 елемент, а потом еще 10)def compose(x: Enumerator[A], y:Enumerator[A]) =new Enumerator[A] {def apply[S](it: Iteratee[A,S]) = y(x(it))}
  34. 34. ComposeIteratee(принять заголовок пакета, а потом сам пакет)def compose[A,S](frs: Iteratee[A,S], snd:Iteratee[A,S]) =new Iteratee[A,S] {def fold[B](onNext: (Input[A] => Iteratee[A,S])=>B,onDone: S => B) =frs.fold( step => onNext(compose(step(_),snd)),s => snd.fold(onNext,onDone))}Первое намерение:
  35. 35. ComposeIteratee -- problemsdef compose[A,S](x: MyIteratee[A,S], y:MyIteratee[A,S]) =new MyIteratee[A,S] {def fold[B](onNext: (Input[A] => MyIteratee[A,S])=>B,onDone: S => B) =frs.fold( step => onNext(compose(step(_),snd)),s => snd.fold(onNextonNext,onDone))}Теряем символ
  36. 36. Iteratee - уточнение сигнатурыtrait Iteratee5[A,S]{def fold[B](whenNext: (Input[A] => Iteratee[A,S]) => B),whenEnd: S => B)}old
  37. 37. Iteratee - уточнение сигнатурыtrait Iteratee5[A,S]{def fold[B](whenNext: (Input[A] => Iteratee[A,S]) => B),whenEnd: S => B)}old
  38. 38. Iteratee - уточнение сигнатурыtrait Iteratee6[A,S]{def fold[B](whenNext: (Input[A] => Iteratee[A,S]) => B),whenDone: (Input[A], S)(Input[A], S) => B)}new
  39. 39. sealed trait Input[+A]case class El[+A] extends Input[A]case object Eol extends Input[Nothing]case object EmptyEmpty extends Input[Nothing]
  40. 40. def compose[A,S](frs: MyIteratee[A,S], snd:MyIteratee[A,S]) =new MyIteratee[A,S] {def fold[B](onNext: (Input[A] => MyIteratee[A,S])=>B,onDone: (Input[A],S) => B) =frs.fold( step => onNext(compose(step(_),snd)),(in,s) => in match {case Input.Eof => onDone(in,s)case Input.Empty => snd.fold(in,s)case Input.El(a) =>PutOne(a)(snd).fold(onNext,onDone)})}
  41. 41. Enumeratee = Iteratee + Enumerator
  42. 42. Enumeratee = Iteratee + Enumerator
  43. 43. Enumeratee = Iteratee + Enumeratortrait Enumeratee[From, To]{def transform[S](it: Iteratee[From,S]): Iteratee[To, S]= JoinIteratee(applyOn(it))def applyOn[A](it: Iteratee[From,S]):Iteratee[From,Iteratee[To,S]]}
  44. 44. case class MapEnumeratee[From,To](f:From => To)extends Enumeratee[From,To]{def applyOn[S](it: Iteratee[To,S]): Iteratee[From, Iteratee[To,S]]=new Iteratee[From, Iteratee[To,S]] {def fold[B](onNext, onDone) =it.fold(step => onNext( x => applyOn(step(x map f)) ),(in, s) => onDone(Input.Empty,Done(in,s)))}}Enumeratee: примерДоопределить map на Input: Input.El(x) map (f) = Input.El(f(x))Input.Eof map f = Input.EofInput.Empy map f = Input.Empty
  45. 45. Итого:Абстракции генерирования и потоковой обработки:Iteratee -- конечное звено обработки элементов (fold)Enumerator – генератор элементов (apply)Enumeratee -- преобразователь (transform)Строить нетривиальные процессы потоковой обработкиКомбинировать в функциональном стиле
  46. 46. FP/OOPМожно использовать как OOP паттернFold не нуженtrait OOIteratee[A,S]{def next(inp: Input[A]): OOIteratee[A,S]def isDone: Boolean}
  47. 47. trait OOIteratee[A,S]{def next(inp: Input[A]): OOIteratee[A,S]def whenDone: Option[(Input[A],S)]def isDone: Boolean = whenDone.isDefineddef whenNext: Option[Input[A]=>MyIteratee[A,S]] =if (isDone) None else Some(next(_))}
  48. 48. def fold[B](onNext: (Input[A]=>MyIteratee[A,S])=>B,onDone: (Input[A],S) => B): B =if (!isDone) {onNext( step => next(step) )} else {onDone(whenDone.get)}
  49. 49. Использование в реальной жизниScala - обработка потоков в playhttp://www.playframework.com/documentation/2.1.1/IterateesC# -- Reactice Extensions (Rx)http://msdn.microsoft.com/en-us/data/gg577609.aspxHaskell -- Iteratee IO.http://www.haskell.org/haskellwiki/Iteratee_I/O
  50. 50. Руслан Шевченкogithub : @rsshhttps://github.com/rssh/iteratee-articletwitter: @rssh1http://www.gosave.comПомогаем монетизировать мобильные приложения

×