How can I pass the parameter in the function num()? - scala

object MatchTest4 extends App{
def matchTest(x: Any): Any = x match {
case 1 => def num(p: Int, q: Int): Unit = {
val sum = p + q
println(sum)
}
case 2 => def num(p: Int, q: Int): Unit = {
val sub = p - q
println(sub)
}
case 3 => def num(p: Int, q: Int): Unit = {
val mul = p * q
println(mul)
}
case 4 => def num(p: Int, q: Int): Unit = {
val div = p / q
println(div)
}
case _ => println("Invalid Choice")
}
println("Enter Your Choice")
val b= readInt()
println(matchTest(b))
}
Now I want to give parameter to the function num().Is it possible?

The below code should accomplish what you are trying to do. The changes I made were:
Removed the return type for the matchTest. Scala will automatically infer the return type as a function value.
Replaced the method definitions "num" by anonymous functions.
Modified the signature of your wildcard pattern match to also return a function consistent with other pattern matches. (This is a hack, I hope someone knows a better way)
You can run your returned anonymous functions like matchTest(4)(2,3) etc.
def matchTest(x: Any) = x match {
case 1 => (p: Int, q: Int) => {
val sum = p + q
println(sum)
}
case 2 => (p: Int, q: Int) => {
val sub = p - q
println(sub)
}
case 3 => (p: Int, q: Int) => {
val mul = p * q
println(mul)
}
case 4 => (p: Int, q: Int) => {
val div = p / q
println(div)
}
case _ => println("Invalid Choice"); (a: Int, b: Int) => println("Invalid Choice")
}

Related

How to use pattern matching with function values in Scala

I have several functions with same input and output types initialized in an object
object Utils {
def f1(value: Int): Double = ???
def f2(value: Int): Double = ???
def f3(value: Int): Double = ???
}
I have a list of higher order values for those functions:
val x = List(Utils.f1, Utils.f2)
How can I use pattern matching to check which functions of those declared in the object are contained in x? I would like to obtain something similar to the following code:
x(0) match {
case Utils.f1 => ...
case Utils.f2 => ...
}
You can't match against functions, it has no meaningfully defined equality.
This will be possible if you make f1, f2, f3 vals. Please notice that upon pattern matching the equality by reference will be used
object Utils {
val f1: Int => Double = _ * 10.0
val f2: Int => Double = _ * 20.0
val f3: Int => Double = _ * 30.0
}
val x: Seq[Int => Double] = List(Utils.f1, Utils.f2)
import Utils._
x(0) match {
case `f1` => println(1)
case `f2` => println(2)
case `f3` => println(3)
}
If you keep f1, f2, f3 defs then
object Utils {
def f1(value: Int): Double = value * 10.0
def f2(value: Int): Double = value * 20.0
def f3(value: Int): Double = value * 30.0
}
val x: Seq[Int => Double] = List(Utils.f1, Utils.f2)
val f1: Int => Double = Utils.f1
val f2: Int => Double = Utils.f2
val f3: Int => Double = Utils.f3
x(0) match {
case `f1` => println(1)
case `f2` => println(2)
case `f3` => println(3)
}
produces MatchError.

Why can Unit be assigned to a Tuple without compilation error?

