Alternative a valori nulli e tipi di opzioni

1

In relazione a questa domanda voglio sapere se c'è un accordo conciso modo per eleminare valori nulli fuori dal codice in generale o se non c'è.

es. immagina una classe che rappresenta un utente con compleanno come attributo che può essere impostato ma non deve, il che significa che è null. In scala e in linguaggi simili si può usare il tipo di opzione per descrivere questo e capisco perché questo è meglio di avere semplicemente un valore nullo normale come lo si codificherebbe in java.

Tuttavia mi chiedo se questo sia il concetto giusto o se possiamo farlo meglio in questo caso e anche in generale.

Mi è venuto in mente che potremmo sostituire il compleanno degli utenti (e altri attributi facoltativi o eventualmente sconosciuti / non impostati) con un elenco di possibili attributi facoltativi. Quindi potremmo avere

ourUser.getOptionalAttributes()
// could return a list [Date Birthday, Float Height, Color Eyecolor]
// or just [Color Eyecolor]
// or even an empty list

Tuttavia, l'uso di una lista regolare significherebbe che potremmo memorizzare più compleanni, ad es. Quindi avevamo bisogno di un modo per dire al compilatore che l'elenco può contenere solo un tipo di compleanno.

Sono totalmente sulla strada sbagliata qui e sono tipi di opzioni il modo (filosofico) corretto di esprimere attributi opzionali? Inoltre, ci sono concetti aggiuntivi per la gestione della logica degli attributi opzionali diversi dai tipi nullable e dai tipi di opzioni?

    
posta valenterry 02.05.2014 - 11:15
fonte

4 risposte

1

Che cos'è un tipo ?

Un tipo è meta dati che possono essere utilizzati, in fase di compilazione o in fase di esecuzione, per descrivere la forma dei nostri dati.

trait A { val b: X; def c(y: Y): Z}

Quindi sappiamo nel nostro programma che quando vediamo un a: A , sappiamo che a ha la forma di A così possiamo tranquillamente chiamare a.b .

Quindi quale forma ha null ?

null non ha dati. null non ha una forma. String s = null è consentito in quanto null non ha forma, quindi può adattarsi a qualsiasi dove. MikeFHay sopra dice che una collezione vuota può essere pensata come null object . Questo è sbagliato, una raccolta vuota ha esattamente la stessa forma di qualsiasi altra raccolta.

Se un campo può essere nullo, non possiamo più contare su a.b per essere sicuri. La forma dei dati in questo campo non è veramente A , solo potenzialmente A . L'altra forma che può essere è null . Questa è la forma di questo campo è un unione di A e null .

La maggior parte delle lingue consente ai sindacati di essere implementati come tagged union . Il tipo Option di Scala è un'unione con tag di None | Some(a:A) . Come Ceylon saggio aggiunge un suffisso ? per i tipi che dicono che il tipo potrebbe essere null come in String? s = null .

    
risposta data 02.05.2014 - 19:52
fonte
2

are option types the (philosophical) correct way to express optional attributes?

La parola ripetuta suggerisce che sì, lo sono. Esprimono in modo semplice e chiaro ciò che stai cercando di esprimere.

C'è un'alternativa nulla che non hai menzionato e che spesso può essere migliore di un null o Opzione tradizionale. Pattern di oggetto nullo , in cui definisci un oggetto con comportamento neutro predefinito, in modo che le chiamate ad esso non facciano nulla in modo trasparente. Una raccolta vuota può essere considerata un oggetto nullo, ma il concetto può essere applicato anche in altri luoghi.

    
risposta data 02.05.2014 - 12:26
fonte
2

So we could have like

ourUser.getOptionalAttributes()
// could return a list [Date Birthday, Float Height, Color Eyecolor]
// or just [Color Eyecolor]
// or even an empty list

Am i totally on the wrong track here and are option types the (philosophical) correct way to express optional attributes?

