質問
オプションモナドの作業はどのように働いていますか?私は閲覧しています SCALA API そして、例があります(私は2番目のものを意味します)、
理解の仕組みのために、request.getParameterから返品されていない場合、式全体がなしになります
しかし、私がこのコードを試すとき:
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("") )