Check this REPL session, under Scala 2.12.10:
scala> val a = 3 match { case 3 => 1 case 4 => println("why") }
a: AnyVal = 1
scala> val a: Int = 3 match { case 3 => 1 case 4 => println("why") }
<console>:11: error: type mismatch;
found : Unit
required: Int
val a: Int = 3 match { case 3 => 1 case 4 => println("why") }
scala> val (a, b) = 3 match { case 3 => (1, 2) case 4 => println("why") }
a: Any = 1
b: Any = 2
scala> val (a: Int, b) = 3 match { case 3 => (1, 2) case 4 => println("why") }
a: Int = 1
b: Any = 2
scala> val (a, b) = 4 match { case 3 => (1, 2) case 4 => println("why") }
why
scala.MatchError: () (of class scala.runtime.BoxedUnit)
... 36 elided
I would expect the snippets with tuples to not compile as if Unit is ever returned from the second match, then you always get a runtime error. Why does Unit match successfully to Tuple2 in the compiler view?
Unit cannot be assigned to a Tuple
val t: (Int, Int) = () // Error: type mismatch; found: Unit required: (Int, Int)
However the following syntax represents proper pattern matching
val (a: Int, b: Int) = ...
which in your case desugars to something like so
val x: Any = 3 match {
case 3 => (1, 2)
case 4 => println("why")
}
val a: Int = x match {
case t: (_, _) if t._1.isInstanceOf[Int] => t._1.asInstanceOf[Int]
}
val b: Int = x match {
case t: (_, _) if t._2.isInstanceOf[Int] => t._2.asInstanceOf[Int]
}
Notice those asInstanceOf[Int] which convince compiler static type of a and b is Int, however what would happen at runtime is a different story. For example, consider
val t: (Int, Int) = println("why").asInstanceOf[(Int, Int)]
which compiles but fails a runtime.
Analysing -Xprint:jvm output of
lazy val (a: Int, b: Int) = (): Any
we have approximately
val t: Tuple2 = {
val x1: Any = ()
if (x1.isInstanceOf[Tuple2]) {
val x2: Tuple2 = x1.asInstanceOf[Tuple2]
val a: Any = x2._1
val b: Any = x2._2
if (a.isInstanceOf[Int]) {
val x3: Int = scala.Int.unbox(a) // in effect asInstanceOf[Int]
if (b.isInstanceOf[Int]) {
val x4: Int = scala.Int.unbox(b) // in effect asInstanceOf[Int]
new Tuple2(x3, x4)
} else throw new MatchError(x1)
} else throw new MatchError(x1)
} else throw new MatchError(x1)
}
def a: Int = t._1
def b: Int = t._2
whilst
lazy val (a: Int, b: Int) = ()
does not compile, hence if expression on the right of =, in pattern value definition, types to Any it makes all the difference.
Since your partial function can return either a Tuple2[Int, Int] or a Unit, the compiler considers its return type to be the "smallest common supertype" of those two types, that is Any :
scala> val x = 4 match { case 3 => (1, 2) case 4 => println("why") }
why
x: Any = ()
Notice how the return value is x: Any = () and not x: Unit = ().
What you're doing when extracting the tuple is equivalent to this, which compiles (since Any is a supertype of Tuple2), but produces a MatchError:
scala> val (a, b) = ().asInstanceOf[Any]
scala.MatchError: () (of class scala.runtime.BoxedUnit)
... 28 elided

Restricting Method Parameter to a Specific Type in Scala

