Re: Filter on future doesn't make sense
Roland Kuhn <[email protected]> Fri, 1 Jul 2016 15:06:37 +0200
| Newsgroups | gmane.comp.lang.scala |
|---|---|
| Message-ID | <[email protected]> |
--Apple-Mail=_03E3AE74-F2CE-4CA7-AC26-4B2FA2037A21 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=UTF-8 The difference is that Option does not have onComplete: if you restrict you= rself to the Option API then Future behaves observably in the same way. If = you want to have something like onComplete you should look at Either[NoSuch= ElementException, T]#fold. In general there is no .filter on monads because that would require the exp= licit ability to represent emptiness (which is not part of the contract); t= he success path for the combinators could be seen as such a representation = and it is indeed often used as such, so Future is quite well-behaved in thi= s regard. Another comment I=E2=80=99d like to make on the discussed change = is that it is not reasonable to expect that the result of filtering returns= a different type than the original one=E2=80=94no other container has this= behavior. Regards, Roland > 1 juli 2016 kl. 14:54 skrev Oliver Ruebenacker <[email protected]>: >=20 >=20 > Hello, >=20 > Looks like sometimes you do get an exception: >=20 > Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_45= ). > Type in expressions for evaluation. Or try :help. >=20 > scala> import scala.concurrent.Future > import scala.concurrent.Future >=20 > scala> import scala.concurrent.ExecutionContext.Implicits.global > import scala.concurrent.ExecutionContext.Implicits.global >=20 > scala> Future{1}.onComplete { case _ =3D> println("Complete!") } >=20 > scala> Complete! >=20 >=20 > scala> Future{1}.filter(_ =3D=3D 0).onComplete { case _ =3D> println("Com= plete!") } > Complete! >=20 > scala> import scala.util.{Success, Failure } > import scala.util.{Success, Failure} >=20 > scala> Future{1}.filter(_ =3D=3D 0).onComplete { > | case Success(value) =3D> println(value) > | case Failure(ex) =3D> println(ex) > | } >=20 > java.util.NoSuchElementException: Future.filter predicate is not satisfie= d > scala> >=20 > Best, Oliver >=20 >=20 > On Fri, Jul 1, 2016 at 5:44 AM, Viktor Klang <[email protected] <mai= lto:[email protected]>> wrote: > I think you are conflating the notion of optionality here. >=20 > option.filter(p).map(f).foreach(println) >=20 > behaves exactly like >=20 > future.filter(p).map(f).foreach(println) >=20 > --=20 > Cheers, > =E2=88=9A >=20 > On Jul 1, 2016 11:36 AM, "Avi Levi" <[email protected] <mailto:123avi@gmai= l.com>> wrote: > Correct, just on future you get an exception if element does not pass the= filter. Wouldn't it be better if we can get something that express an empt= y future? >=20 > On Jul 1, 2016 12:30 PM, "Viktor Klang" <[email protected] <mailto:v= [email protected]>> wrote: > But you don't get an exception on the success path. All operations on the= success path will be skipped, just as for Option. >=20 > --=20 > Cheers, > =E2=88=9A >=20 > On Jul 1, 2016 10:35 AM, "Avi Levi" <[email protected] <mailto:123avi@gmai= l.com>> wrote: > Hi Victor , > I totally agree that expectations are subjective . > But like you said a filter on List will return a List if no element compl= y than we will get Nil which represents an empty container (empty list) > a filter on option will return a option if the element doesn't comply tha= n we will get None which represents an empty container=20 > following the same logic a filter on future should return something that = express empty container , defiantly not an exception, because it is not an = exception we do intend to filter those elements. >=20 > =20 >=20 > 2016-07-01 10:50 GMT+03:00 Viktor Klang <[email protected] <mailto:v= [email protected]>>: > Hi Avi, >=20 > I see what you mean. >=20 > I'd want to avoid discussing expectation since it is subjective. I will h= owever note that the actualnsemantics of the filter method on Future needs = improvement: http://www.scala-lang.org/api/2.11.8/index.html#scala.concurre= nt.Future@filter(p:T=3D <http://www.scala-lang.org/api/2.11.8/index.html#sc= ala.concurrent.Future@filter(p:T=3D>>Boolean)(implicitexecutor:scala.concur= rent.ExecutionContext):scala.concurrent.Future[T] >=20 > As for might not return the value, the same goes for all filter-methods: >=20 > List returns List, but it might not have any elements at all. Option retu= rns Option but can be Some or None, Future is either Success or Failure. >=20 > If success has an optionality aspect in your usage, use Future of Option = to express that, that would be my recommendation. >=20 > --=20 > Cheers, > =E2=88=9A >=20 > On Jul 1, 2016 9:20 AM, "Avi Levi" <[email protected] <mailto:123avi@gmail= .com>> wrote: > Thanks Victor, > Of course it can be implemented as you suggested. But still I can argue t= hat the current implementation is not "really filtering" the results as one= might expect and less expressive if it might or not return the value than = Option is more expressive, don't you agree? >=20 > On Jul 1, 2016 10:06 AM, "Viktor Klang" <[email protected] <mailto:v= [email protected]>> wrote: > Hi Avi, >=20 > Use Fututre[Option[Int]] if you want to deal with Some/None as a result o= f filter ( f.map(_.filter(p) ) (alt. see monad transformers) >=20 > --=20 > Cheers, > =E2=88=9A >=20 > On Jul 1, 2016 8:53 AM, "Avi Levi" <[email protected] <mailto:123avi@gmail= .com>> wrote: > I was trying to figure out what should I accept when filtering over a fut= ure . > the current implementation yields either a T or an exception which kind o= f breaks referential transparency (doesn't it ?) . > on the other hand what can I expect given this expression=20 > def foo(i:Int):Future[Int] >=20 > the type result of=20 >=20 > foo(1).filter(_ % 2 =3D=3D 0) >=20 >=20 >=20 > I.M.H.O I would expect it to yield Option[T] which makes more sense to e= xpress that we might get a value that pass the filter or not . is that make= sense ? >=20 > Cheers > Avi=20 >=20 > --=20 > You received this message because you are subscribed to the Google Groups= "scala-language" group. > To unsubscribe from this group and stop receiving emails from it, send an= email to [email protected] <mailto:scala-languag= [email protected]>. > For more options, visit https://groups.google.com/d/optout <https://group= s.google.com/d/optout>. >=20 > --=20 > You received this message because you are subscribed to a topic in the Go= ogle Groups "scala-language" group. > To unsubscribe from this topic, visit https://groups.google.com/d/topic/s= cala-language/wpGOB8f7qmY/unsubscribe <https://groups.google.com/d/topic/sc= ala-language/wpGOB8f7qmY/unsubscribe>. > To unsubscribe from this group and all its topics, send an email to scala= [email protected] <mailto:scala-language+unsubscribe@g= ooglegroups.com>. > For more options, visit https://groups.google.com/d/optout <https://group= s.google.com/d/optout>. >=20 > --=20 > You received this message because you are subscribed to the Google Groups= "scala-language" group. > To unsubscribe from this group and stop receiving emails from it, send an= email to [email protected] <mailto:scala-languag= [email protected]>. > For more options, visit https://groups.google.com/d/optout <https://group= s.google.com/d/optout>. >=20 > --=20 > You received this message because you are subscribed to a topic in the Go= ogle Groups "scala-language" group. > To unsubscribe from this topic, visit https://groups.google.com/d/topic/s= cala-language/wpGOB8f7qmY/unsubscribe <https://groups.google.com/d/topic/sc= ala-language/wpGOB8f7qmY/unsubscribe>. > To unsubscribe from this group and all its topics, send an email to scala= [email protected] <mailto:scala-language+unsubscribe@g= ooglegroups.com>. > For more options, visit https://groups.google.com/d/optout <https://group= s.google.com/d/optout>. >=20 >=20 >=20 > --=20 > Sincerely, > Avi Levi > m: +972-52-3459959 <tel:%2B972-52-3459959> > <https://www.linkedin.com/in/leviavi> > https://about.me/avi.levi <https://about.me/avi.levi> >=20 > --=20 > You received this message because you are subscribed to the Google Groups= "scala-language" group. > To unsubscribe from this group and stop receiving emails from it, send an= email to [email protected] <mailto:scala-languag= [email protected]>. > For more options, visit https://groups.google.com/d/optout <https://group= s.google.com/d/optout>. >=20 > --=20 > You received this message because you are subscribed to a topic in the Go= ogle Groups "scala-language" group. > To unsubscribe from this topic, visit https://groups.google.com/d/topic/s= cala-language/wpGOB8f7qmY/unsubscribe <https://groups.google.com/d/topic/sc= ala-language/wpGOB8f7qmY/unsubscribe>. > To unsubscribe from this group and all its topics, send an email to scala= [email protected] <mailto:scala-language+unsubscribe@g= ooglegroups.com>. > For more options, visit https://groups.google.com/d/optout <https://group= s.google.com/d/optout>. >=20 > --=20 > You received this message because you are subscribed to the Google Groups= "scala-language" group. > To unsubscribe from this group and stop receiving emails from it, send an= email to [email protected] <mailto:scala-languag= [email protected]>. > For more options, visit https://groups.google.com/d/optout <https://group= s.google.com/d/optout>. >=20 > --=20 > You received this message because you are subscribed to the Google Groups= "scala-language" group. > To unsubscribe from this group and stop receiving emails from it, send an= email to [email protected] <mailto:scala-languag= [email protected]>. > For more options, visit https://groups.google.com/d/optout <https://group= s.google.com/d/optout>. >=20 >=20 >=20 > --=20 > Oliver Ruebenacker > Senior Software Engineer, Diabetes Portal <http://www.type2diabetesgeneti= cs.org/>, Broad Institute <http://www.broadinstitute.org/> >=20 >=20 > --=20 > You received this message because you are subscribed to the Google Groups= "scala-language" group. > To unsubscribe from this group and stop receiving emails from it, send an= email to [email protected] <mailto:scala-languag= [email protected]>. > For more options, visit https://groups.google.com/d/optout <https://group= s.google.com/d/optout>. --=20 You received this message because you are subscribed to the Google Groups "= scala-language" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to [email protected]. For more options, visit https://groups.google.com/d/optout. --Apple-Mail=_03E3AE74-F2CE-4CA7-AC26-4B2FA2037A21 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=UTF-8 <html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset= =3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s= pace; -webkit-line-break: after-white-space;" class=3D"">The difference is = that Option does not have onComplete: if you restrict yourself to the Optio= n API then Future behaves observably in the same way. If you want to have s= omething like onComplete you should look at <font face=3D"Courier" class=3D= "">Either[NoSuchElementException, T]#fold</font>.<div class=3D""><br class= =3D""></div><div class=3D"">In general there is no .filter on monads becaus= e that would require the explicit ability to represent emptiness (which is = not part of the contract); the success path for the combinators could be se= en as such a representation and it is indeed often used as such, so Future = is quite well-behaved in this regard. Another comment I=E2=80=99d like to m= ake on the discussed change is that it is not reasonable to expect that the= result of filtering returns a different type than the original one=E2=80= =94no other container has this behavior.</div><div class=3D""><br class=3D"= "></div><div class=3D"">Regards,</div><div class=3D""><br class=3D""></div>= <div class=3D"">Roland<br class=3D""><div class=3D""><br class=3D""><div><b= lockquote type=3D"cite" class=3D""><div class=3D"">1 juli 2016 kl. 14:54 sk= rev Oliver Ruebenacker <<a href=3D"mailto:[email protected]" class=3D"">c= [email protected]</a>>:</div><br class=3D"Apple-interchange-newline"><div = class=3D""><div dir=3D"ltr" class=3D""><div class=3D""><div class=3D""><br = class=3D""></div> Hello,<br class=3D""><br class=3D= ""></div> Looks like sometimes you do get an exception:<br class=3D""= ><div class=3D""><div class=3D""><br class=3D""><b class=3D""><span style= =3D"font-family:monospace,monospace" class=3D"">Welcome to Scala 2.11.8 (Ja= va HotSpot(TM) 64-Bit Server VM, Java 1.8.0_45).<br class=3D"">Type in expr= essions for evaluation. Or try :help.<br class=3D""><br class=3D"">scala>= ; import scala.concurrent.Future<br class=3D"">import scala.concurrent.Futu= re<br class=3D""><br class=3D"">scala> import scala.concurrent.Execution= Context.Implicits.global<br class=3D"">import scala.concurrent.ExecutionCon= text.Implicits.global<br class=3D""><br class=3D"">scala> Future{1}.onCo= mplete { case _ =3D> println("Complete!") }<br class=3D""><br class=3D""= >scala> Complete!<br class=3D""><br class=3D""><br class=3D"">scala> = Future{1}.filter(_ =3D=3D 0).onComplete { case _ =3D> println("Complete!= ") }<br class=3D"">Complete!<br class=3D""><br class=3D"">scala> import = scala.util.{Success, Failure }<br class=3D"">import scala.util.{Success, Fa= ilure}<br class=3D""><br class=3D"">scala> Future{1}.filter(_ =3D=3D 0).= onComplete {<br class=3D""> | case Success(value) = =3D> println(value)<br class=3D""> | case Failur= e(ex) =3D> println(ex)<br class=3D""> | }<br cla= ss=3D""><br class=3D"">java.util.NoSuchElementException: Future.filter pred= icate is not satisfied<br class=3D"">scala></span></b><br class=3D""><br= class=3D""></div><div class=3D""> Best, Oliver<br = class=3D""></div><div class=3D""><br class=3D""></div></div></div><div clas= s=3D"gmail_extra"><br class=3D""><div class=3D"gmail_quote">On Fri, Jul 1, = 2016 at 5:44 AM, Viktor Klang <span dir=3D"ltr" class=3D""><<a href=3D"m= ailto:[email protected]" target=3D"_blank" class=3D"">viktor.klang@gma= il.com</a>></span> wrote:<br class=3D""><blockquote class=3D"gmail_quote= " style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><= p dir=3D"ltr" class=3D"">I think you are conflating the notion of optionali= ty here.</p><p dir=3D"ltr" class=3D"">option.filter(p).map(f).foreach(print= ln)</p><p dir=3D"ltr" class=3D"">behaves exactly like</p><p dir=3D"ltr" cla= ss=3D"">future.filter(p).map(f).foreach(println)</p><span class=3D"HOEnZb">= <font color=3D"#888888" class=3D""><p dir=3D"ltr" class=3D"">-- <br class= =3D""> Cheers,<br class=3D""> =E2=88=9A</p></font></span><div class=3D"HOEnZb"><div class=3D"h5"> <div class=3D"gmail_quote">On Jul 1, 2016 11:36 AM, "Avi Levi" <<a href= =3D"mailto:[email protected]" target=3D"_blank" class=3D"">[email protected]<= /a>> wrote:<br type=3D"attribution" class=3D""><blockquote class=3D"gmai= l_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left= :1ex"><p dir=3D"ltr" class=3D"">Correct, just on future you get an exceptio= n if element does not pass the filter. Wouldn't it be better if we can get = something that express an empty future? </p> <div class=3D"gmail_quote">On Jul 1, 2016 12:30 PM, "Viktor Klang" <<a h= ref=3D"mailto:[email protected]" target=3D"_blank" class=3D"">viktor.k= [email protected]</a>> wrote:<br type=3D"attribution" class=3D""><blockquot= e class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc sol= id;padding-left:1ex"><p dir=3D"ltr" class=3D"">But you don't get an excepti= on on the success path. All operations on the success path will be skipped,= just as for Option.</p><p dir=3D"ltr" class=3D"">-- <br class=3D""> Cheers,<br class=3D""> =E2=88=9A</p> <div class=3D"gmail_quote">On Jul 1, 2016 10:35 AM, "Avi Levi" <<a href= =3D"mailto:[email protected]" target=3D"_blank" class=3D"">[email protected]<= /a>> wrote:<br type=3D"attribution" class=3D""><blockquote class=3D"gmai= l_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left= :1ex"><div dir=3D"rtl" class=3D""><div dir=3D"ltr" class=3D"">Hi Victor ,</= div><div dir=3D"ltr" class=3D"">I totally agree that expectations are subje= ctive .</div><div dir=3D"ltr" class=3D"">But like you said a filter on List= will return a List if no element comply than we will get Nil which represe= nts an empty container (empty list)</div><div dir=3D"ltr" class=3D"">a filt= er on option will return a option if the element doesn't comply than we wil= l get None which represents an empty container </div><div dir=3D"ltr" = class=3D"">following the same logic a filter on future should return someth= ing that express empty container , defiantly not an exception, because it i= s not an exception we do intend to filter those elements.</div><div dir=3D"= ltr" class=3D""><br class=3D""></div><div dir=3D"ltr" class=3D""> </di= v></div><div class=3D"gmail_extra"><br class=3D""><div class=3D"gmail_quote= "><div dir=3D"ltr" class=3D"">2016-07-01 10:50 GMT+03:00 Viktor Klang <span= dir=3D"ltr" class=3D""><<a href=3D"mailto:[email protected]" targe= t=3D"_blank" class=3D"">[email protected]</a>></span>:</div><blockq= uote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc = solid;padding-left:1ex"><p dir=3D"ltr" class=3D"">Hi Avi,</p><p dir=3D"ltr"= class=3D"">I see what you mean.</p><p dir=3D"ltr" class=3D"">I'd want to a= void discussing expectation since it is subjective. I will however note tha= t the actualnsemantics of the filter method on Future needs improvement: <a= href=3D"http://www.scala-lang.org/api/2.11.8/index.html#scala.concurrent.F= uture@filter(p:T=3D" target=3D"_blank" class=3D"">http://www.scala-lang.org= /api/2.11.8/index.html#scala.concurrent.Future@filter(p:T=3D</a>>Boolean= )(implicitexecutor:scala.concurrent.ExecutionContext):scala.concurrent.Futu= re[T]</p><p dir=3D"ltr" class=3D"">As for might not return the value, the s= ame goes for all filter-methods:</p><p dir=3D"ltr" class=3D"">List returns = List, but it might not have any elements at all. Option returns Option but = can be Some or None, Future is either Success or Failure.</p><p dir=3D"ltr"= class=3D"">If success has an optionality aspect in your usage, use Future = of Option to express that, that would be my recommendation. </p><span class= =3D""><font color=3D"#888888" class=3D""><p dir=3D"ltr" class=3D"">-- <br c= lass=3D""> Cheers,<br class=3D""> =E2=88=9A</p></font></span><div class=3D""><div class=3D""> <div class=3D"gmail_quote">On Jul 1, 2016 9:20 AM, "Avi Levi" <<a href= =3D"mailto:[email protected]" target=3D"_blank" class=3D"">[email protected]<= /a>> wrote:<br type=3D"attribution" class=3D""><blockquote class=3D"gmai= l_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left= :1ex"><p dir=3D"ltr" class=3D"">Thanks Victor,<br class=3D""> Of course it can be implemented as you suggested. But still I can argue th= at the current implementation is not "really filtering" the results as one = might expect and less expressive if it might or not return the value than O= ption is more expressive, don't you agree? </p> <div class=3D"gmail_quote">On Jul 1, 2016 10:06 AM, "Viktor Klang" <<a h= ref=3D"mailto:[email protected]" target=3D"_blank" class=3D"">viktor.k= [email protected]</a>> wrote:<br type=3D"attribution" class=3D""><blockquot= e class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc sol= id;padding-left:1ex"><p dir=3D"ltr" class=3D"">Hi Avi,</p><p dir=3D"ltr" cl= ass=3D"">Use Fututre[Option[Int]] if you want to deal with Some/None as a r= esult of filter ( f.map(_.filter(p) ) (alt. see monad transformers)</p><p d= ir=3D"ltr" class=3D"">-- <br class=3D""> Cheers,<br class=3D""> =E2=88=9A</p> <div class=3D"gmail_quote">On Jul 1, 2016 8:53 AM, "Avi Levi" <<a href= =3D"mailto:[email protected]" target=3D"_blank" class=3D"">[email protected]<= /a>> wrote:<br type=3D"attribution" class=3D""><blockquote style=3D"marg= in:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex" class=3D""><div = dir=3D"ltr" class=3D"">I was trying to figure out what should I accept when= filtering over a future .<div class=3D"">the current implementation yields= either a T or an exception which kind of breaks referential transparency (= doesn't it ?) .</div><div class=3D"">on the other hand what can I expect gi= ven this expression </div><div class=3D""><p class=3D""><span class=3D= ""><i class=3D"">def foo(i:Int):Future[Int]</i></span></p><p class=3D""><sp= an class=3D"">the type result of </span></p><p class=3D""><i class=3D"= ">foo(1).filter(_ % 2 =3D=3D 0)</i></p><p class=3D""><span class=3D""><br c= lass=3D""></span></p></div><div class=3D"">I.M.H.O I would expect it to yie= ld Option[T] which makes more sense to express that we might get a va= lue that pass the filter or not . is that make sense ?</div><div class=3D""= ><br class=3D""></div><div class=3D"">Cheers</div><font color=3D"#888888" c= lass=3D""><div class=3D"">Avi </div></font></div><font color=3D"#88888= 8" class=3D""><div class=3D""><br class=3D"webkit-block-placeholder"></div> -- <br class=3D""> You received this message because you are subscribed to the Google Groups "= scala-language" group.<br class=3D""> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:[email protected]" targ= et=3D"_blank" class=3D"">[email protected]</a>.<b= r class=3D""> For more options, visit <a href=3D"https://groups.google.com/d/optout" targ= et=3D"_blank" class=3D"">https://groups.google.com/d/optout</a>.<br class= =3D""> </font></blockquote></div><div class=3D""><br class=3D"webkit-block-placeho= lder"></div> -- <br class=3D""> You received this message because you are subscribed to a topic in the Goog= le Groups "scala-language" group.<br class=3D""> To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/= d/topic/scala-language/wpGOB8f7qmY/unsubscribe" target=3D"_blank" class=3D"= ">https://groups.google.com/d/topic/scala-language/wpGOB8f7qmY/unsubscribe<= /a>.<br class=3D""> To unsubscribe from this group and all its topics, send an email to <a href= =3D"mailto:[email protected]" target=3D"_blank" c= lass=3D"">[email protected]</a>.<br class=3D""> For more options, visit <a href=3D"https://groups.google.com/d/optout" targ= et=3D"_blank" class=3D"">https://groups.google.com/d/optout</a>.<br class= =3D""> </blockquote></div><div class=3D""><br class=3D"webkit-block-placeholder"><= /div> -- <br class=3D""> You received this message because you are subscribed to the Google Groups "= scala-language" group.<br class=3D""> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:[email protected]" targ= et=3D"_blank" class=3D"">[email protected]</a>.<b= r class=3D""> For more options, visit <a href=3D"https://groups.google.com/d/optout" targ= et=3D"_blank" class=3D"">https://groups.google.com/d/optout</a>.<br class= =3D""> </blockquote></div><div class=3D""><br class=3D"webkit-block-placeholder"><= /div> -- <br class=3D""> You received this message because you are subscribed to a topic in the Goog= le Groups "scala-language" group.<br class=3D""> To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/= d/topic/scala-language/wpGOB8f7qmY/unsubscribe" target=3D"_blank" class=3D"= ">https://groups.google.com/d/topic/scala-language/wpGOB8f7qmY/unsubscribe<= /a>.<br class=3D""> To unsubscribe from this group and all its topics, send an email to <a href= =3D"mailto:[email protected]" target=3D"_blank" c= lass=3D"">[email protected]</a>.<br class=3D""> For more options, visit <a href=3D"https://groups.google.com/d/optout" targ= et=3D"_blank" class=3D"">https://groups.google.com/d/optout</a>.<br class= =3D""> </div></div></blockquote></div><br class=3D""><br clear=3D"all" class=3D"">= <div class=3D""><br class=3D""></div>-- <br class=3D""><div data-smartmail= =3D"gmail_signature" class=3D""><div dir=3D"rtl" class=3D""><div class=3D""= ><div dir=3D"rtl" class=3D""><div class=3D""><div dir=3D"rtl" class=3D""><d= iv dir=3D"ltr" class=3D""><span style=3D"color:rgb(51,51,51);font-family:pr= oxima-nova-1,proxima-nova-2,Tahoma,Helvetica,Verdana,sans-serif;font-size:1= 4px;line-height:21px" class=3D"">Sincerely,</span><br style=3D"color:rgb(51= ,51,51);font-family:proxima-nova-1,proxima-nova-2,Tahoma,Helvetica,Verdana,= sans-serif;font-size:14px;line-height:21px" class=3D""><span style=3D"color= :rgb(51,51,51);font-family:proxima-nova-1,proxima-nova-2,Tahoma,Helvetica,V= erdana,sans-serif;font-size:14px;line-height:21px" class=3D"">Avi Levi</spa= n></div><div dir=3D"ltr" class=3D""><span style=3D"color:rgb(51,51,51);font= -family:proxima-nova-1,proxima-nova-2,Tahoma,Helvetica,Verdana,sans-serif;f= ont-size:14px;line-height:21px" class=3D"">m: <a href=3D"tel:%2B972-52-3459= 959" value=3D"+972523459959" target=3D"_blank" class=3D"">+972-52-3459959</= a></span><span style=3D"color:rgb(51,51,51);font-family:proxima-nova-1,prox= ima-nova-2,Tahoma,Helvetica,Verdana,sans-serif;font-size:14px;line-height:2= 1px" class=3D""><br class=3D""></span></div><div dir=3D"ltr" class=3D""><sp= an style=3D"color:rgb(51,51,51);font-family:proxima-nova-1,proxima-nova-2,T= ahoma,Helvetica,Verdana,sans-serif;font-size:14px;line-height:21px" class= =3D""><a href=3D"https://www.linkedin.com/in/leviavi" target=3D"_blank" cla= ss=3D""><img src=3D"https://docs.google.com/uc?export=3Ddownload&id=3D0= B82ayL0XJaZ5WEY0c2xWQWYxNDQ&revid=3D0B82ayL0XJaZ5YklVWjUvcG9tQmNrVEFRSD= hNd0lNLzUwKzlvPQ" class=3D""><span class=3D""></span><span class=3D""></spa= n></a></span></div><div dir=3D"ltr" class=3D""><span style=3D"margin:0px;pa= dding:0px;border:0px;outline:0px;font-size:14px;font-family:proxima-nova-1,= proxima-nova-2,Tahoma,Helvetica,Verdana,sans-serif;vertical-align:baseline;= color:rgb(43,130,173);line-height:21px" class=3D""><a href=3D"https://about= .me/avi.levi" target=3D"_blank" class=3D"">https://about.me/avi.levi</a></s= pan><br class=3D""></div></div></div></div></div></div></div> </div><div class=3D""><br class=3D"webkit-block-placeholder"></div> -- <br class=3D""> You received this message because you are subscribed to the Google Groups "= scala-language" group.<br class=3D""> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:[email protected]" targ= et=3D"_blank" class=3D"">[email protected]</a>.<b= r class=3D""> For more options, visit <a href=3D"https://groups.google.com/d/optout" targ= et=3D"_blank" class=3D"">https://groups.google.com/d/optout</a>.<br class= =3D""> </blockquote></div><div class=3D""><br class=3D"webkit-block-placeholder"><= /div> -- <br class=3D""> You received this message because you are subscribed to a topic in the Goog= le Groups "scala-language" group.<br class=3D""> To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/= d/topic/scala-language/wpGOB8f7qmY/unsubscribe" target=3D"_blank" class=3D"= ">https://groups.google.com/d/topic/scala-language/wpGOB8f7qmY/unsubscribe<= /a>.<br class=3D""> To unsubscribe from this group and all its topics, send an email to <a href= =3D"mailto:[email protected]" target=3D"_blank" c= lass=3D"">[email protected]</a>.<br class=3D""> For more options, visit <a href=3D"https://groups.google.com/d/optout" targ= et=3D"_blank" class=3D"">https://groups.google.com/d/optout</a>.<br class= =3D""> </blockquote></div><div class=3D""><br class=3D"webkit-block-placeholder"><= /div> -- <br class=3D""> You received this message because you are subscribed to the Google Groups "= scala-language" group.<br class=3D""> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:[email protected]" targ= et=3D"_blank" class=3D"">[email protected]</a>.<b= r class=3D""> For more options, visit <a href=3D"https://groups.google.com/d/optout" targ= et=3D"_blank" class=3D"">https://groups.google.com/d/optout</a>.<br class= =3D""> </blockquote></div><div class=3D""><br class=3D"webkit-block-placeholder"><= /div> -- <br class=3D""> You received this message because you are subscribed to the Google Groups "= scala-language" group.<br class=3D""> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:[email protected]" targ= et=3D"_blank" class=3D"">[email protected]</a>.<b= r class=3D""> For more options, visit <a href=3D"https://groups.google.com/d/optout" targ= et=3D"_blank" class=3D"">https://groups.google.com/d/optout</a>.<br class= =3D""> </div></div></blockquote></div><br class=3D""><br clear=3D"all" class=3D"">= <br class=3D"">-- <br class=3D""><div class=3D"gmail_signature" data-smartm= ail=3D"gmail_signature"><div dir=3D"ltr" class=3D""><div class=3D""><div di= r=3D"ltr" class=3D""><div class=3D""><div dir=3D"ltr" class=3D""><div class= =3D""><div dir=3D"ltr" class=3D""><div class=3D"">Oliver Ruebenacker<br cla= ss=3D""></div><div class=3D"">Senior Software Engineer, <a href=3D"http://w= ww.type2diabetesgenetics.org/" target=3D"_blank" class=3D"">Diabetes Portal= </a>, <a href=3D"http://www.broadinstitute.org/" target=3D"_blank" class=3D= "">Broad Institute</a><br class=3D""></div><br class=3D""></div></div></div= ></div></div></div></div></div> </div><div class=3D""><br class=3D"webkit-block-placeholder"></div> -- <br class=3D""> You received this message because you are subscribed to the Google Groups "= scala-language" group.<br class=3D""> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:[email protected]" clas= s=3D"">[email protected]</a>.<br class=3D""> For more options, visit <a href=3D"https://groups.google.com/d/optout" clas= s=3D"">https://groups.google.com/d/optout</a>.<br class=3D""> </div></blockquote></div><br class=3D""></div></div></body></html> <p></p> -- <br /> You received this message because you are subscribed to the Google Groups &= quot;scala-language" group.<br /> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:[email protected]">scal= [email protected]</a>.<br /> For more options, visit <a href=3D"https://groups.google.com/d/optout">http= s://groups.google.com/d/optout</a>.<br /> --Apple-Mail=_03E3AE74-F2CE-4CA7-AC26-4B2FA2037A21--