2014-10-17 9 views
5

Sono sicuro che c'è una buona ragione per questo, ma non lo vedo.Option.fold - perché il suo secondo argomento non è un operatore binario?

Fold su (diciamo) List ritorni

il risultato dell'applicazione dell'operatore piega op fra tutti gli elementi e z

Ha una evidente relazione con foldLeft e foldRight che fare la stessa cosa ma con ordine definito (e quindi non sono necessari operatori associativi)

Fold su Option rendimenti

Restituisce il risultato dell'applicazione di f a questo scala.Option 's valore se il scala.Option è non vuota. In caso contrario, valuta l'espressione ifEmpty.

ifEmpty è (nella posizione del) z per un elenco. f è (nella posizione del) op

Per None (che, usando il mio modello mentale di Option come un "contenitore" che può o non può contenere un valore, è un contenitore "vuoto"), le cose sono OK , Option.fold restituisce lo zero (valore di ifEmpty).

Per Some(x), però, non f dovrebbe prendere due params, z e x quindi è coerente con il fold su sequenze (compreso avere una relazione simile al foldLeft e foldRight).

C'è sicuramente un argomento di utilità contro questo: avere f basta prendere x come parametro in pratica probabilmente più conveniente. Nella maggior parte dei casi, se lo fosse, prendeva anche z che verrebbe ignorato. Ma anche la coerenza è importante ...

Quindi qualcuno può spiegarmi perché l'opzione fold su Option è ancora "corretta" fold?

+0

Ma "Some # fold" richiede 2 argomenti. https://github.com/scala/scala/blob/v2.11.3/src/library/scala/Option.scala#L1 Mi dispiace non capisco la domanda – Jatin

+0

Ha effettivamente due argomenti; ma gli argomenti sono solo in elenchi di argomenti separati. – Jesper

+0

Sto chiedendo perché il secondo argomento non è un operatore binario. Non perché fold se stesso prende due argomenti - come tu dici, lo fa! –

risposta

2

Perché dovrebbe essere?

Il motivo di piegatura "normalmente" richiede un operatore binario perché "normalmente" viene utilizzato su un elenco che può essere elaborato uno ad uno con operatori binari (e il valore di inizializzazione z).

Piegare su un'opzione è, di fatto, una funzione mappa con un caso predefinito. Se si guarda alla sua definizione, letteralmente è:

if (isEmpty) ifEmpty else f(this.get) 

Dal momento che si dispone di un solo argomento possibile, f deve essere un operatore unario. Si potrebbe argomentare di avere un'opzione fold che prende un operatore binario e ha usato il valore ifEmpty come seme nel caso in cui l'opzione sia definita, ma il valore seme sensato e il valore ragionevole per quando l'opzione è vuota potrebbero essere molto diversi.

Come qualcuno ha sottolineato, per le diverse strutture sono necessarie diverse origini (ad esempio per gli alberi), perché l'applicazione "sensibile" di una riduzione ha strutture diverse.

0

scala.Option.fold è un errore; scarsa progettazione dell'API.

Option { 
    // This is equivalent to: map f getOrElse ifEmpty. 
    def fold[B](ifEmpty: => B)(f: A => B): B = if (isEmpty) ifEmpty else f(this.get) 
} 

Il metodo Option.fold può essere a portata di mano, ma non c'è da fold (allo stesso modo per Either.fold).

TraversableOnce { 
    // List, et alia 
    def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op) 
} 

Il beneficio di un metodo standard è che il concetto e tipo di firma sono coerenti (non c'è bisogno di rivedere ancora una volta la documentazione).

Inoltre, Option.foldLeftè coerente e richiede un operatore binario.