Is there a way to avoid to convert number types in Scala? Should I use Numeric, Integral? - scala

I would like to not to mind about type of numbers.
All numbers could be treated as Double,
but I would like to know the better scalaish way to use numbers just as numbers.
This is just one example, suppose I have the following:
val n = 5
val l = List(1,2,3,4,5) grouped (n / 2d).ceil.toInt
Is there a way to do just (exactly):
val l = List(1,2,3,4,5) grouped (n / 2).ceil
with no compilation error due to the mismatched type of 'grouped' parameter?
EDIT
The n / 2 in grouped (n / 2).ceil part could be, in another example, the non integer result of a function f:
grouped f.ceil
It still needs type conversion, or in all situations there is a trick or design pattern to avoid it?

val l = List(1,2,3,4,5) grouped((n + 1) / 2)

You could check out the numeric library Spire, I believe it has what you are looking for, namely, the ability to treat numbers as numbers whether they are int/double/float/etc.

There is a way to do it. You can define an implicit conversion like this:
implicit def double2Int(d: Double): Int = d.toInt
Once that's in scope, it will convert any Double automatically to Int. However, doing so is not recommended, as you lose type safety.

Related

Convert an Int type to a tuple identifier in scala?

Is it possible to convert an Int to a tuple identifier (in scala)? So for a working example suppose I had this:
val testTuple = ("Hector", "Jonas", "Javi")
val id = 2
println(testTuple._id) // does not work as it tries 'num' as a name parameter
I can see that tuple elements can be accessed by the order in which they appear - much like an index (except the first value is 1 rather than 0), e.g. testTuple._1 // is Hector would work as described here among other places.
So how can this be done? Many thanks
You can use testTuple.productElement(id - 1). But note that this returns Any.
NO, You can not do this. _n is a member of tuple<n> and it automatically equals to the size of tuple. According to the notes:
For each TupleN type, where 1 <= N <= 22, Scala defines a number of
element-access methods.
Ex:
val data = (4,3,2)
val sum = data._1 + data._2 + data._3
For more information, you can see Scala Tuples.
Thanks.

Rounding numeric parameter types in Scala

I'm experimenting with a method in Scala which is attempting to round numbers depending on how big they are, e.g. if the value is below 1 then it makes sense to round it by at least one decimal point; rather than remaining an integer. Here's what I'm trying:
def roundSmart[A](num: A)(implicit numeric: Numeric[A]) = num match {
case num if num < 1 => numeric.toDouble(num)
case _ => numeric.toInt(num)
}
Which throws this error:
value < is not a member of type parameter A
Of course the parameters need to accept a range of parameter types within the function signature as it may be taking integers or doubles so this has added a further complexity.
I've taken the conditional statement on the first case from this answer -
Using comparison operators in Scala's pattern matching system and am eager to use a Functional Programming approach. Perhaps there is also some in-built scala function like Math.round() that could help to round the second condition rather than remove any decimals. Thanks!
TL;DR : every numeric methods you'll need are inside numeric
The error is self-explanatory: your type A (which is generic) does not have a < method.
However, what you have is a typeclass with all numeric methods in it, so you should probably import them:
import numeric._
This imports (among other things) implicit conversion to OrderingOps, which has the desired method. But this comparison cannot work, since 1 is not an A, it's an Int!
The solution is simply to use fromIntof numeric.
While we're at it, you will have unexpected results for input such as -234.2e123... You'd better do your test on the absolute value of your number (abs is also a method of numeric).
Also, if you want to do a simple test, there is no need to use pattern matching, a if else statement is enough
def roundSmart[A](num: A)(implicit numeric: Numeric[A]) = {
import numeric._
if (abs(num) < fromInt(1)) toDouble(num) else toInt(num)
}

First Element of a Lazy Stream in Scala

