Pregunta

me pregunto porque scala.Option no tiene un método fold Como esto definido:

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

equivalente a

map(ifSome).getOrElse(ifNone)

¿No hay mejor que usar map + getOrElse?

¿Fue útil?

Solución

Tu puedes hacer:

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

o

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

(Ambas soluciones evaluarán els por valor, que podría no ser lo que quieres. Gracias a Rex kerr por señalarlo).

Editar:

Pero lo que realmente quieres es Scalaz's catamorfismo cata (básicamente un fold que no solo maneja el Some valor pero también mapea el None parte, que es lo que describiste)

opt.cata(fun, els)

definido como (donde value es el valor de la opción con proxenetismo)

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

que es equivalente a opt.map(some).getOrElse(none).

Aunque debo comentar que solo debes usar CATA cuando es la forma "más natural" de expresarla. Hay muchos casos en los que un simple mapgetOrElse Suficiente, especialmente cuando implica potencialmente encadenar muchos maps. (Aunque también podrías encadenar el funS con la composición de la función, por supuesto, depende de si desea centrarse en la composición de la función o la transformación del valor).

Otros consejos

Personalmente encuentro métodos como cata que toman dos cierres como argumentos a menudo lo exageran. ¿Realmente ganas en legibilidad? map + getOrElse? Piense en un recién llegado a su código: ¿Qué harán con

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

¿De verdad crees que esto es más claro que

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

De hecho, diría que ninguno es preferible sobre el buen viejo

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

Como siempre, hay un límite en el que la abstracción adicional no le brinda beneficios y se vuelve contraproducente.

Finalmente fue agregado En Scala 2.10, con la firma fold[B](ifEmpty: => B)(f: A => B): B.

Desafortunadamente, esto tiene una consecuencia negativa común: B se infiere para las llamadas basadas solo en el ifEmpty argumento, que en la práctica es a menudo más estrecho. Por ejemplo (una versión correcta ya está en la biblioteca estándar, esto es solo para la demostración)

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

Scala inferirá B ser - estar Nil.type en lugar de deseado List[A] y quejarse de f No regresar Nil.type. En cambio, necesitas uno de

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

Esto hace fold no del todo equivalente a la correspondiente match.

Como se menciona por debilski, puedes usar Scalaz's OptionW.cata o fold. Como comentó Jason, los parámetros nombrados hacen que esto se vea bien:

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

Ahora, si el valor que desea en el None el caso es mzero para algunos Monoid[M] Y tienes una función f: A => M Para el Some Caso, puede hacer esto:

opt foldMap f

Asi que,

opt map (_ + 1) getOrElse 0

convertirse en

opt foldMap (_ + 1)

Personalmente pienso Option debería tener un apply Método que sería el catamorfismo. De esa manera podrías hacer esto:

opt { _ + 1, 0 }

o

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

De hecho, sería bueno tener esto para todas las estructuras de datos algebraicos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top