Question

Je me demande pourquoi scala.Option n'a pas de fold méthode définie comme ceci:

fold(ifSome: A => B , ifNone: => B)

équivalent à

map(ifSome).getOrElse(ifNone)

est-il pas mieux que d'utiliser map + getOrElse?

Était-ce utile?

La solution

Vous pouvez faire:

opt foldLeft (els) ((x, y) => fun(x))

ou

(els /: opt) ((x,y) => fun(x))

(Les deux solutions évaluera els par la valeur, ce qui pourrait ne pas être ce que vous voulez. Merci à Rex Kerr pour le pointant.)

Modifier

Mais ce que vous voulez vraiment est catamorphisme cata (essentiellement un fold qui non seulement poignées la valeur Some mais aussi des cartes de la partie None, qui est ce que vous avez décrit)

opt.cata(fun, els)

défini comme (où value est la valeur d'option souteneur)

def cata[X](some: A => X, none: => X): X = value match {
  case None => none
  case Some(a) => some(a)
}

ce qui équivaut à opt.map(some).getOrElse(none).

Bien que je remarque que vous ne devez utiliser CATA quand il est la manière « plus naturelle » de l'exprimer. Il y a beaucoup de cas où un simple suffit map-getOrElse, surtout quand il implique potentiellement enchaînant beaucoup de maps. (Bien que vous pouvez également enchaîner les funs avec la composition de fonction, bien sûr -. Cela dépend si vous voulez vous concentrer sur la composition de la fonction ou la transformation de la valeur)

Autres conseils

Personnellement, je trouve des méthodes telles que cata qui prennent deux fermetures comme arguments exagérez souvent. Avez-vous vraiment gagner en lisibilité sur map + getOrElse? Pensez à un nouveau venu à votre code: Que vont-ils faire de

opt cata { x => x + 1, 0 }

Pensez-vous vraiment c'est plus clair que

opt map { x => x + 1 } getOrElse 0

En fait, je dirais que ni est préférable à la bonne vieille

opt match {
  case Some(x) => x + 1
  case None => 0
}

Comme toujours, il y a une limite où l'abstraction supplémentaire ne donne pas les avantages que vous et se retourne contre-productif.

Il a finalement été ajouté à Scala 2.10 , avec la fold[B](ifEmpty: => B)(f: A => B): B signature.

Malheureusement, cela a une conséquence négative commune: B est déduit pour les appels basés uniquement sur l'argument ifEmpty, qui est en pratique souvent plus étroite. Par exemple. (Une version correcte est déjà dans la bibliothèque standard, ceci est juste pour la démonstration)

 def toList[A](x: Option[A]) = x.fold(Nil)(_ :: Nil)

Scala déduira B être Nil.type au lieu de List[A] désiré et se plaignent de ne pas retourner f Nil.type. , Vous avez besoin au lieu un des

 x.fold[List[A]](Nil)(_ :: Nil)
 x.fold(Nil: List[A])(_ :: Nil)

Cela rend fold pas tout à fait équivalent à correspondant match.

Comme mentionné par Debilski, vous pouvez utiliser OptionW.cata de Scalaz ou fold. Jason a commenté, les paramètres nommés ce look agréable:

opt.fold { ifSome = _ + 1, ifNone = 0 }

Maintenant, si la valeur que vous voulez dans le cas de None est mzero pour certains Monoid[M] et vous avez une f: A => M fonction pour le cas Some, vous pouvez faire ceci:

opt foldMap f

opt map (_ + 1) getOrElse 0

devient

opt foldMap (_ + 1)

Personnellement, je pense que Option devrait avoir une méthode de apply qui serait le catamorphisme. De cette façon, vous pouvez simplement faire ceci:

opt { _ + 1, 0 }

ou

opt { some = _ + 1, none = 0 }

En fait, ce serait bien d'avoir pour toutes les structures de données algébriques.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top