I have a function that I would like it to be generic but restrict it to take a certain subtypes. To keep things simple, I want my function to just work on Long, Int, Float and Double. So here is what I have come up with:
def covariance[A](xElems: Seq[A], yElems: Seq[A]): A = {
val (meanX, meanY) = (mean(xElems), mean(yElems))
val (meanDiffX, meanDiffY) = (meanDiff(meanX, xElems), meanDiff(meanY, yElems))
((meanDiffX zip meanDiffY).map { case (x, y) => x * y }.sum) / xElems.size - 1
}
def mean[A](elems: Seq[A]): A = {
(elems.fold(_ + _)) / elems.length
}
def meanDiff[A](mean: A, elems: Seq[A]) = {
elems.map(elem => elem - mean)
}
Here is the method that I will use to check for the above mentioned types:
import scala.reflect.{ClassTag, classTag}
def matchList2[A : ClassTag](list: List[A]) = list match {
case intlist: List[Int #unchecked] if classTag[A] == classTag[Int] => println("A List of ints!")
case longlist: List[Long #unchecked] if classTag[A] == classTag[Long] => println("A list of longs!")
}
Notice that I'm using ClassTag. I can also use a TypeTag and perhaps even the Shapeless library.
I would like to know if this is a good approach? Or should I use bounded types to solve what I want?
EDIT: Based on the comment and suggestion to use the Fractional Typeclass, here is how I think it could work!
def covariance[A: Fractional](xElems: Seq[A], yElems: Seq[A]): A = {
val (meanX, meanY) = (mean(xElems), mean(yElems))
val (meanDiffX, meanDiffY) = (meanDiff(meanX, xElems), meanDiff(meanY, yElems))
((meanDiffX zip meanDiffY).map { case (x, y) => x * y }.sum) / xElems.size - 1
}
def mean[A](elems: Seq[A]): A = {
(elems.fold(_ + _)) / elems.length
}
def meanDiff[A](mean: A, elems: Seq[A]) = {
elems.map(elem => elem - mean)
}
Based on the comments and inputs, here is what I came up with!
def mean[A](xs: Seq[A])(implicit A: Fractional[A]): A =
A.div(xs.sum, A.fromInt(xs.size))
def covariance[A](xs: Seq[A], ys: Seq[A])(implicit A: Fractional[A]): A = {
val (meanX, meanY) = (mean(xs), mean(ys))
val (meanDiffX, meanDiffY) = (meanDiff(meanX, xs), meanDiff(meanY, ys))
(meanDiffX zip meanDiffY).map { case (x, y) => A.div(A.times(x, y), A.fromInt(xs.size - 1)) }.sum
}
def meanDiff[A](mean: A, elems: Seq[A])(implicit A: Fractional[A]): Seq[A] = {
elems.map(elem => A.minus(elem, mean))
}

Partial Functions as an input parameter in scala

I am trying to pass the partial function as input to square function.
What is worng with the following code?
package PartialFunction
object PartialFunctionSum {
val yourConstant = 10
val pf: PartialFunction[(Int, Int), Int] = {
case (x, y) => x + y + yourConstant
}
def square(cb:(Int, Int) => Int): Unit = {
println(cb(5,10))
}
def main(args: Array[String]): Unit= {
square(pf)
}
}
A PartialFunction is a Function1 (a => b) and square needs a Function2 ((a,b) => c)
One way to accomplish what you want to do is changing cb type to Function1.
object PartialFunctionSum extends App {
val yourConstant = 10
val pf: PartialFunction[(Int, Int), Int] = {
case (x, y) => x + y + yourConstant
}
def square(cb:((Int, Int)) => Int): Unit = {
println(cb(5,10))
}
square(pf)
}
Also, anywhere where you need a FunctionX, you can define a PartialFunction, so
square {
case (x, y) => x + y + yourConstant
}
Or transform your PartialFunction in a Function2 with a lambda
square( pf.apply(_, _) )
Anywhere you need a function you can a pass a PartialFunction,
Your problem is with square definition:
def square(cb:(Int, Int) => Int): Unit = {
println(cb(5,10))
}
That means that cb is a function that receives two Ints and returns another Int.
Just change square signature as follows:
def square(cb: ((Int, Int)) => Int): Unit = {
println(cb(5 -> 10))
}
And now your types are compatible and the rest of your code works as you expected.
(Int, Int) => Int is an instance of Function2[Int, Int, Int](a Function that takes 2 Int parameters and returns an Int), not PartialFunction[(Int, Int), Int] (a partial function that takes an input of type (Int, Int) and returns an Int)
If you want to pass your parameters as a Tuple then:
def square(cb:PartialFunction[(Int, Int),Int]): Unit = {
println(cb((5,10)))
}
Example:
def square(cb:PartialFunction[(Int, Int),Int]): Unit = {
println(cb((5,10)))
}
square: (cb: PartialFunction[(Int, Int),Int])Unit
scala> square{case (i, j) => i * j}
50

How to declare implicit arguments in higher order functions?

I want IMPLICIT args in a higher order function, like:
func(arg1) { implicit (x, y) => x * y }
But the compiler says:
error: expected start of definition
val a = func("2", "4") { implicit (x, y) =>
^
java version "1.7.0_40"
Scala code runner version 2.10.2-RC2 -- Copyright 2002-2013, LAMP/EPFL
The runnable sample code:
object Test extends App {
new Test().run
}
class Test {
def run = {
val a = func("2", "4") { (x, y) => // It's OK
x * y
}
println("a: " + a)
val b = gunc("2", "4") { implicit x => { implicit y => // It's OK
x * y
}}
println("b: " + b)
}
def func(x: String, y: String)(f: (Int, Int) => Int) = f(x.toInt, y.toInt)
def gunc(x: String, y: String)(g: Int => Int => Int) = g(x.toInt)(y.toInt)
def hunc(x: String, y: String)(h: Tuple2[Int, Int] => Int) = h((x.toInt, y.toInt))
}
[ADD COMMENT]
I wonder...
We can declare as "implicit x => ..." with one arg.
It seems there is no way to declare two implicit args.
Try adding:
val c = hunc("2", "4") { implicit pair => pair._1 * pair._2 }
When you say implicit y => y * 2 you're not
declaring an implicit argument but mark the function as implicit,
so you make an analog to this:
implicit val f1 = (y: Int) => y * 2
def func1(x: String, y: String)(f: Int => Int) = f(1)
func1("", "")(f1)
When you want to mark a function with two
arguments as implicit you can do it this way:
implicit val f2 = (x: Int, y: Int) => y * 2
def func2(x: String, y: String)(f: (Int, Int) => Int) = f(1, 2)
func2("", "")(f2)
But you cannot do it so:
func2("", "")(implicit (x, y) => x), in this particular case I just don't see any meaning to use implicits.
Also you can see this question, maybe you'll find some useful information there