通过scala中的反射检查两种类型是否等价
Check if two types are equivalent through reflection in scala
我有一些代码:
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 {})
}
}
由于这段代码会 运行 很多,因此我正在尝试对其进行大量优化,因此,我正在尝试合并 combine 函数的前两行。为此,我认为代码看起来像这样:
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 {})
}
}
有什么方法可以让代码只检查两种类型是否相同,这样我就不必匹配所有情况?
这里有很多问题:
这些测试不太可能对性能产生任何影响,因为创建 运行 一个 Future
是一个复杂得多的操作,并且会占用大量时间。
类型参数是不必要的,因为值总是被视为 LogicUnit
,所以签名可以是:
def combine(arg1: LogicUnit, arg2: LogicUnit): Future[LogicUnit]
最好使用 match
而不是 isInstanceOf
,因为编译器会知道参数的类型。
第一个版本不依赖于arg1
的类型所以不用测试:
def combine(arg1: LogicUnit, arg2: LogicUnit): Future[LogicUnit] =
arg2 match {
case _: Ezib => Future(new Ezib {})
case _: Zieb => Future(new Zieb {})
}
如果您确实需要测试两个参数,请嵌套测试以免重复第一个测试:
def combine(arg1: LogicUnit, arg2: LogicUnit): Future[LogicUnit] =
arg1 match {
case a1: Ezib =>
arg2 match {
case a2: Ezib => Future(???)
case a2: Zieb => Future(???)
}
case a1: Zieb =>
arg2 match {
case a2: Ezib => Future(???)
case a2: Zieb => Future(???)
}
}
这个公式清晰易读,它允许每个分支使用 a1
和 a2
的值,编译器知道这些值是已匹配的特定类型。
也可能是使用 combine
的多态版本会提高性能:
def combine(arg1: Ezib, arg2: Ezib): Future[LogicUnit] = ???
def combine(arg1: Ezib, arg2: Zieb): Future[LogicUnit] = ???
def combine(arg1: Zieb, arg2: Ezib): Future[LogicUnit] = ???
def combine(arg1: Zieb, arg2: Zieb): Future[LogicUnit] = ???
def combine(arg1: LogicUnit, arg2: LogicUnit): Future[LogicUnit] =
arg1 match {
case a1: Ezib =>
arg2 match {
case a2: Ezib => combine(a1, a2)
case a2: Zieb => combine(a1, a2)
}
case a1: Zieb =>
arg2 match {
case a2: Ezib => combine(a1, a2)
case a2: Zieb => combine(a1, a2)
}
}
如果在调用点已知具体类型,则编译器可以直接调用适当的方法,而不必匹配类型。
我有一些代码:
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 {})
}
}
由于这段代码会 运行 很多,因此我正在尝试对其进行大量优化,因此,我正在尝试合并 combine 函数的前两行。为此,我认为代码看起来像这样:
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 {})
}
}
有什么方法可以让代码只检查两种类型是否相同,这样我就不必匹配所有情况?
这里有很多问题:
这些测试不太可能对性能产生任何影响,因为创建 运行 一个 Future
是一个复杂得多的操作,并且会占用大量时间。
类型参数是不必要的,因为值总是被视为 LogicUnit
,所以签名可以是:
def combine(arg1: LogicUnit, arg2: LogicUnit): Future[LogicUnit]
最好使用 match
而不是 isInstanceOf
,因为编译器会知道参数的类型。
第一个版本不依赖于arg1
的类型所以不用测试:
def combine(arg1: LogicUnit, arg2: LogicUnit): Future[LogicUnit] =
arg2 match {
case _: Ezib => Future(new Ezib {})
case _: Zieb => Future(new Zieb {})
}
如果您确实需要测试两个参数,请嵌套测试以免重复第一个测试:
def combine(arg1: LogicUnit, arg2: LogicUnit): Future[LogicUnit] =
arg1 match {
case a1: Ezib =>
arg2 match {
case a2: Ezib => Future(???)
case a2: Zieb => Future(???)
}
case a1: Zieb =>
arg2 match {
case a2: Ezib => Future(???)
case a2: Zieb => Future(???)
}
}
这个公式清晰易读,它允许每个分支使用 a1
和 a2
的值,编译器知道这些值是已匹配的特定类型。
也可能是使用 combine
的多态版本会提高性能:
def combine(arg1: Ezib, arg2: Ezib): Future[LogicUnit] = ???
def combine(arg1: Ezib, arg2: Zieb): Future[LogicUnit] = ???
def combine(arg1: Zieb, arg2: Ezib): Future[LogicUnit] = ???
def combine(arg1: Zieb, arg2: Zieb): Future[LogicUnit] = ???
def combine(arg1: LogicUnit, arg2: LogicUnit): Future[LogicUnit] =
arg1 match {
case a1: Ezib =>
arg2 match {
case a2: Ezib => combine(a1, a2)
case a2: Zieb => combine(a1, a2)
}
case a1: Zieb =>
arg2 match {
case a2: Ezib => combine(a1, a2)
case a2: Zieb => combine(a1, a2)
}
}
如果在调用点已知具体类型,则编译器可以直接调用适当的方法,而不必匹配类型。