- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Option[Double] arithmetic operators
Thu, 2009-10-22, 20:38
Suppose d1, d2, d3 d4 are all Option[Double]
One way of doing arithmetic with Option[Double] values so that the
expression returns None if any of the values is None is as follows:
val result: Option[Double] =
for (a <- d1; b <- d2; c <- d3; d <- d4)
yield (a+b+c+d)/ 4;
Clever, yes, but it sucks from a readability point of view.
AND you have to ALIAS all variables.
Is there a more readable way of doing this?
Would it be possible to define +-/* etc etc for Option[Double] Option[Int]
etc.
Has anybody done this already somewhere?
Thu, 2009-10-22, 22:47
#2
Re: Option[Double] arithmetic operators
It's worth noting that Not-a-Number already has this behavior (in hardware). Unfortunately, RichDouble doesn't contain an isNaN method for testing, but java.lang.Double does.
I hate recommending a shift from Option to value-based success/failure, but if you want higher performance numeric code, this might be the way to go.
If you just want elegant and correct code, the easiest way pre-2.8 (and possibly still the clearest post-2.8) is to use the standard pimping pattern (shown here with a trick to shortcut evaluations when the first argument is None; it's perfectly okay to test for o==None || od==None in RichOptionDouble instead of making the subclassed RichNoneDouble object, though):
class RichOptionDouble(od:Option[Double]) {
def +(o:Option[Double]) = if (o==None) o else Some(o.get+od.get)
def unary_-() = Some(-od.get)
def -(o:Option[Double]) = if (o==None) o else Some(o.get+od.get)
// Same deal for *, /
}
object RichNoneDouble extends RichOptionDouble(None) {
override def +(o:Option[Double]) = None
override def unary_-() = None
override def -(o:Option[Double]) = None
// Same deal for *, /
}
implicit def optiondouble2richoptiondouble(od:Option[Double]) = {
if (od==None) RichNoneDouble else new RichOptionDouble(od)
}
scala> Some(3.5)+Some(0.7)
res0: Option[Double] = Some(4.2)
scala> Some(4.4)+None
res1: Option[Double] = None
scala> -None
res2: Option[Double] = None
If you wanted to be really safe, you could check for isNaN also and turn those into RichNoneDoubles and/or None return types.
Also, as Paul mentions, one can use Numeric to avoid having to rewrite the math for each type as of 2.8.
--Rex
On Thu, Oct 22, 2009 at 3:38 PM, Tim Azzopardi <tim@tigerfive.com> wrote:
I hate recommending a shift from Option to value-based success/failure, but if you want higher performance numeric code, this might be the way to go.
If you just want elegant and correct code, the easiest way pre-2.8 (and possibly still the clearest post-2.8) is to use the standard pimping pattern (shown here with a trick to shortcut evaluations when the first argument is None; it's perfectly okay to test for o==None || od==None in RichOptionDouble instead of making the subclassed RichNoneDouble object, though):
class RichOptionDouble(od:Option[Double]) {
def +(o:Option[Double]) = if (o==None) o else Some(o.get+od.get)
def unary_-() = Some(-od.get)
def -(o:Option[Double]) = if (o==None) o else Some(o.get+od.get)
// Same deal for *, /
}
object RichNoneDouble extends RichOptionDouble(None) {
override def +(o:Option[Double]) = None
override def unary_-() = None
override def -(o:Option[Double]) = None
// Same deal for *, /
}
implicit def optiondouble2richoptiondouble(od:Option[Double]) = {
if (od==None) RichNoneDouble else new RichOptionDouble(od)
}
scala> Some(3.5)+Some(0.7)
res0: Option[Double] = Some(4.2)
scala> Some(4.4)+None
res1: Option[Double] = None
scala> -None
res2: Option[Double] = None
If you wanted to be really safe, you could check for isNaN also and turn those into RichNoneDoubles and/or None return types.
Also, as Paul mentions, one can use Numeric to avoid having to rewrite the math for each type as of 2.8.
--Rex
On Thu, Oct 22, 2009 at 3:38 PM, Tim Azzopardi <tim@tigerfive.com> wrote:
Suppose d1, d2, d3 d4 are all Option[Double]
One way of doing arithmetic with Option[Double] values so that the
expression returns None if any of the values is None is as follows:
val result: Option[Double] =
for (a <- d1; b <- d2; c <- d3; d <- d4)
yield (a+b+c+d)/ 4;
Clever, yes, but it sucks from a readability point of view.
AND you have to ALIAS all variables.
Is there a more readable way of doing this?
Would it be possible to define +-/* etc etc for Option[Double] Option[Int]
etc.
Has anybody done this already somewhere?
--
View this message in context: http://www.nabble.com/Option-Double--arithmetic-operators-tp26015945p26015945.html
Sent from the Scala - User mailing list archive at Nabble.com.
Thu, 2009-10-22, 22:57
#3
Re: Option[Double] arithmetic operators
Whoops, forgot to proofread for typos:
On Thu, Oct 22, 2009 at 5:41 PM, Rex Kerr <ichoran@gmail.com> wrote:
It's should be a minus sign inside the Some, of course:
def -(o:Option[Double]) = if (o==None) o else Some(o.get - od.get)
--Rex
On Thu, Oct 22, 2009 at 5:41 PM, Rex Kerr <ichoran@gmail.com> wrote:
class RichOptionDouble(od:Option[Double]) {
def +(o:Option[Double]) = if (o==None) o else Some(o.get+od.get)
def unary_-() = Some(-od.get)
def -(o:Option[Double]) = if (o==None) o else Some(o.get+od.get)
It's should be a minus sign inside the Some, of course:
def -(o:Option[Double]) = if (o==None) o else Some(o.get - od.get)
--Rex
Thu, 2009-10-22, 23:07
#4
Re: Option[Double] arithmetic operators
Thanks, that looks like its exactly what I was looking for.
Rex Kerr-2 wrote:
>
> Whoops, forgot to proofread for typos:
>
> On Thu, Oct 22, 2009 at 5:41 PM, Rex Kerr wrote:
>
>>
>> class RichOptionDouble(od:Option[Double]) {
>> def +(o:Option[Double]) = if (o==None) o else Some(o.get+od.get)
>> def unary_-() = Some(-od.get)
>> def -(o:Option[Double]) = if (o==None) o else Some(o.get+od.get)
>>
>
> It's should be a minus sign inside the Some, of course:
>
> def -(o:Option[Double]) = if (o==None) o else Some(o.get - od.get)
>
> --Rex
>
>
Fri, 2009-10-23, 20:37
#5
Re: Option[Double] arithmetic operators
You can also check out the Applicative functor - implemented in scalaz (http://scalaz.googlecode.com/svn/artifacts/latest/demo/scalazdemo/control/Applicative.scala)
On Fri, Oct 23, 2009 at 12:53 AM, Tim Azzopardi <tim@tigerfive.com> wrote:
On Fri, Oct 23, 2009 at 12:53 AM, Tim Azzopardi <tim@tigerfive.com> wrote:
Thanks, that looks like its exactly what I was looking for.
Rex Kerr-2 wrote:
>
> Whoops, forgot to proofread for typos:
>
> On Thu, Oct 22, 2009 at 5:41 PM, Rex Kerr <ichoran@gmail.com> wrote:
>
>>
>> class RichOptionDouble(od:Option[Double]) {
>> def +(o:Option[Double]) = if (o==None) o else Some(o.get+od.get)
>> def unary_-() = Some(-od.get)
>> def -(o:Option[Double]) = if (o==None) o else Some(o.get+od.get)
>>
>
> It's should be a minus sign inside the Some, of course:
>
> def -(o:Option[Double]) = if (o==None) o else Some(o.get - od.get)
>
> --Rex
>
>
--
View this message in context: http://www.nabble.com/Option-Double--arithmetic-operators-tp26015945p26017843.html
Sent from the Scala - User mailing list archive at Nabble.com.
Sat, 2009-10-24, 01:17
#6
Re: Option[Double] arithmetic operators
Thanks to all for the replies. I have read and learnt from them.
I have used Rex Kerr's suggested approach. It is working well for me so far.
I have NOT dealt with null and isNaN in the code below.
I have NOT tried generalizing this using Numeric as suggested above.
I have used Jorge Ortiz's Scala-Time technique for managing imports and
implicits
I have used the latest nightly eclipse plugin using the 2.8pre compiler. No
idea if it works on earlier versions.
============ File: RichOptionDouble.scala ============
package org.scala_tools.option.math
// Modelled on Martin Odersky pimp my library technique
// http://www.artima.com/weblogs/viewpost.jsp?thread=179766
class RichOptionDouble(od:Option[Double]) {
def +(o:Option[Double]) = if (o==None) o else Some(od.get+o.get)
// Without the :Option[Double] in the definition of unary_-(),
RichNoneDouble unary_-()
// doesn't compile as it expects to return Some[Double]
def unary_-():Option[Double] = Some(-od.get)
def -(o:Option[Double]) = if (o==None) o else Some(od.get-o.get)
def *(o:Option[Double]) = if (o==None) o else Some(od.get*o.get)
def /(o:Option[Double]) = if (o==None) o else Some(od.get/o.get)
}
object RichNoneDouble extends RichOptionDouble(None) {
override def +(o:Option[Double]) = None
override def unary_-() = None
override def -(o:Option[Double]) = None
override def *(o:Option[Double]) = None
override def /(o:Option[Double]) = None
}
==========================================
================= File: Implicits.scala ============
package org.scala_tools.option.math
// Modeled on technique in Scala-Time
object Implicits extends Implicits
trait Implicits {
implicit def optiondouble2richoptiondouble(od:Option[Double]) = {
if (od==None) RichNoneDouble else new RichOptionDouble(od)
}
implicit def double2optiondouble(d:Double) = Some(d)
implicit def int2optiondouble(i:Int) = Some(i.toDouble)
}
==========================================
================= File: Imports.scala ============
package org.scala_tools.option.math
// Modelled on technique in Scala-Time
object Imports extends Imports
trait Imports extends Implicits
==========================================
Usage
import org.scala_tools.option.math.Imports._
object Foo {
def main(args : Array[String]) : Unit = {
val d1 = Some(1d)
val d2 = Some(2d)
val dn = None
val i:Int = 1;
println(d1 + d2)
println(d1 + dn)
println(dn + d1)
println
println(d1 + d2 + dn)
println(d1 + dn + d2)
println(dn + d1 + d2)
println
println(d1 + d2 + 3)
println(d1 + 3 + d2)
// println(3 + d1 + d2) does not compile
println(Some(3.0) + d1 + d2) // is ok
println
println(d1 + d2 + 3.0)
println(d1 + 3.0 + d2)
// println(3.0 + d1 + d2) does not compile
println(Some(3.0) + d1 + d2) // is ok
println
}
}
outputs:
Some(3.0)
None
None
None
None
None
Some(6.0)
Some(6.0)
Some(6.0)
Some(6.0)
Some(6.0)
Some(6.0)
On Thu, Oct 22, 2009 at 12:38:10PM -0700, Tim Azzopardi wrote:
> val result: Option[Double] =
> for (a <- d1; b <- d2; c <- d3; d <- d4)
> yield (a+b+c+d)/ 4;
>
> Clever, yes, but it sucks from a readability point of view.
> AND you have to ALIAS all variables.
>
> Is there a more readable way of doing this?
I don't know if it's any more readable, but you can avoid aliasing any
number of ways:
val list: List[Option[Double]]
list.flatten match {
case xs if xs.size == list.size => Some(xs.sum / xs.size)
case _ => None
}
If you're following the thread on some scala list about
map/fmap/cofmap/on/by, it suddenly becomes relevant here because one of
the "cofmaps" I wrote on Numeric was an implicit which created
Numeric[Option[T]] from Numeric[T]. It would propagate None but
otherwise do the math. Pretty seamless as I recall, but I wrote it
months ago and haven't come back.