题
如何工作选择单?我正在浏览 Scala API 还有一个例子(我的意思是第二个),
由于理解的工作方式,如果没有从请求返回。
但是,当我尝试此代码时:
val upper = for {
name <- None //request.getParameter("name")
trimmed <- Some(name.trim)
upper <- Some(trimmed.toUpperCase) if trimmed.length != 0
} yield upper
println(upper.getOrElse(""))
我会收到编译错误。这应该如何工作?
解决方案
因此,您会发现编译器错误
name <- None
这样, None
设定为 None.type
和变量 name
推断为类型 Nothing
. 。 (也就是说,如果实际存在,它将具有这种类型,但显然是在运行时甚至没有创建它。)因此,没有方法 name.trim
存在,它不会编译。
如果你有 request.getParameter("name")
可用,它的类型是 Option[String]
, name
可能有类型 String
和 name.trim
会编译。
您可以通过指定类型来解决此问题 None
:
name <- None: Option[String]
其他提示
为了扩展凯文的答案,您可以避免包装值 Some()
通过使用 =
操作员而不是 <-
操作员:
val upper = for {
name <- None: Option[String] //request.getParameter("name")
trimmed = name.trim
upper = trimmed.toUpperCase if trimmed nonEmpty
} yield upper
坦白的理解会编译到与凯文的版本非常相似的内容,但我经常发现使用更清楚地使用 map
和 filter
明确避免杂乱(例如额外的可变名称),这些名称对表达的语义内容没有任何添加。
要扩展Debilski的答案,您也无需明确将后续值包装在 Some()
, ,您实际映射的唯一值是原始的 name
.
更好的方法是使用 map
和 filter
直接进行操作,而不是出于理解:
注意:在幕后,Scala编译器将转换为MAP/FLATMAP/过滤器的组合,因此这种方法永远不会比透明度的效率更低,并且很可能会更有效
def clean(x:Option[String]) = x map { _.trim.toUpperCase } filterNot { _.isEmpty }
val param = None : Option[String] // request.getParameter("name")
println( clean(param).getOrElse("") )
不隶属于 StackOverflow