2011-07-14 10 views
37

w normalnej mapie Scala i płaskiej mapie różnią się tym, że flatMap zwróci dane do przetłumaczenia spłaszczone na liście. Jednak w dokumentacji Akka, map i flatMap wydają się robić coś innego?W kontraktach terminowych na Scala Akka, jaka jest różnica między mapą a mapą flat?

http://akka.io/docs/akka/1.1/scala/futures.html

mówi „Zwykle to działa całkiem dobrze, ponieważ oznacza, że ​​jest bardzo mało napowietrznych do uruchamiania funkcji szybkiego. Jeśli istnieje możliwość funkcji biorąc nietrywialne ilość czasu, aby przetwarzać może być lepiej mieć to zrobić jednocześnie, a do tego używamy flatMap:”

val f1 = Future { 
    "Hello" + "World" 
} 

val f2 = f1 flatMap {x => 
    Future(x.length) 
} 

val result = f2.get() 

Czy ktoś mógłby wyjaśnić, jaka jest różnica między mapie i flatMap tutaj kontraktami Akka?

+0

Myślę, że to pomaga lepiej to zrozumieć - dlaczego używamy płaskiej mapy http://raichoo.blogspot.com/2011/07/from-functions-to-monads-in-scala.html – Phil

Odpowiedz

59

W "normalnej" Scala (jak mówią), mapę i flatMap nie mają nic wspólnego z listami (zaznaczyć opcję na przykład).

Alexey podał poprawną odpowiedź. Teraz, jeśli chcesz wiedzieć, dlaczego potrzebujemy obu, pozwala na ładną składnię for podczas tworzenia kontraktów futures. Biorąc pod uwagę coś takiego:

val future3 = for(x <- future1; 
        y <- future2) yield (x + y) 

Kompilator przepisuje je jako:

val future3 = future1.flatMap(x => future2.map(y => x+y)) 

Jeśli zastosujemy podpis metody, należy zauważyć, że wyrażenie zwróci coś typu Future[A].

Załóżmy teraz tylko mapa została wykorzystana, kompilator mógłby zrobić coś takiego:

val future3 = future1.map(x => future2.map(y => x+y)) 

Jednak wynik whould zostały typu Future[Future[A]]. Dlatego musisz go spłaszczyć.

Aby dowiedzieć się o koncepcji tyłu, tutaj jest jednym z najlepszych wprowadzenie czytałem:

http://www.codecommit.com/blog/ruby/monads-are-not-metaphors

+7

Nie zdawałem sobie sprawy, że spłaszczanie może spłaszczyć typy, moim zdaniem było to, że spłaszczył listę obiektów w jedną listę. Tak więc, od mojego "starego" myślenia, myślałem, że to tylko przeszedłem listę i spłaszczyłem to. W rzeczywistości, spłaszczanie może spłaszczyć typy, jak powiedziałeś Future [Future [A]] jest analogiczny do List [List [A]]. Po wykonaniu tego kroku mogę lepiej to zrozumieć. – Phil

+0

Wielkie dzięki! Specjalnie na pocztę! Ten "średnik" wysadził mój umysł! – noru

34

Czy ktoś może wyjaśnić, jaka jest różnica między mapą a mapą FlatMap w przypadku kontraktów terminowych na Akka?

typu, w zasadzie:

flatMap[A](f: T => Future[A]): Future[A] 

map[A](f: T => A): Future[A] 
+0

Dokładnie to ma znaczenie kiedy masz metodę, która zwraca Future [A], ale zamiast zdobywać Future [Future [A]], chcesz Future [A]. – Mahesh

+0

Jeśli chcesz dowiedzieć się więcej o zasadach projektowania wokół 'map' i' flatMap', które są zakorzenione w abstrakcji Monady, proponuję ten wykład twórcy Scali, Martin Odersky https://www.coursera.org/ learn/progfun2/lecture/98tNE/lecture-1-4-monads –

1

jestem wklejając realizację dwóch metod tutaj. różnica w angielskich terminów jest poniżej i zwraca wynik funkcji jako nowej przyszłości

  /** Creates a new future by applying a function to the successful result of 
     * this future. If this future is completed with an exception then the new 
     * future will also contain this exception. 
     * 
     * $forComprehensionExamples 
     */ 
     def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] = { // transform(f, identity) 
     val p = Promise[S]() 
     onComplete { v => p complete (v map f) } 
     p.future 
     } 

     /** Creates a new future by applying a function to the successful result of 
     * this future, and returns the result of the function as the new future. 
     * If this future is completed with an exception then the new future will 
     * also contain this exception. 
     * 
     * $forComprehensionExamples 
     */ 
     def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): Future[S] = { 
     import impl.Promise.DefaultPromise 
     val p = new DefaultPromise[S]() 
     onComplete { 
      case f: Failure[_] => p complete f.asInstanceOf[Failure[S]] 
      case Success(v) => try f(v) match { 
      // If possible, link DefaultPromises to avoid space leaks 
      case dp: DefaultPromise[_] => dp.asInstanceOf[DefaultPromise[S]].linkRootOf(p) 
      case fut => fut.onComplete(p.complete)(internalExecutor) 
      } catch { case NonFatal(t) => p failure t } 
     } 
    p.future 
    } 

Od implementacji tą różnicą, że flatMap faktycznie wywołuje funkcję z wyniku, gdy obietnica kończy.

case Success(v) => try f(v) match 

Na dobry artykuł czytać: http // danielwestheide.com/blog/2013/01/16/the-neofici-przewodnik-do-scala-Part-9-obiecuje-i-future-in- ćwiczyć.html

Powiązane problemy