L'unica volta che l'uso di una lista ha senso è quando un determinato attributo può verificarsi da 0 a n > 1 volte. Non so nemmeno cosa pensi di fare con il primo esempio: quell'elenco è eterogeneo. (Non sto dicendo che non è possibile - potresti usare le classi dei casi in modo che ogni elemento dell'elenco abbia una data, un float o un colore, ma seriamente, che cosa ti spinge?)

Un tipo Maybe / Option è fondamentalmente la cosa giusta per rappresentare Nothing o un singolo valore di tipo T . Se type T ha n valori distinti, Option <T> ha n + 1 valori distinti; ed essendo un tipo distinto da T , è un errore assegnare ciecamente un Option <T> a T nello stesso modo in cui è sbagliato ciecamente assegnare un numero a 64-bit a un 32 -bit numero.

Per segnalare errore in un calcolo, puoi in alternativa lanciare un'eccezione invece di restituire un Option . Ciò è utile quando è probabile che un errore venga gestito più in alto nello stack di chiamate. È anche utile quando si passano le funzioni ad altre funzioni. Ad esempio, potresti avere una funzione A che desidera una funzione B che restituisca un intero. Potrebbe essere il caso che B potrebbe teoricamente non riuscire a produrre un intero, ma hai assicurato che questo particolare uso di B produrrà un risultato. Avere Option nel tipo di ritorno di B lo renderebbe incompatibile con A .

Also, are there additional concepts for handling the logic of optional attributes other than nullable types and option-like types?

Esiste il concetto di dividere i valori del tuo tipo nelle classi dei casi appropriate. Come semplice esempio, supponiamo di lavorare con coordinate cartesiane e di dover lavorare con coordinate sia rettangolari che polari. Sebbene ci siano due rappresentazioni, è importante capire che entrambi rappresentano valori dello stesso tipo. Un modo ingenuo di implementare questo sarebbe:

public class Point2D {
   public static enum Type { RECT, POLAR }
   public Type type;
   public Option<Double> x; // Rectangular coords
   public Option<Double> y; // Rectangular coords
   public Option<Double> angle; // Polar coords
   public Option<Double> magnitude; // Polar coords
}

Ma questo approccio è sbagliato - non è che ogni campo (salvato per type ) sia facoltativo, è che ci sono due tipi di Point2D e tu hai unito i due. Se lo hai modellato correttamente utilizzando case classes , nessuno dei campi sarebbe facoltativo:

abstract class Point2D
case class Rect(x: double, y: double) extends Point2D
case class Polar(angle: double, magnitude: double) extends Point2D

Questo è più legato alla scelta del modello giusto piuttosto che ai valori "mancanti", ma lo accenno perché può portare all'uso errato di Option (o null , dio non voglia.)

Come altri hanno menzionato, c'è il concetto di Pattern a oggetti nulli , ma questo è legato alla semantica specifica del tipo. Un oggetto nullo non ha senso per alcuni tipi.

    
risposta data 02.05.2014 - 13:54
fonte
1

Credo che si tratti di quale tipo di domanda ti piacerebbe mettere in scena la fine. Diciamo che vuoi solo che tutte le informazioni correlate vengano mostrate ogni volta tu mostri qualcuno all'utente. Quindi una lista (o EnumMap , se vuoi fare delle garanzie di unicità) sarebbe carina dato che vuoi solo iterare su di essa e stampa la roba.

Tuttavia, se vuoi fare domande come "se questo utente ha uno spettacolo di compleanno un avviso 1 giorno prima agli amici "quindi anche se si inizia con la lista alla fine ti rimane un Option . Non penso che sia male, ma è così non ti libera dall'idea di valori opzionali.

-edit -

Un inconveniente è che devi adattare tutti i tuoi dati nello stesso tipo. Potrebbe essere facile o difficile a seconda delle tue esigenze.

    
risposta data 02.05.2014 - 11:29
fonte

Leggi altre domande sui tag