我的应用程序需要一个参数提供程序 sum
,可以添加到任何library(dplyr)
library(tidyr)
bookings %>%
separate_rows(roomIDs, convert = TRUE) %>%
left_join(rooms, by = c(roomIDs = 'ID')) %>%
group_by(ID, numofRooms) %>%
summarise(roomIDs = paste(roomIDs, collapse= '|'), numofbeds = sum(numofBeds))
# A tibble: 6 x 4
# Groups: ID [?]
# ID numofRooms roomIDs numofbeds
# <int> <int> <chr> <int>
#1 1160545 1 1202544 10
#2 1160546 2 1202547|1202563 5
#3 1160547 2 1202562|1202564 9
#4 1160548 1 1202565 4
#5 1160549 1 1202566 7
#6 1160550 3 1203751|1203752|1203753 6
以允许传递 任意数量的参数输入。
trait
然后,我可以使用他们的class
从trait Arg
case class NamedArg(key: String, value: Any) extends Arg
// I extend my classes with this trait
trait ArgsProvider {
val args: Seq[Arg]
lazy val namedArgs: Map[String, Any] = {
args.filter(_.isInstanceOf[NamedArg]).
map(_.asInstanceOf[NamedArg]).
map(arg => arg.key -> arg.value).toMap
}
...
}
NamedArg
中提取args
,如下所示
ArgsProvider
即使看起来非常不直观和详细,这个设计对我来说也是完美无缺。但是,在撰写某些key
时,我最近发现了一个主要漏洞:无法执行trait ArgsProvider {
...
/*
* Method that takes in a [T: ClassTag] and a (key: String) argument
* (i) if key exists in namedArgs: Map[String, Any]
* - Returns Some(value: T) if value can be casted into T type
* - Throws Exception if value can't be casted into T type
* (ii) if key doesn't exist in namedArgs
* Returns None
*/
def getOptionalTypedArg[T: ClassTag](key: String): Option[T] = {
namedArgs.get(key).map { arg: Any =>
try {
arg.asInstanceOf[T]
} catch {
case _: Throwable => throw new Exception(key)
}
}
}
...
}
。 (或至少这是我所推断的)
更具体地说,当我尝试unit tests
提供的type-checking
进入错误类型时,不会抛出任何异常。例如:
type-cast
虽然可以预期上面一段代码arg
和// here (args: Seq[NamedArg]) overrides the (args: Seq[Arg]) member of ArgsProvider
case class DummyArgsProvider(args: Seq[NamedArg]) extends ArgsProvider
// instantiate a new DummyArgsProvider with a single NamedArg having a String payload (value)
val dummyArgsProvider: DummyArgsProvider = DummyArgsProvider(Seq(
NamedArg("key-string-arg", "value-string-arg")
))
// try to read the String-valued argument as Long
val optLong: Option[Long] = dummyArgsProvider.getOptionalTypedArg[Long]("key-string-arg")
;令我沮丧的是,它完全正常并返回以下输出(在throw
Exception
上)
optLong:Option [Long] = Some(value-string-arg)
我的问题是:
我正在使用
Scala
REPL
答案 0 :(得分:3)
正如@AlexeyRomanov所说,as/isInstanceOf[T]
没有使用ClassTag
。
您可以使用模式匹配,如果有ClassTag
,则使用trait ArgsProvider {
/* ... */
def getOptionalTypedArg[T: ClassTag](key: String): Option[T] = {
namedArgs.get(key).map {
case arg: T => arg
case _ => throw new Exception(key)
}
}
}
进行检查:
ClassTag
或者您可以直接使用import scala.reflect.classTag
def getOptionalTypedArg[T: ClassTag](key: String): Option[T] = {
namedArgs.get(key).map { arg =>
classTag[T].unapply(arg).getOrElse(throw new Exception(key))
}
}
的方法:
ContactPhoto contactPhoto = contact.primaryPhoto();
QString photo = contactPhoto.originalPhoto();
//photo = file:///accounts/1000/pimdata/_startup_data/contacts/2/img-tnqpx0.jpg
if (!photo.isEmpty()){
QFile file(photo);
if (file.open(QIODevice::ReadOnly)) {
qDebug() <<"file.readAll() IF" <<file.readAll() <<endl;
}else{
qDebug() <<"file.readAll() ELSE" <<endl;
}
vcardString += "PHOTO;JPEG;ENCODING=BASE64:" + (file.readAll() + "\n");
}
答案 1 :(得分:1)
您遇到类型擦除问题:Option[Long]
实际存储字符串&#34; value-string-arg&#34;并且不关心它被删除的类型。
但是,如果你执行optLong.get
,它会尝试将其强制转换为预期输出的Long。而且您将获得ClassCastException
只是一点意见:
替换
val namedArgs: Map[String, Any] = {...}
通过
val namedArgs: Map[String, Any] = args.collect{
case NameArg(k, v) => k -> v
}(collection.breakout)
另外,在你的getOptionalTypedArg中,不要抓住所有Throwable。这是不好的做法(你可以捕获OutOfMemoryError和其他致命错误,你不应该这样做)。在您的情况下,您希望捕获ClassCastException。在其他情况下,如果您不确切知道哪个Throwable,请尝试使用NonFatal