Rounding numeric parameter types in Scala - 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)
}

Related

Scala equivalent of Java's Number with divide method

I want to generalise this function
def selfSufficiency(a: Seq[Double], b: Seq[Double]): Double =
a.sum/b.sum
I tried using the ideas provided here to implement a more general function that work with Doubles, Floats, Ints, etc.:
def selfSufficiency[A](a: Seq[A], b: Seq[A])
(implicit n: Numeric[A]):A = {
import n._
a.sum/b.sum
}
I however get a remark from eclipse saying that
value / is not a member of type parameter A.
1- How can I implement this in functional/generalisable way?
2- Does my implementation limits the user to have the same type "A" for both inputs? In other words, can I do this with my code?
selfSufficiency(Seq(1,2,3), Seq(2.0,1.3))
if I cannot, please explain how to implement this?
Please note that the code here provide a toy example. In my production function, I add, subtract, find the larger number, etc.
The problem is that Numeric doesn't encode the division function - you need a Fractional.
Thus your code becomes
def selfSufficiency[A](a: Seq[A], b: Seq[A])
(implicit n: Fractional[A]):A = {
import n._
a.sum/b.sum
}
And now it works.
Edit
I just read this part of your question.
Does my implementation limits the user to have the same type "A" for both inputs? In other words, can I do this with my code?
Because both Fractional and Numeric are parametrized in just one T, both arguments have to be from the same type - for example take a look to the div function.
However, since numeric values of less precision are subtypes of the ones with higher (fig 1). You can make it work by upcast, but you will need to help the compiler a little more.
selfSufficiency[Double](Seq(1,2,3), Seq(2.0,1.3)) // res1: Double = 1.8181818181818183
Note: Without specifying the type as Double, the compiler will yield the following error.
error: could not find implicit value for parameter n: Fractional[AnyVal]
fig 1
Reference: https://www.artima.com/pins1ed/scalas-hierarchy.html
What you are looking for is the Fractional trait which is a more narrow Numeric (subtype) that supports div.

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.

Why Scala compiler throws IndexOutOfBoundException while applying foreach on a mutable list

I have the following Code.
import scala.collection.mutable.MutableList
val x = MutableList[Int]()
(1 to 10).foreach(x+=1)
I get the java.lang.IndexOutOfBoundsException: 1 error.
but,
(1 to 10).foreach(println) this does not throw any error.
the indexOutOfBoundException can be solved by using lambda Operator as follows:
(1 to 10).foreach(_ => x+=1)
Everything works fine with this.
My questions are :
1. Why do i need to use lambda operator in first case unlike second one?
2. Why the compiler throws IndexOutOfBoundException, i suppose this is not the correct context for this Exception.
What happens is a few little conveniences in the library conspiring to bite you.
foreach signature is
def foreach(f: A => Unit): Unit
In your case, A is Int, so it needs a function which takes an Int and returns Unit. Fine with println. Note you have just written println, not println(something), which would not have been a function.
One would expect x += 1 to be just an instruction, so it would have type Unit, not a function, not a valid argument of foreach, and one would get a helpful compile-time error. But += in MutableList actually returns the list, which is convenient as it makes chaining operations easier:
def +=(elem: A): this.type
So the type of x+= 1 is MutableList[Int]. One will still expect a compilation error, not a function. Except that MutableLists (all Seqs actually) are functions, with Int parameters, returning the type of the Seq's elements. The function simply returns the i-th element. Again, that may be convenient, you may simply pass the seq where a function is expected, instead of having to write i => seq(i). Now you have a function, with an Int parameter, what foreach expects.
Still, it does not returns Unit, but Int. However, scala will accept that as an Int => Unit, just discarding the value. So it compiles.
Now to what it does: first, it evaluates the argument in foreach, so it calls x+=1, getting the list x, which now contains an element. It will then call this function, which is the access to the i-th element with arguments ranging from 1 to 10). Doing that, it would not add values to the list, but just access elements at the given indexes. It then fails immediately, as the list contains just one element, at index 0, so calling with 1 throws the IndexOutOfBoundException.

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

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.

Why do people use _? as an identifier suffix?

I start reading Lift framework source code, I find that there're so many methods are defined using a name like methodName_? , is there a convention that _? has some special meaning?
def empty_? : Boolean = {}
You're unlikely to see the construct outside of the lift framework; I suspect that it's mostly Ruby-envy.
Almost any other Scala project will shy away from this syntax. Not because of the trailing question mark, but because it's yet another way to introduce underscores into your code - and the symbol is already far too heavily overloaded.
Based on an evaluation of multiple Scala projects, the notation can be reasonably described as non-idiomatic.
UPDATE
The reason that the underscore is required is to disambiguate from infix notation, in which:
x?y
would be read as
x.?(y)
with ? being a method name. Whereas:
x_?y
Clearly demarks x_? as being atomic.
The syntax is an example of what is formally known as a "mixed identifier", and is intended to allow definitions such as
def prop_=(v:String) = ... //setter
def unary_- = ... //prefix negation operator
It could (arguably) be considered a hack when similar construct is used simply to shove a question mark at the end of a method name.
The ? denotes that this is a predicate, a function returning Boolean. This convention goes back to Lisp, where ? (Scheme), p or -p (other Lisps, simulating the question mark with a "similar" letter) also denote predicates. Think of it as asking a question, "is the object empty?"
Scala will only allow mixed identifier names (containing alphanumerics and punctuation) if you separate them by _. E.g.,
scala> def iszero?(x : Int) = x == 0
<console>:1: error: '=' expected but identifier found.
def iszero?(x : Int) = x == 0
^
doesn't work, but
scala> def iszero_?(x : Int) = x == 0
iszero_$qmark: (x: Int)Boolean
does.