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 &lt;<a href=3D"mailto:[email protected]" class=3D"">c=
[email protected]</a>&gt;:</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>&nbsp;&nbsp;&nbsp;&nbsp; Hello,<br class=3D""><br class=3D=
""></div>&nbsp; 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&gt=
; import scala.concurrent.Future<br class=3D"">import scala.concurrent.Futu=
re<br class=3D""><br class=3D"">scala&gt; import scala.concurrent.Execution=
Context.Implicits.global<br class=3D"">import scala.concurrent.ExecutionCon=
text.Implicits.global<br class=3D""><br class=3D"">scala&gt; Future{1}.onCo=
mplete { case _ =3D&gt; println("Complete!") }<br class=3D""><br class=3D""=
>scala&gt; Complete!<br class=3D""><br class=3D""><br class=3D"">scala&gt; =
Future{1}.filter(_ =3D=3D 0).onComplete { case _ =3D&gt; println("Complete!=
") }<br class=3D"">Complete!<br class=3D""><br class=3D"">scala&gt; import =
scala.util.{Success, Failure }<br class=3D"">import scala.util.{Success, Fa=
ilure}<br class=3D""><br class=3D"">scala&gt; Future{1}.filter(_ =3D=3D 0).=
onComplete {<br class=3D"">&nbsp;&nbsp;&nbsp;&nbsp; | case Success(value) =
=3D&gt; println(value)<br class=3D"">&nbsp;&nbsp;&nbsp;&nbsp; | case Failur=
e(ex) =3D&gt; println(ex)<br class=3D"">&nbsp;&nbsp;&nbsp;&nbsp; | }<br cla=
ss=3D""><br class=3D"">java.util.NoSuchElementException: Future.filter pred=
icate is not satisfied<br class=3D"">scala&gt;</span></b><br class=3D""><br=
 class=3D""></div><div class=3D"">&nbsp;&nbsp;&nbsp;&nbsp; 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"">&lt;<a href=3D"m=
ailto:[email protected]" target=3D"_blank" class=3D"">viktor.klang@gma=
il.com</a>&gt;</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" &lt;<a href=
=3D"mailto:[email protected]" target=3D"_blank" class=3D"">[email protected]<=
/a>&gt; 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" &lt;<a h=
ref=3D"mailto:[email protected]" target=3D"_blank" class=3D"">viktor.k=
[email protected]</a>&gt; 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" &lt;<a href=
=3D"mailto:[email protected]" target=3D"_blank" class=3D"">[email protected]<=
/a>&gt; 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&nbsp;</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"">&nbsp;</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"">&lt;<a href=3D"mailto:[email protected]" targe=
t=3D"_blank" class=3D"">[email protected]</a>&gt;</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>&gt;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" &lt;<a href=
=3D"mailto:[email protected]" target=3D"_blank" class=3D"">[email protected]<=
/a>&gt; 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" &lt;<a h=
ref=3D"mailto:[email protected]" target=3D"_blank" class=3D"">viktor.k=
[email protected]</a>&gt; 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" &lt;<a href=
=3D"mailto:[email protected]" target=3D"_blank" class=3D"">[email protected]<=
/a>&gt; 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&nbsp;</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&nbsp;</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] &nbsp;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&nbsp;</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&amp;id=3D0=
B82ayL0XJaZ5WEY0c2xWQWYxNDQ&amp;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&quot; 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--