所以,我有一个看起来像这样的Scala类:
class TestClass {
var value: Option[Int] = None
}
Run Code Online (Sandbox Code Playgroud)
我正在解决一个问题,我有一个String值,我想在运行时使用反射将其强制转换为Option [Int].所以,在另一段代码中(对TestClass一无所知)我有一些这样的代码:
def setField[A <: Object](target: A, fieldName: String, value: String) {
val field = target.getClass.getDeclaredField(fieldName)
val coercedValue = ???; // How do I figure out that this needs to be Option[Int] ?
field.set(target, coercedValue)
}
Run Code Online (Sandbox Code Playgroud)
为此,我需要知道该字段是一个Option,并且Option的type参数是Int.
我可以选择在运行时(即使用反射)确定'value'的类型是Option [Int]?
我已经看到通过注释字段解决了类似的问题,例如@OptionType(Int.class).如果可能的话,我更喜欢不需要在反射目标上进行注释的解决方案.
基本上我正在寻找最像scala的方式来做以下事情:
def sum(value1: Option[Int], value2: Option[Int]): Option[Int] =
if(value1.isDefined && value2.isDefined) Some(value1.get + value2.get)
else if(value1.isDefined && value2.isEmpty) value1
else if(value1.isEmpty && value2.isDefined) value2
else None
Run Code Online (Sandbox Code Playgroud)
这给出了正确的输出:
sum(Some(5), Some(3)) // result = Some(8)
sum(Some(5), None) // result = Some(5)
sum(None, Some(3)) // result = Some(3)
sum(None, None) // result = None
Run Code Online (Sandbox Code Playgroud)
然而,总结两个以上的选项,我必须使用太多ifs或使用某种循环.
编辑-1:
在写这个问题时,我想出了一个答案:
def sum2(value1: Option[Int], value2: Option[Int]): Option[Int] =
value1.toList ::: value2.toList reduceLeftOption { _ + _ }
Run Code Online (Sandbox Code Playgroud)
这个看起来非常惯用于我没有经验的眼睛.这甚至可以使用两个以上的值.可以在不转换为列表的情况下执行相同的操作吗?
EDIT 2:
我最终得到了这个解决方案(感谢ziggystar):
def sum(values: …Run Code Online (Sandbox Code Playgroud) 我有一个Scala帮助器方法,当前尝试获取URL并返回带有该网页的HTML的Option [String].
如果有任何异常(格式错误的URL,读取超时等等)或者如果有任何问题,则返回None.问题是,抛出异常以便调用代码可以记录异常或者在这种情况下返回None是否更好?
使用带有简单选项的for循环可以:
scala> for (lst <- Some(List(1,2,3))) yield lst
res68: Option[List[Int]] = Some(List(1, 2, 3))
Run Code Online (Sandbox Code Playgroud)
但循环选项的内容不会:
scala> for (lst <- Some(List(1,2,3)); x <- lst) yield x
<console>:8: error: type mismatch;
found : List[Int]
required: Option[?]
for (lst <- Some(List(1,2,3)); x <- lst) yield x
^
Run Code Online (Sandbox Code Playgroud)
...除非Option明确转换为List:
scala> for (lst <- Some(List(1,2,3)).toList; x <- lst) yield x
res66: List[Int] = List(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)
为什么需要显式列表转换?这是惯用的解决方案吗?
如何在ruby中建模可选值?Scala有Option [],这是我在ruby中寻找的东西.
这个问题与这个问题相反.
val x = Some((1, 2))
val (y: Option[Int], z: Option[Int]) = ???
Run Code Online (Sandbox Code Playgroud)
纯Scala答案和Scalaz答案都很有帮助.
我想知道标准库是完全null免费的 - 如果不是 - 会感兴趣的是合理的用例存在哪些返回null比返回一些Option实例更可取.
大多数SQL实现(这个问题与SQL无关,它只是一个例子)提供函数COALESCE(x1,x2,...,xn),x1如果不是则返回NULL,x2否则只有在x2不是NULL等等的情况下才返回.如果所有xi值都是NULL结果则是NULL.
我希望COALESCE在Scala中获得类似SQL的内容,以便将Option值NULL替换为None.我会举几个例子:
> coalesce(None,Some(3),Some(4))
res0: Some(3)
> coalesce(Some(1),None,Some(3),Some(4))
res1: Some(1)
> coalesce(None,None)
res2: None
Run Code Online (Sandbox Code Playgroud)
所以我把它实现为:
def coalesce[T](values: Option[T]*): Option[T] =
(List[T]() /: values)((prev: List[T], cur: Option[T]) =>
prev:::cur.toList).headOption
Run Code Online (Sandbox Code Playgroud)
它工作正常,但我想知道是否已经存在类似于Scala的一部分实现的功能.
比方说,我有一堆"验证"函数,如果没有错误则返回None,否则返回Some(String)指定错误消息.像下面这样的东西......
def validate1:Option[String]
def validate2:Option[String]
def validate3:Option[String]
Run Code Online (Sandbox Code Playgroud)
我将按顺序调用它们,一旦返回Some(String),我就会停止并返回相同的内容.如果它返回None,我会转到下一个,直到序列结束.如果所有这些都返回None,则返回None.
我想把它们粘在一起"表达".就像是 ...
for( a <- validate1; b <- validate2; c <- validate3) yield None;
Run Code Online (Sandbox Code Playgroud)
但是,Option完全与我想要的相反.它在None处停止,并以Some(String)跟随.
我怎样才能实现这样的目标?
object Main extends App {
val p1 = Promise[Option[String]]()
val p2 = Promise[Option[String]]()
val f1 = p1.future
val f2 = p2.future
val res = (for{
file1Opt <- f1
file2Opt <- f2
file1 <- file1Opt
file2 <- file2Opt
} yield {
combineFiles(file1, file2)
}).fallbackTo(Future.successful("Files not found"))
Thread.sleep(2000)
println("XXXXXXXXXXXXXXXXXXX")
p1.success(Some("file one"))
p2.success(Some("file two"))
val finalData = res.map(s =>
s + " " + "add more data to the file"
)
finalData.map(println(_))
def combineFiles(f1: String, f2: String): String = {
f1 + " …Run Code Online (Sandbox Code Playgroud)