How to pass a scala class as an object into a function parameter? - scala

How do I run the refint1 function? I've triedvar x = new RefInt(5) and then doing scala> argpass.refint1(x)but get a found: RefInt, required : argpass.RefInt => Unit error in the console.
object argpass{
class RefInt (initial : Int) {
private var n : Int = initial
def get () : Int = n
def set (m : Int) : Unit = { n = m}
}
def refint1 ( f: RefInt => Unit) : (Int, Int, Int) = {
var x = new RefInt(5)
val first = f(x)
val firstget = x.get
val sec = f(x)
val secget = x.get
val third = f(x)
val thirdget = x.get
(firstget, secget, thirdget)
}
//How do i run the refint1 function?

As Luis said in the comments, f returns Unit, which is basically void. This should solve your problem:
class RefInt(initial: Int) {
var n: Int = initial
def get(): Int = n
def set(m: Int): Unit = { n = m }
}
def refint1(f: RefInt => Unit): (Int, Int, Int) = {
var x = new RefInt(5)
f(x)
val firstget = x.get
f(x)
val secget = x.get
f(x)
val thirdget = x.get
(firstget, secget, thirdget)
}
That being said, I think you can improve your design a little bit. Here's a different approach to solve the same problem:
case class RefInt(initial: Int)
def refInt1(initial: RefInt, f: RefInt => RefInt) : (Int, Int, Int) = {
val x0 = f(initial)
val x1 = f(x0)
val x2 = f(x1)
(x0.initial, x1.initial, x2.initial)
}
println(refInt1(RefInt(5), ri => ri.copy(ri.initial * 2)))

Related

Cannot create constructor with logic in Scala program?

I have the following program:
class Rational(n: Int, d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g
def this(n: Int) = this(n, 1)
def this(s: String) = {
val regex: Regex = "^([+-]?(\\d+|\\d*\\.?\\d+)|\\d*\\/?\\d+)$".r
if (!regex.matches(s)) throw new NumberFormatException()
val input: Array[String] = s.split("\\.|\\/")
val num: Int = input(0).toInt
if (input.length equals 1)
this(num, 1) // problem here
else
this(num, input(1).toInt) // problem here
}
}
I tried to create the constructor with some logic. However, I cannot due to
'Rational' does not take parameters
What's the problem?
Try to introduce a helper method
import scala.util.matching.Regex
def gcd(i: Int, i1: Int): Int = BigInt(i).gcd(BigInt(i1)).toInt
class Rational(n: Int, d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g
def this(n: Int) = this(n, 1)
def this(s: String) = {
this(Rational.transformStr(s)._1, Rational.transformStr(s)._2)
}
}
object Rational {
// helper method
def transformStr(s: String): (Int, Int) = {
val regex: Regex = "^([+-]?(\\d+|\\d*\\.?\\d+)|\\d*\\/?\\d+)$".r
if (!regex.matches(s)) throw new NumberFormatException()
val input: Array[String] = s.split("\\.|\\/")
val num: Int = input(0).toInt
if (input.length equals 1)
(num, 1)
else
(num, input(1).toInt)
}
}
or better, factory methods (because constructors have many limitations)
class Rational(n: Int, d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g
}
object Rational {
// factory methods
def apply(n: Int) = new Rational(n, 1)
def apply(s: String): Rational = {
val regex: Regex = "^([+-]?(\\d+|\\d*\\.?\\d+)|\\d*\\/?\\d+)$".r
if (!regex.matches(s)) throw new NumberFormatException()
val input: Array[String] = s.split("\\.|\\/")
val num: Int = input(0).toInt
if (input.length equals 1)
new Rational(num, 1)
else
new Rational(num, input(1).toInt)
}
}
Executing code in overloaded constructor prior to calling this()
By the way, you can also use default values
class Rational(n: Int, d: Int = 1 /*default*/ ) {
// ...
}
object Rational {
def apply(s: String): Rational = ???
}

Scala, why when I pass a lambda function as argument to another function i cannot execute it

I am trying to create a concurrent method that saves in two different variables the result of two blocks of code task1 and task2:
def parallel[A, B](fun_a: => A, fun_b: => B): (A, B) = {
var res_a: A = 1.asInstanceOf[A]
var res_b: B = 1.asInstanceOf[B]
val hilo = new Thread {
override def run(): Unit = {
res_a = fun_a
}
}
val hilo1 = new Thread() {
override def run(): Unit = {
res_b = fun_b
}
}
hilo.start()
hilo1.start()
hilo.join()
hilo1.join()
(res_a, res_b)
}
val task1 = {3+4}
val task2 = {3*1}
println(parallel(task1, task2))
This is the correct answer in theory but I do not understand if val task1/task2 are functions or just the result of the block inside brackets. I tried to edit the method parallel to accept only generic values:
def parallel[A, B](fun_a: A, fun_b: B): (A, B)
and it still works fine. In this case, The computation of task1 and task2 is made before they pass as parameter to the function, or is made when the result is assigned to the variables res_a, res_b in each thread?
I tried to pass task1 and task2 as a method, it works fine but when I pass it as function, in the variable is saved the serialization of the function.
def task1():Int = {3+4} //method
val task2: Int => Int = (x:Int) => {3*x} //anonymous function
println(parallel(task1, task2))
i changed the code so the anonymous function gets executed but now i get an exception:
def parallel[A, B](fun_a: => A, fun_b: => B): (A, B) = {
var res_a: A = 1.asInstanceOf[A]
var res_b: B = 1.asInstanceOf[B]
val hilo = new Thread {
override def run(): Unit = {
res_a = fun_a
}
}
val hilo1 = new Thread() {
override def run(): Unit = {
res_b = fun_b(3) // here, because i think this is a function {val task2: Int => Int = (x:Int) => {3*x} i try to pass its argument
}
}
hilo.start()
hilo1.start()
hilo.join()
hilo1.join()
(res_a, res_b)
}
it says that B does not take parameters but i defined it before as a lambda that takes one parameter.
I do not understand why i defined the method as one that takes as arguments two functions but it does not let me pass arguments to that functions
The following code works:
def parallel[A, B](fun_a: => A, fun_b: Int => B): (A, B) = {
var res_a: A = 1.asInstanceOf[A]
var res_b: B = 1.asInstanceOf[B]
val hilo = new Thread {
override def run(): Unit = {
res_a = fun_a
}
}
val hilo1 = new Thread() {
override def run(): Unit = {
res_b = fun_b(3)
}
}
hilo.start()
hilo1.start()
hilo.join()
hilo1.join()
(res_a, res_b)
}
println(
parallel(
{ 3 * 3 },
(x: Int) => { 3 + x }
)
)
Note how the type declaration of fun_b is changed to fun_b: Int => B. In this case, fun_a doesn't do much, though.
And admittedly, the generic type doesn't make much sense, if Int is hard coded in there. So a more sensible solution would be something like this:
def parallel[A, B](fun_a: A => A, fun_b: B => B, a: A, b: B): (A, B) = {
var res_a: A = 1.asInstanceOf[A]
var res_b: B = 1.asInstanceOf[B]
val hilo = new Thread {
override def run(): Unit = {
res_a = fun_a(a)
}
}
val hilo1 = new Thread() {
override def run(): Unit = {
res_b = fun_b(b)
}
}
hilo.start()
hilo1.start()
hilo.join()
hilo1.join()
(res_a, res_b)
}
println(
parallel(
(y: Int) => { y * 3 },
(x: Int) => { x + 3 },
3,
3
)
)
println(
parallel(
(y: Int) => { y * 3 },
(x: String) => { x + 3 },
3,
"3"
)
)
println(
parallel(
(y: String) => { y * 3 },
(x: Int) => { x + 3 },
"3",
3
)
)
This will print:
(9,6)
(9,33)
(333,6)

Test to make sure two functions run concurrently?

Suppose I've got a function runConcurrently(f1: Int => Int, f2: Int => Int): (Int, Int) that return results of f1 and f2.
Now I'd like to write a test to make sure that f1 and f2 run concurrently when runConcurrently is invoked. I'd like to make the test deterministic and as efficient as possible.
How would you suggest write the test ?
P.S. I don't want to couple it with any specific test framework or library. The only dependency should be the Scala/Java SDK.
The closest you can do is use some kind of a shared condition that both functions use:
def runConcurrently(f1: => Int, f2: => Int): Future[(Int, Int)] =
Future(f1) zip Future(f2)
val sem1 = new Semaphore(0)
val sem2 = new Semaphore(0)
def f1 = {
sem1.release
sem2.acquire
1
}
def f2 = {
sem2.release
sem1.acquire
2
}
Await.result(runConcurrently(f1, f2), 1 second) shouldBe (1,2)
The idea is that neither of the functions can complete before the other one has at least started. So, an attempt to run them sequentially will never finish, and you'll get a timeout.
In particular, this code will fail if you try to run it with a single-threaded execution context.
As said before, this probably wont always work, also is far from being deterministic.
But, it may serve you.
final class FunctionMeter[-I, +O](private[this] val underlying: I => O) {
private[this] var start: Long = _
private[this] var finish: Long = _
def getStartTime: Long = start
def getFinishTime: Long = finish
def getFun: I => O = input => {
start = System.nanoTime()
val output = underlying(input)
finish = System.nanoTime()
output
}
}
def test(f1: Int => Int, f2: Int => Int): Boolean {
val m1 = new FunctionMeter(f1)
val m2 = new FunctionMeter(f2)
runConcurrently(m1.getFunction, m2.getFunction)
m2.getStartTime < m1.getFinishTime && m1.getStartTime < m2.getFinishTime
}
Anyways, I am with Dima that this is not something you should test.
An ugly solution for an ugly problem:
object Test extends App {
def runConcurrently(f1: () => Int, f2: () => Int): (Int, Int) = {
import ExecutionContext.Implicits.global
val f = Future(f1())
val g = Future(f2())
Await.result(f.zip(g), Duration.Inf)
}
#volatile var start1: Long = 0
#volatile var start2: Long = 0
#volatile var end1: Long = 0
#volatile var end2: Long = 0
val f1 : () => Int = {
case x : Unit => {
start1 = System.nanoTime()
Thread.sleep(1000)
end1 = System.nanoTime()
1
}
}
val f2 : () => Int = {
case x : Unit => {
start2 = System.nanoTime()
Thread.sleep(1000)
end2 = System.nanoTime()
1
}
}
runConcurrently(f1, f2)
assert(start1 < end2)
assert(start2 < end1)
}

Can a partially applied function be extracted or interrogated for the applied parameter value

Is there a way to extract or interrogate a partially applied function to get the applied value.
For example, can the value 3 be extracted from reduceBy3 in the code below.
def subtract(x:Int, y:Int) = x-y
val reduceBy3 = subtract(3,_:Int)
I have experimented with creating an extractor has shown in the example below however the unapply method must accept an (Int=>Int) function that requires interrogation.
class ReduceBy(y: Int) {
val amt = y
def subtract(y: Int, x: Int) = x - y
}
object ReduceBy extends Function1[Int, Int => Int] {
def apply(y: Int) = {
val r = new ReduceBy(y)
r.subtract(y, _: Int)
}
def unapply(reduceBy: ReduceBy): Option[Int] = Some(reduceBy.amt)
}
object ExtractPartialApplied extends App {
val r3 = ReduceBy(3)
val extract = r3 match {
case ReduceBy(x) => ("reduceBy", x)
case x: ReduceBy => ("reduceBy", x.amt)
case _ => ("No Match", 0)
}
println(extract)
val z = r3(5)
println(z)
}
You can have your subtract method receive the first parameter, and then return a function-like object which will then take the second parameter, similarly to a multiple-argument-list function, but which you can then extend however you wish.
This doesn't look very elegant though, and needs a bit of manual boilerplate.
class ReduceBy(val amt: Int) {
def subtract(x: Int) = {
val xx = x // avoid shadowing
new Function[Int, Int] {
def x = xx
def apply(y: Int) = x - y
}
}
}
A solution adapting the answer by danielkza is to have the companion object do the extraction and return a ReduceBy function that holds onto the the initial value.
object ReduceBy {
def apply(y: Int) = new ReduceBy(y)
def unapply(reduceBy: ReduceBy): Option[Int] = Some(reduceBy.amt)
}
class ReduceBy(val amt: Int) extends Function[Int, Int] {
def apply(y: Int) = y - amt
}
object ExtractPartialApplied extends App {
val reduceBy3 = ReduceBy(3)
val extract = reduceBy3 match {
case ReduceBy(x) => ("ReduceBy(x)", x)
case x: ReduceBy => ("ReduceBy", x.amt)
case _ => ("No Match", 0)
}
println(extract)
println(reduceBy3(5))
}

Setting instance vars with apply

With Array it's possible to get and set elements with val i = xs(0) and xs(0) = i syntax. How to implement this functionality in my own class? So far I was only able to implement getting the values.
class Matrix(val m : Int, val n : Int) {
val matrix = Array.ofDim[Double](m, n)
def apply(i:Int)(j:Int) = matrix(i)(j)
}
UPDATE: Thanks to Mauricio for answer about update method. That's the final version
class Matrix(val m:Int, val n:Int) {
private val matrix = Array.ofDim[Double](m, n)
def apply(i:Int) = new {
def apply(j:Int) = matrix(i)(j)
def update(j:Int, v:Double) = { matrix(i)(j) = v }
}
}
it("matrix") {
val m = new Matrix(3, 3)
m(0)(1) = 10.0
val x = m(0)(1)
x should equal(10.0)
x.isNegInfinity should be (false) // Implicits for Double work!
}
You need to declare an update method:
class Matrix(val m : Int, val n : Int) {
private val matrix = Array.ofDim[Double](m, n)
def apply(i:Int)(j:Int) = matrix(i)(j)
def update( i : Int, j : Int, value : Double) {
matrix(i)(j) = value
}
}
val m = new Matrix( 10, 10 )
m(9, 9) = 50