I have a function that takes a variable number of arguments. The first is a String and the rest are numbers (either Int or Double) so I am using Any* to get the arguments. I would like to treat the numbers uniformly as Doubles, but I cannot just use asInstanceOf[Double] on the numeric arguments. For example:
val arr = Array("varargs list of numbers", 3, 4.2, 5)
val d = arr(1).asInstanceOf[Double]
gives:
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double
Is there a way to do this? (The function needs to add up all the numbers).
Scala's asInstanceOf is its name for casting. Casting is not converting.
What you want can be accomplished like this:
val mongrel = List("comment", 1, 4.0f, 9.00d)
val nums = mongrel collect { case i: Int => i case f: Float => f case d: Double => d }
val sumOfNums = nums.foldLeft(0.0) ((sum, num) => sum + num)
Here is a slight simplification of Randall's answer:
val mongrel = List("comment", 1, 4.0f, 9.00d)
val nums = mongrel collect { case i: java.lang.Number => i.doubleValue() }
val sumOfNums = nums.sum
Matching for any kind of number turns out to be a little tricky in Scala, see here for another way of doing it.
When there is a need to handle different types, you should avoid casting them and instead use a pattern match. To add up all Double's and Int's of an array you could use:
val array = Array("varargs list of numbers", 3, 4.2, 5)
array.foldLeft(0.0){
case (s, i: Int) => s + i
case (s, d: Double) => s + d
case (s, _) => s
}
The pattern match allows you to treat each different type separately and avoids running into ClassCastExceptions.
Stepping back for a moment, might it be easier to have the function take Double* instead of Any*?
scala> def foo(str: String, nums: Double*) {
nums foreach { n => println(s"num: $n, class: ${n.getClass}") }
}
foo: (str: String, nums: Double*)Unit
scala> foo("", 1, 2.3)
num: 1.0, class: double
num: 2.3, class: double
Related
I have the following class definition and list
class myclass{
val val1: Int = 1
val val2: Int = 2
...
}
val mylist = List(a: myclass, b: myclass, c: myclass, d: myclass)
How can I convert the next line of code to underscore notation
mylist.foldLeft(0)((x,y) => x + y.val1 * y.val2)
I know that the next line doesn't work:
(0 /: mylist)(_ + _.val1 * _.val2)
This is because the first _ is refered to x and the second is referred to y, but the third _ scala doesn't know which variable is referred, my question is if there is a way that this works
This isn't too crazy:
scala> case class C(v: Int, w: Int)
defined class C
scala> val cs = List(C(1,2),C(3,4))
cs: List[C] = List(C(1,2), C(3,4))
scala> cs.iterator.map(c => c.v*c.w).foldLeft(0)(_+_)
res0: Int = 14
It expresses that the operations are independent. Iterating avoids an intermediate list.
Suppose I have the following code:
val someNumbers = List(-11, -10, -5, 0, 5, 10)
someNumbers.foreach( println _ )
val j = 10
(x: Int) => x + j
My question is Are partially applied functions and Closures orthogonal in Scala? This presentation seems to suggest that they are.
EDIT: 13 July 2014 [Changed code above]
It's really easy to see what's being returned when you go into the repl:
scala> type IntPairPred = (Int, Int) => Boolean
defined type alias IntPairPred
scala> val gt: IntPairPred = _ > _
gt: IntPairPred = <function2>
scala> gt(2,3)
res3: Boolean = false
What gt is, is a function2 i.e. a function that takes 2 parameters
Here's another example:
scala> def fn(a: Int, b: Int) = () => a + b
fn: (a: Int, b: Int)() => Int
scala> val a = fn(2,3)
a: () => Int = <function0>
What fn returns, is a function0 i.e. a function that doesn't take any parameters
Sorry but your example doesn't seem to refer to partial application, at least to me.
You're just using some shortcut syntax to define regular functions.
Actually gt, ge, ... definitions are expanded to something pretty like
val gt: IntPairPred = (x: Int, y: Int) => x > y
val gt: IntPairPred = (x: Int, y: Int) => x >= y
//and so on...
Regular functions support modification of its arguments, but this is not what you're looking for, I presume.
To define a closure, you should define a partial function referring to a variable in the outer scope, like
var one = 1
val gt1 = gt(1, _: Int)
assert(gt1(0)) //ok
assert(!gt1(1)) //ok
one = 2 //weirdo!
assert(gt1(0)) //ok
assert(gt1(1)) //ok
assert(!gt1(2)) //ok
So the point is not in functions definition or partial application. The point is if, at definition time, you're using variables from the closing scope within your function. In this case your function is influenced by the variable you closed over.
Is this what you were after?
It seems easy problem for any specific kind of Number i.e. Double/Integer but it is hard to write in general case.
implicit def iterebleWithAvg(data:Iterable[Double]) = new {
def avg:Double = data.sum / data.size
}
How to implement this for any kind of Number(Int,Float,Double,BigDecemial)?
You have to pass an implicit Numeric which will allow summation and conversion to Double:
def average[T]( ts: Iterable[T] )( implicit num: Numeric[T] ) = {
num.toDouble( ts.sum ) / ts.size
}
The compiler will provide the correct instance for you:
scala> average( List( 1,2,3,4) )
res8: Double = 2.5
scala> average( 0.1 to 1.1 by 0.05 )
res9: Double = 0.6000000000000001
scala> average( Set( BigInt(120), BigInt(1200) ) )
res10: Double = 660.0
You can the use the function to define an implicit view (provided you propagate the implicit numeric dependency):
implicit def iterebleWithAvg[T:Numeric](data:Iterable[T]) = new {
def avg = average(data)
}
scala> List(1,2,3,4).avg
res13: Double = 2.5
Here's the way I define it in my code.
Instead of using Numeric, I use Fractional, since Fractional defines a division operation (Numeric doesn't necessarily have division). This means that when you call .avg, you will get back the same type you put in, instead of always getting Double.
I also define it over all GenTraversableOnce collections so that it works on, for example, Iterator.
class EnrichedAvgFractional[A](self: GenTraversableOnce[A]) {
def avg(implicit num: Fractional[A]) = {
val (total, count) = self.toIterator.foldLeft((num.zero, num.zero)) {
case ((total, count), x) => (num.plus(total, x), num.plus(count, num.one))
}
num.div(total, count)
}
}
implicit def enrichAvgFractional[A: Fractional](self: GenTraversableOnce[A]) = new EnrichedAvgFractional(self)
Notice how if we give it a collection of Double, we get back Double and if we give it BigDecimal, we get back BigDecimal. We could even define our own Fractional number type (which I do occasionally), and it will work for that.
scala> Iterator(1.0, 2.0, 3.0, 4.0, 5.0).avg
res0: Double = 3.0
scala> Iterator(1.0, 2.0, 3.0, 4.0, 5.0).map(BigDecimal(_)).avg
res1: scala.math.BigDecimal = 3.0
However, Int is not a kind of Fractional, meaning that it doesn't make sense to get an Int and the result of averaging Ints, so we have to have a special case for Int that converts to a Double.
class EnrichedAvgInt(self: GenTraversableOnce[Int]) {
def avg = {
val (total, count) = self.toIterator.foldLeft(0, 0) {
case ((total, count), x) => (total + x, count + 1)
}
total.toDouble / count
}
}
implicit def enrichAvgInt(self: GenTraversableOnce[Int]) = new EnrichedAvgInt(self)
So averaging Ints gives us a Double:
scala> Iterator(1, 2, 3, 4, 5).avg
res2: Double = 3
I've got a two dimensional array and I want to apply a function to each value in the array.
Here's what I'm working with:
scala> val array = Array.tabulate(2,2)((x,y) => (0,0))
array: Array[Array[(Int, Int)]] = Array(Array((0,0), (0,0)), Array((0,0), (0,0)))
I'm using foreach to extract the tuples:
scala> array.foreach(i => i.foreach(j => println(i)))
[Lscala.Tuple2;#11d559a
[Lscala.Tuple2;#11d559a
[Lscala.Tuple2;#df11d5
[Lscala.Tuple2;#df11d5
Let's make a simple function:
//Takes two ints and return a Tuple2. Not sure this is the best approach.
scala> def foo(i: Int, j: Int):Tuple2[Int,Int] = (i+1,j+2)
foo: (i: Int,j: Int)(Int, Int)
This runs, but need to apply to array(if mutable) or return new array.
scala> array.foreach(i => i.foreach(j => foo(j._1, j._2)))
Shouldn't be to bad. I'm missing some basics I think...
(UPDATE: removed the for comprehension code which was not correct - it returned a one dimensional array)
def foo(t: (Int, Int)): (Int, Int) = (t._1 + 1, t._2 + 1)
array.map{_.map{foo}}
To apply to a mutable array
val array = ArrayBuffer.tabulate(2,2)((x,y) => (0,0))
for (sub <- array;
(cell, i) <- sub.zipWithIndex)
sub(i) = foo(cell._1, cell._2)
2dArray.map(_.map(((_: Int).+(1) -> (_: Int).+(1)).tupled))
e.g.
scala> List[List[(Int, Int)]](List((1,3))).map(_.map(((_: Int).+(1) -> (_: Int).+(1)).tupled))
res123: List[List[(Int, Int)]] = List(List((2,4)))
Dot notation required to force
I'm learning Scala as it fits my needs well but I am finding it hard to structure code elegantly. I'm in a situation where I have a List x and want to create two Lists: one containing all the elements of SomeClass and one containing all the elements that aren't of SomeClass.
val a = x collect {case y:SomeClass => y}
val b = x filterNot {_.isInstanceOf[SomeClass]}
Right now my code looks like that. However, it's not very efficient as it iterates x twice and the code somehow seems a bit hackish. Is there a better (more elegant) way of doing things?
It can be assumed that SomeClass has no subclasses.
EDITED
While using plain partition is possible, it loses the type information retained by collect in the question.
One could define a variant of the partition method that accepts a function returning a value of one of two types using Either:
import collection.mutable.ListBuffer
def partition[X,A,B](xs: List[X])(f: X=>Either[A,B]): (List[A],List[B]) = {
val as = new ListBuffer[A]
val bs = new ListBuffer[B]
for (x <- xs) {
f(x) match {
case Left(a) => as += a
case Right(b) => bs += b
}
}
(as.toList, bs.toList)
}
Then the types are retained:
scala> partition(List(1,"two", 3)) {
case i: Int => Left(i)
case x => Right(x)
}
res5: (List[Int], List[Any]) = (List(1, 3),List(two))
Of course the solution could be improved using builders and all the improved collection stuff :) .
For completeness my old answer using plain partition:
val (a,b) = x partition { _.isInstanceOf[SomeClass] }
For example:
scala> val x = List(1,2, "three")
x: List[Any] = List(1, 2, three)
scala> val (a,b) = x partition { _.isInstanceOf[Int] }
a: List[Any] = List(1, 2)
b: List[Any] = List(three)
Just wanted to expand on mkneissl's answer with a "more generic" version that should work on many different collections in the library:
scala> import collection._
import collection._
scala> import generic.CanBuildFrom
import generic.CanBuildFrom
scala> def partition[X,A,B,CC[X] <: Traversable[X], To, To2](xs : CC[X])(f : X => Either[A,B])(
| implicit cbf1 : CanBuildFrom[CC[X],A,To], cbf2 : CanBuildFrom[CC[X],B,To2]) : (To, To2) = {
| val left = cbf1()
| val right = cbf2()
| xs.foreach(f(_).fold(left +=, right +=))
| (left.result(), right.result())
| }
partition: [X,A,B,CC[X] <: Traversable[X],To,To2](xs: CC[X])(f: (X) => Either[A,B])(implicit cbf1: scala.collection.generic.CanBuildFrom[CC[X],A,To],implicit cbf2: scala.collection.generic.CanBuildFrom[CC[X],B,To2])(To, To2)
scala> partition(List(1,"two", 3)) {
| case i: Int => Left(i)
| case x => Right(x)
| }
res5: (List[Int], List[Any]) = (List(1, 3),List(two))
scala> partition(Vector(1,"two", 3)) {
| case i: Int => Left(i)
| case x => Right(x)
| }
res6: (scala.collection.immutable.Vector[Int], scala.collection.immutable.Vector[Any]) = (Vector(1, 3),Vector(two))
Just one note: The partition method is similar, but we need to capture a few types:
X -> The original type for items in the collection.
A -> The type of items in the left partition
B -> The type of items in the right partition
CC -> The "specific" type of the collection (Vector, List, Seq etc.) This must be higher-kinded. We could probably work around some type-inference issues (see Adrian's response here: http://suereth.blogspot.com/2010/06/preserving-types-and-differing-subclass.html ), but I was feeling lazy ;)
To -> The complete type of collection on the left hand side
To2 -> The complete type of the collection on the right hand side
Finally, the funny "CanBuildFrom" implicit paramters are what allow us to construct specific types, like List or Vector, generically. They are built into to all the core library collections.
Ironically, the entire reason for the CanBuildFrom magic is to handle BitSets correctly. Because I require CC to be higher kinded, we get this fun error message when using partition:
scala> partition(BitSet(1,2, 3)) {
| case i if i % 2 == 0 => Left(i)
| case i if i % 2 == 1 => Right("ODD")
| }
<console>:11: error: type mismatch;
found : scala.collection.BitSet
required: ?CC[ ?X ]
Note that implicit conversions are not applicable because they are ambiguous:
both method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A]
and method any2Ensuring in object Predef of type [A](x: A)Ensuring[A]
are possible conversion functions from scala.collection.BitSet to ?CC[ ?X ]
partition(BitSet(1,2, 3)) {
I'm leaving this open for someone to fix if needed! I'll see if I can give you a solution that works with BitSet after some more play.
Use list.partition:
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> val (even, odd) = l partition { _ % 2 == 0 }
even: List[Int] = List(2)
odd: List[Int] = List(1, 3)
EDIT
For partitioning by type, use this method:
def partitionByType[X, A <: X](list: List[X], typ: Class[A]):
Pair[List[A], List[X]] = {
val as = new ListBuffer[A]
val notAs = new ListBuffer[X]
list foreach {x =>
if (typ.isAssignableFrom(x.asInstanceOf[AnyRef].getClass)) {
as += typ cast x
} else {
notAs += x
}
}
(as.toList, notAs.toList)
}
Usage:
scala> val (a, b) = partitionByType(List(1, 2, "three"), classOf[java.lang.Integer])
a: List[java.lang.Integer] = List(1, 2)
b: List[Any] = List(three)
If the list only contains subclasses of AnyRef, becaus of the method getClass. You can do this:
scala> case class Person(name: String)
defined class Person
scala> case class Pet(name: String)
defined class Pet
scala> val l: List[AnyRef] = List(Person("Walt"), Pet("Donald"), Person("Disney"), Pet("Mickey"))
l: List[AnyRef] = List(Person(Walt), Pet(Donald), Person(Disney), Pet(Mickey))
scala> val groupedByClass = l.groupBy(e => e.getClass)
groupedByClass: scala.collection.immutable.Map[java.lang.Class[_],List[AnyRef]] = Map((class Person,List(Person(Walt), Person(Disney))), (class Pet,List(Pet(Donald), Pet(Mickey))))
scala> groupedByClass(classOf[Pet])(0).asInstanceOf[Pet]
res19: Pet = Pet(Donald)
Starting in Scala 2.13, most collections are now provided with a partitionMap method which partitions elements based on a function returning either Right or Left.
That allows us to pattern match a given type (here Person) that we transform as a Right in order to place it in the right List of the resulting partition tuple. And other types can be transformed as Lefts to be partitioned in the left part:
// case class Person(name: String)
// case class Pet(name: String)
val (pets, persons) =
List(Person("Walt"), Pet("Donald"), Person("Disney")).partitionMap {
case person: Person => Right(person)
case pet: Pet => Left(pet)
}
// persons: List[Person] = List(Person(Walt), Person(Disney))
// pets: List[Pet] = List(Pet(Donald))