2016-03-28 11 views
6

In Scala, quando voglio impostare qualcosa su None, ho un paio di possibilità: usare None o Option.empty[A].Quando dovrei usare Option.empty [A] e quando dovrei usare None in Scala?

Dovrei sceglierne uno e usarlo in modo coerente, o ci sono momenti in cui dovrei usarne uno rispetto all'altro?

Esempio:

scala> def f(str: Option[String]) = str 
f: (str: Option[String])Option[String] 

scala> f(None) 
res0: Option[String] = None 

scala> f(Option.empty) 
res1: Option[String] = None 

risposta

6

Mi attenersi a None quando possibile, che è quasi sempre, è più breve e ampiamente utilizzato. Option.empty consente di specificare il tipo di valore sottostante, quindi utilizzarlo quando è necessario aiutare a digitare l'inferenza. Se il tipo è già noto per il compilatore None avrebbe funzionato come previsto, tuttavia definendo nuova variabile

var a = None 

causerebbe infering a come None.type che è improbabile che ci si aspetta.

È possibile quindi utilizzare uno dei paio di modi per aiutare dedurre ciò che è necessario

@ var a = Option.empty[String] 
a: Option[String] = None 
@ var a: Option[String] = None 
a: Option[String] = None 
@ var a = None: Option[String] // this one is rather uncommon 
a: Option[String] = None 

Un altro posto quando compilatore avrebbe bisogno di aiuto:

List(1, 2, 3).foldLeft(Option.empty[String])((a, e) => a.map(s => s + e.toString)) 

(codice non ha alcun senso, ma solo per fare un esempio, Se si omette il tipo o lo si sostituisce con None, il tipo di accumulatore viene dedotto rispettivamente a Option[Nothing] e None.type.

E per me personalmente questo è il posto che vorrei andare con Option.empty, per gli altri casi mi attengo con None quando possibile.

1

seguito sono le esportazioni del foglio di lavoro che utilizzano Scala e Scalaz.

def f(str: Option[String]) = str    //> f: (str: Option[String])Option[String] 
f(None)          //> res1: Option[String] = None 
var x:Option[String]=None      //> x : Option[String] = None 
x=Some("test") 
x            //> res2: Option[String] = Some(test) 
x=None 
x  

Ora utilizzando Scalaz,

def fz(str: Option[String]) = str    //> fz: (str: Option[String])Option[String] 
fz(none)          //> res4: Option[String] = None 
var xz:Option[String]=none     //> xz : Option[String] = None 
xz=some("test") 
xz           //> res5: Option[String] = Some(test) 
xz=none 
xz   

Si noti che tutte le dichiarazioni valutano allo stesso modo indipendentemente si utilizza None o Option.Empty. Come ?

Come potete vedere è importante comunicare a Scala le vostre intenzioni tramite il tipo restituito nell'istruzione var x:Option[String]=None. Ciò consente una successiva assegnazione di un Some. Tuttavia un semplice var x=None avrà esito negativo nelle righe successive poiché ciò renderà la variabile x risolta in None.type e non in Option[T].

Penso che si dovrebbe seguire la convenzione. Per gli incarichi vorrei andare per l'opzione var x:Option[String]=None. Inoltre, ogni volta che si utilizza None, è opportuno utilizzare un tipo di reso (in questo caso Option [String]) in modo che l'assegnazione non venga risolta in None.type.
Solo nei casi in cui non ho alcun modo per fornire un tipo e ho bisogno di un po 'di assegnazione fatto andrò per Option.empty

+0

Non riesco a pensare a nessun senso in cui "entrambi risolvono l'opzione [niente]". E come mostrano altre risposte, non possono essere sempre usati in modo intercambiabile. –

+0

Sì, hai ragione, stavo parlando di Scalaz ma il significato non era chiaro. Grazie. Ho aggiornato la risposta. –

+2

Anche lì, si ottiene effettivamente "none [A]: Option [A]'.Questo è lo stesso tipo di 'Option.empty', non di 'Option [Nothing]'; questo è -perché_ può essere usato in modo intercambiabile. Si ottiene solo l'opzione [Nothing] 'se è usata senza l'argomento type in una posizione in cui Scala non può inferirlo, come con' Option.empty'. –

1

Dato che Option[A].empty restituisce semplicemente None:

/** An Option factory which returns `None` in a manner consistent with 
* the collections hierarchy. 
*/ 
def empty[A] : Option[A] = None 

direi:

  1. Come hai detto, sii coerente con il codebase. Rendere coerente significa che i programmatori che accedono al tuo codice hanno una cosa in meno di cui preoccuparsi. "Dovrei usare None o Option.empty Bene, vedo @cdmckay sta usando X tutta la base di chiamata, userò anche quello?"
  2. Leggibilità - pensare ciò che trasmette il punto che si desidera di più. Se dovessi leggere un particolare metodo, avrebbe più senso se restituisse uno spazio vuoto Option (ignoriamo per un momento il fatto che l'implementazione sottostante sta semplicemente restituendo None) o un None esplicito? IMO, penso a None come un valore inesistente, come la documentazione specifica:

    /** This case object represents non-existent values. 
    * 
    * @author Martin Odersky 
    * @version 1.0, 16/07/2003 
    */ 
    
+0

Downvoting, in quanto non risponde alla domanda (se a volte uno è preferito per ragioni diverse dalla coerenza). Inoltre, il punto su un'opzione vuota che ha più o meno senso di un esplicito Nessuno mi sembra criptico. – osa

2

Breve uso risposta None se si parla di un valore, ad esempio quando si passa il parametro a qualsiasi funzione, utilizzare Option.empty[T] quando si definisce qualcosa.

var something = Option.empty[String] significa something è None per ora, ma può diventare Some("hede") in futuro. D'altra parte var something = None non significa nulla.non è possibile riassegnarlo con il compilatore Some("hede") arrabbiato: found : Some[String] required: None.type Quindi, questo significa che None e Option.empty[T] non sono alternative. È possibile passare None a qualsiasi opzione [T] ma non è possibile passare alcuni [T] a None.type

0

Come tutti gli altri hanno sottolineato, è più una questione di gusto personale, in cui la maggior parte delle persone preferisce None o, in alcuni casi, è necessario inserire esplicitamente il tipo perché il compilatore non può dedurre.

Questa domanda possono essere estrapolati per altre classi di Scala, come ad esempio Sequences, Map, Set, List e così via. In tutti loro avete diversi modi per definire lo stato vuoto. Impiegando sequenza:

  • Seq()
  • Seq.empty
  • Seq.empty[Type]

Dal 3, preferisco la seconda, perché:

  • Il primo (Seq()) è soggetto ad errori. Sembra che se qualcuno volesse creare una sequenza e si è dimenticato di aggiungere elementi
  • Il secondo (Seq.empty) è esplicito circa il desiderio di avere una sequenza vuota
  • Mentre la terza (Seq.empty[Type]) è il più esplicito il secondo, è più prolisso, quindi non uso in genere
Problemi correlati