I have some code:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
trait LogicUnit
trait Ezib extends LogicUnit
trait Zieb extends LogicUnit
object LogicUnit {
@inline
def combine[A <: LogicUnit, B <: LogicUnit](arg1: A, arg2: B): Future[LogicUnit] = {
if (arg1.isInstanceOf[Ezib] && arg2.isInstanceOf[Ezib]) return Future(new Ezib {})
else if (arg1.isInstanceOf[Zieb] && arg2.isInstanceOf[Zieb]) return Future(new Zieb {})
else if (arg1.isInstanceOf[Ezib] && arg2.isInstanceOf[Zieb]) return Future(new Zieb {})
else return Future(new Ezib {})
}
}
Since this code will be run a lot I am trying to optimize it a lot hence, I am trying to combine the first two lines of the combine function. To do so I figured the code would look something like this:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
trait LogicUnit
trait Ezib extends LogicUnit
trait Zieb extends LogicUnit
object LogicUnit {
@inline
def combine[A <: LogicUnit, B <: LogicUnit](arg1: A, arg2: B): Future[LogicUnit] = {
if (arg1.isInstanceOf[typeOf(arg2)]) return Future(arg1)
else if (arg1.isInstanceOf[Ezib] && arg2.isInstanceOf[Zieb]) return Future(new Zieb {})
else return Future(new Ezib {})
}
}
Is there any way I can get the code to just check if the two types are the same so I don't have to match for all cases?
There are a number of issues here:
It is unlikely that these tests are going to make any difference to the performance because creating and running a
Future
is a much more complex operation and will dominate the time.The type parameters are unnecessary since the values are always treated as
LogicUnit
so the signature can just be:It is better to use
match
rather thanisInstanceOf
because the compiler then knows what the type of the argument is.The first version does not depend on the type of
arg1
so there is no need to test it:If you do need to test both arguments, nest the tests so that the first test is not repeated:
This formulation is clear and readable, and it allows each branch to use a value of
a1
anda2
that are known by the compiler to be the specific type that has been matched.It may also be the case that using polymorphic versions of
combine
would improve performance:If the concrete type is known at the call site then the compiler can call the appropriate method directly rather than having to match the type.