Here is a minimal example, I can define a function that gives my the next integer via
def nextInteger(input: Int): Int = input+1
I can then define a lazy stream of integers as
lazy val integers: Stream[Int] = 1 #:: integers map(x=>nextInteger(x))
To my surprise, taking the first element of this stream is 2 and not 1
scala> integers
res21: Stream[Int] = Stream(2, ?)
In this simple example I can achieve my desired result using 0 instead of 1 in the definition of integers, but how can one in general set up a stream such that the initial value isn't lost? In my case I am setting up an iterative algorithm and will want to know the initial value.
EDIT:
Furthermore, I've never understood the design choice which makes the following syntax fail:
scala> (integers take 10 toList) last
res27: Int = 11
scala> integers take 10 toList last
<console>:24: error: not found: value last
integers take 10 toList last
^
I find wrapping things in brackets cumbersome, is there a shorthand I am not aware of?
You're probably thinking that 1 #:: integers map(x=>nextInteger(x)) is parsed as 1 #:: (integers map(x=>nextInteger(x))) while it is actually parsed as (1 #:: integers).map(x=>nextInteger(x)). Adding parens fixes your problem:
val integers: Stream[Int] = 1 #:: (integers map nextInteger)
(Notice that since nextInteger is just a function, you don't need to make a lambda for it, and since Stream is already lazy, making integers lazy is unnecessary)
As to your edit, check out this excellent answer on the matter. In short: no there is no easy way. The thing is that unless you already know the arity of the functions involved, having something like what you suggest work would be hell for the next person reading your code... For example,
myList foo bar baz
Might be be myList.foo.bar.baz as well as myList.foo(bar).baz and you wouldn't know without checking the definitions of foo, bar, and baz. Scala decides to eliminate this ambiguity - it is always the latter.

How to perform calculation given multiple types of numbers?

I have some numbers list that I go through it, and doing a simple calculation to for two numbers:
I have numberA and numberB, and the calculation im doing is:
val res = (numberA/numberB) * 100
now, I dont know what type is the number, but I know it could be float (with 2 nums after the dot) or integer...
so I want to know what is the syntax in scala to calculate it?
currently I have:
val num1 = (vatReclaimed.toInt/vatPaid.toInt) * 100
but its obviously dont work, and I cannot really use toInt i guess since I dont know the type...
whats important to me that the res will hold the right answer, so if its 2.3 * 4 the res will hold 9.2
thanksss!
When you do not know the type only, that is a number, you probably have to work with Numeric. With numeric you can convert any numeric value to Double, Float, Int or Long. For precision I would recommend Double:
def calc[A : Numeric, B : Numeric](a: A, b: B): Double = (a.toDouble / b.toDouble) * 100

Partial Functions in Scala

I just wanted to clarify something about partially defined functions in Scala. I looked at the docs and it said the type of a partial function is PartialFunction[A,B], and I can define a partial function such as
val f: PartialFunction[Any, Int] = {...}
I was wondering, for the types A and B, is A a parameter, and B a return type? If I have multiple accepted types, do I use orElse to chain partial functions together?
In the set theoretic view of a function, if a function can map every value in the domain to a value in the range, we say that this function is a total function. There can be situations where a function cannot map some element(s) in the domain to the range; such functions are called partial functions.
Taking the example from the Scala docs for partial functions:
val isEven: PartialFunction[Int, String] = {
case x if x % 2 == 0 => x+" is even"
}
Here a partial function is defined since it is defined to only map an even integer to a string. So the input to the partial function is an integer and the output is a string.
val isOdd: PartialFunction[Int, String] = {
case x if x % 2 == 1 => x+" is odd"
}
isOdd is another partial function similarly defined as isEven but for odd numbers. Again, the input to the partial function is an integer and the output is a string.
If you have a list of numbers such as:
List(1,2,3,4,5)
and apply the isEven partial function on this list you will get as output
List(2 is even, 4 is even)
Notice that not all the elements in the original list have been mapped by the partial function. However, there may be situations where you want to apply another function in those cases where a partial function cannot map an element from the domain to the range. In this case we use orElse:
val numbers = sample map (isEven orElse isOdd)
And now you will get as output:
List(1 is odd, 2 is even, 3 is odd, 4 is even, 5 is odd)
If you are looking to set up a partial function that, in effect, takes multiple parameters, define the partial function over a tuple of the parameters you'll be feeding into it, eg:
val multiArgPartial: PartialFunction[(String, Long, Foo), Int] = {
case ("OK", _, Foo("bar", _)) => 0 // Use underscore to accept any value for a given parameter
}
and, of course, make sure you pass arguments to it as tuples.
In addition to other answers, if by "multiple accepted types" you mean that you want the same function accept e.g. String, Int and Boolean (and no other types), this is called "union types" and isn't supported in Scala currently (but is planned for the future, based on Dotty). The alternatives are:
Use the least common supertype (Any for the above case). This is what orElse chains will do.
Use a type like Either[String, Either[Int, Boolean]]. This is fine if you have two types, but becomes ugly quickly.
Encode union types as negation of intersection types.