5

オプションモナドはどのように機能するのですか?私はscalaapiを閲覧していますが、例があります(つまり、2番目のものです)。

理解のための方法のため、request.getParameterからNoneが返された場合、式全体がNoneになります。

しかし、私がこのコードを試してみると:

 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(""))

コンパイルエラーが発生します。これはどのように機能するはずですか?

4

3 に答える 3

13

これにより、コンパイラエラーが発生します

  name <- None

このようにして、 の型Noneが に設定されNone.type、変数nameは 型であると推測されますNothing。(つまり、実際に存在する場合はこの型になりますが、明らかに for 内包表記は実行時にそれを作成することさえできません。)したがって、メソッドname.trimは存在せず、コンパイルされません。

利用可能な場合request.getParameter("name")、その型は になりOption[String]name潜在的に型Stringを持ち、name.trimコンパイルされます。

のタイプを指定することで、これを回避できますNone

  name <- None: Option[String]
于 2010-11-26T19:30:58.840 に答える
5

Kevinの答えを拡張するために、演算子の代わりに演算子Some()を使用して値をラップすることを回避できます。=<-

val upper = for {
   name <- None: Option[String] //request.getParameter("name")
   trimmed = name.trim
   upper = trimmed.toUpperCase if trimmed nonEmpty
} yield upper

for-comprehensionは、Kevinのバージョンと非常によく似たものにコンパイルされますが、式のセマンティックコンテンツに何も追加しない混乱(余分な変数名など)を避けるためにmapfilter明示的に使用する方が明確であることがよくあります。

于 2010-11-26T22:28:48.783 に答える
3

Debilskiの答えを拡張するために、後続の値を明示的にラップする必要もありませんSome()。実際にマッピングしている値は元の値だけですname

より良いアプローチは、理解のためではなく、 mapandfilter操作を直接使用することです。

注:舞台裏では、Scalaコンパイラーはfor-comprehensionをmap / flatMap / filterの組み合わせに変換するため、このアプローチはfor-comprehensionよりも効率が悪くなることはなく、より効率的である可能性があります。

def clean(x:Option[String]) = x map { _.trim.toUpperCase } filterNot { _.isEmpty }

val param = None : Option[String] // request.getParameter("name")
println( clean(param).getOrElse("") )
于 2010-11-26T19:48:43.997 に答える