Qual è lo scopo dell'utilizzo di NIL per rappresentare nodi null?


17

Nel mio corso Algorithms and Data Structures , professori, diapositive e il libro ( Introduzione agli algoritmi, 3a edizione ) hanno usato la parola NILper indicare, ad esempio, un figlio di un nodo (in un albero) che non esiste.

Una volta, durante una lezione, invece di dire NIL, il mio compagno di classe ha detto null, e il professore lo ha corretto, e non capisco perché i professori sottolineano questa parola.

C'è un motivo per cui le persone usano la parola NILinvece di null, o none, o qualsiasi altra parola? Ha NILun significato particolare che gli altri non hanno? C'è qualche motivo storico?

Si noti che ho visto anche alcuni punti del Web in cui, ad esempio, è nullstata utilizzata la parola anziché NIL, ma di solito viene utilizzata quest'ultima.

Risposte:


25

Per quanto mi riguarda, null, nil, nonee nothingsono nomi comuni per lo stesso concetto: un valore che rappresenta la “mancanza di valore”, e che è presente in molti tipi diversi (chiamati tipi nullable ). Questo valore viene in genere utilizzato laddove un valore è normalmente presente, ma può essere omesso, ad esempio un parametro opzionale. Diversi linguaggi di programmazione lo implementano in modo diverso e alcuni linguaggi potrebbero non avere tale concetto. Nelle lingue con puntatori, è un puntatore nullo . In molti linguaggi orientati agli oggetti, null non è un oggetto: chiamare un metodo su di esso è un errore. Per fare alcuni esempi:

  • In Lisp, nilè comunemente usato per indicare l'assenza di un valore. A differenza della maggior parte delle altre lingue, nilha una struttura: è un simbolo il cui nome è "NIL". È anche l'elenco vuoto (perché un elenco dovrebbe essere una cella contro, ma a volte non esiste una cella contro perché l'elenco è vuoto). Sia che sia implementato da un puntatore nullo sotto il cofano o come un simbolo come qualsiasi altro, dipende dall'implementazione.
  • In Pascal, nilè un valore puntatore (valido in qualsiasi tipo di puntatore) che potrebbe non essere sottoposto a dereferenziazione.
  • In C e C ++, qualsiasi tipo di puntatore include un NULLvalore che è distinto da qualsiasi puntatore a un oggetto valido.
  • In Smalltalk, nilè un oggetto senza alcun metodo definito.
  • In Java e in C #, nullè un valore di qualsiasi tipo di oggetto. Qualsiasi tentativo di accedere a un campo o metodo per nullattivare un'eccezione.
  • In Perl, undefè distinto da qualsiasi altro valore scalare e utilizzato in tutto il linguaggio e la libreria per indicare l'assenza di un valore "reale".
  • In Python, Noneè distinto da qualsiasi altro valore e utilizzato in tutto il linguaggio e la libreria per indicare l'assenza di un valore "reale".
  • In ML (SML, OCaml), Noneè un valore di qualsiasi tipo nello schema dei tipi 'a option, che contiene Nonee Some xper qualsiasi xtipo 'a.
  • In Haskell, il concetto simile usa i nomi Nothinge Just xper i valori e Maybe aper il tipo.

Nelle presentazioni dell'algoritmo, il nome utilizzato tende a derivare dallo sfondo del presentatore o dal linguaggio utilizzato negli esempi di codice.

In semantica presentazioni, nomi diversi possono essere usati per fare riferimento, ad esempio, l' NULLidentificatore che denota una costante puntatore nella lingua, e il valore nella semantica. Non credo che ci sia uno schema di denominazione standard e alcune presentazioni lasciano una differenza di carattere o non entrano affatto in sintassi concreta.niol

È possibile che il tuo docente desideri utilizzare la parola nullper una costante puntatore nulla nel linguaggio di programmazione utilizzato nel corso (Java o C #?) E NILper indicare l'assenza di un nodo in alcune strutture di dati, che possono o meno essere implementate come costante puntatore null (ad esempio, come visto sopra, in Lisp, NILspesso non viene implementato come puntatore null). Questa distinzione sarebbe rilevante quando si discute delle tecniche di attuazione per le strutture di dati. Quando si discute delle strutture stesse dei dati, il concetto di costante puntatore null è irrilevante, conta solo il concetto di non uguale a qualsiasi altro valore.

Non esiste uno schema di denominazione standard. Un altro docente o un libro di testo potrebbe usare nomi diversi.


Altri due esempi. L'obiettivo C ha entrambi NULL(per la compatibilità C) e nil; chiamare metodi on nilè un no-op. JavaScript ha entrambi null(un valore che non rappresenta nulla) e undefined(il valore non è nemmeno impostato).
200_successo

1
"Nei linguaggi orientati agli oggetti, null non è un oggetto: chiamare un metodo su di esso è un errore." - Questo non è vero per tutte le lingue, incluse alcune delle lingue che hai elencato. In Ruby e Smalltalk, nilè un oggetto come un altro, è un'istanza di NilClass, non esiste un altro concetto di "nullità" e, in particolare, non esiste un puntatore nullo. In Scala, Nilè molto distinto da null, nullè un po 'come un puntatore null, tuttavia in realtà ha un tipo ( Null), Nilè un vecchio oggetto normale, l'istanza singleton della EmptyListclasse se vuoi, e c'è anche ...
Jörg W Mittag,

1
... Nothingqual è il tipo in basso e non ha istanza, e Unitqual è il tipo di subroutine che non restituiscono un valore e ha l'istanza singleton (). nullin qualche modo ribadisce la nozione di "puntatore nullo" o "riferimento null", non perché ciò sia in qualche modo inerente al termine ma semplicemente a causa dell'ubiquità di linguaggi come C, C ++, D, Java, C #, che lo usano in questo maniera. NILnon porta questa connotazione, anche se in realtà è usata in questo modo, ad esempio in Pascal, Modula-2 e Oberon. In Ruby, nilha molti metodi utili: nil.to_i # => 0, nil.to_s # => '', ...
Jörg W Mittag

1
... nil.to_a # => [], nil.to_h # => {}, nil.to_f # => 0.0, nil.inspect # => 'nil', e così via. Puoi vedere l'elenco completo qui .
Jörg W Mittag,

3

Credo che la ragione dell'uso sia di zero che di null sia che il primo è principalmente un sostantivo, e il secondo principalmente un aggettivo (ho controllato sul web e nel mio diario di carta: American Heritage 1992).

Per quanto riguarda il significato e la storia, NIL è una contrazione dal latino "nihil" che significa "niente".

Per quanto ne so, l'uso del nome nilper indicare un puntatore null è stato introdotto con il linguaggio di programmazione Lisp (1958).

Un puntatore nullo è un valore di puntatore che non dovrebbe puntare a nulla e quindi non dovrebbe essere negato. Nella maggior parte dei casi, i puntatori sono semplicemente indirizzi di memoria. Qualsiasi variabile (ovvero qualsiasi posizione) destinata a contenere un tale puntatore conterrà sempre una configurazione di bit e tale configurazione può essere letta come indirizzo di memoria. Quindi spesso accade che il valore nilsia l'indirizzo di un'area di memoria proibita al programma, causando così una qualche forma di errore (possibilmente interrompendo) se il programma tenta di dereferenziare nil, che può essere solo un errore.

Avere un valore standard predefinito univoco per svolgere questo ruolo è essenziale nei linguaggi che utilizzano esplicitamente i puntatori, poiché è importante essere in grado di verificare se un puntatore punta o meno a una posizione di memoria o meno. Tipicamente, in Lisp, un elenco è stato creato come una successione di coppie "contro" contenenti un puntatore "auto" a un elemento elenco e un puntatore "cdr" alla coppia successiva. Nell'ultima coppia dell'elenco, il secondo puntatore era nil.

Ciò corrisponde alla definizione ricorsiva di un elenco come elenco vuoto o elemento di elenco concatenato a un elenco. Quindi un elenco senza elementi era rappresentato da nil. Questo elenco vuoto sembra essere l'identità del monoid elenco.

Poiché gli elenchi possono essere utilizzati per rappresentare insiemi, anche l'insieme vuoto può essere rappresentato da nil.

Quindi nilstoricamente era un valore di puntatore speciale, ma veniva compreso come un valore di identità speciale per altri domini più astratti, come elenchi o insiemi.

Un puntatore uguale nilera un puntatore nullo, essendo null un aggettivo anziché un sostantivo (cioè un sostantivo).

L'uso coordinato di entrambe le parole, come aggettivo e sostantivo è abbastanza coerente con altre pratiche. Il qualificatore null viene spesso utilizzato per lo zero di una struttura algebrica, come l'identità di un monoide: l' elemento null . Gli elenchi formano un monoide , dove il valore zero è l'identità. Lo stesso vale per gli insiemi (sebbene formino un'algebra con molte più proprietà). Uno dice allo stesso modo che un numero intero è nullo quando è zero.

Ci sono molte varianti sull'uso di queste parole e altre, come nessuna, a seconda degli autori e delle idiosincrasie dei linguaggi di programmazione.

Le due principali connotazioni sono , come spiegato sopra

  • come "valore indefinito" standard, che rappresenta in realtà l'assenza di qualsiasi valore utilizzabile.

  • come valore di identità di alcuni domini

Ciò dimostra che non è del tutto esatto affermare che NIL è " un valore che rappresenta l '" assenza di un valore ", come fatto da Gilles nella risposta accettata . Dipende dalla lingua e dai suoi usi. Il linguaggio di programmazione LISP probabilmente ha introdotto NIL nella terminologia di programmazione 55 anni fa. In LISP, NILè l'elenco vuoto e si può equivalentemente notare ()quale sia la rappresentazione naturale dell'elenco vuoto.Non rappresenta l'assenza di un valore. A volte viene utilizzato come segnaposto per i valori mancanti, anche se ciò è spesso da evitare proprio perché l'elenco vuoto è un valore. Ciò che rappresenta un valore mancante in una struttura in qualsiasi oggetto arbitrario, scelto dal programmatore, che non può essere confuso con valori accettabili.

I due concetti sono piuttosto diversi, anche se abbiamo dimostrato sopra che possono essere correlati. Potrebbe essere interessante avere una modalità dettagliata di tassonomia dell'uso della terminologia enumerata dalla risposta di Gilles, per vedere se gli usi di ciascuna di queste parole sono più orientati verso una connotazione o l'altra.

I nomi non sono altro che ciò a cui sono assegnati in un determinato contesto, da parte di chi definisce il discorso. Alcuni usi sono più comuni, più naturali o più coerenti, ma si dovrebbe sempre verificare la presenza di definizioni e accertarsi del significato previsto in ciascun contesto. E non bisogna sempre aspettarsi che la terminologia sia stata scelta con gusto o coerenza.


0

NIL è un oggetto con un valore che indica al programmatore che l'oggetto non è valido. È particolarmente utile in C ++ in cui NULL è definito come 0. Se si rimuove il riferimento a NULL in C ++, si ottiene un comportamento indefinito. Se si rimanda a NIL (un puntatore a un oggetto vuoto che è stato definito), si ottiene un oggetto che si può dire è oltre la fine della struttura dei dati. È ottimo per prevenire guasti catastrofici ai programmi e rilevare errori.

Puoi usare NIL in casi come elenchi doppiamente collegati, avendo l'inizio e la fine dell'elenco per tenere traccia sia della testa che della coda, e assicurarti che -> next e -> puntatori prev non rimandino mai a NULL.


Per quanto posso vedere, questo è semplicemente errato. Non esiste un "NIL" in C ++ .
David Richerby,

1
Penso che tu abbia frainteso la mia risposta. Il link che hai fornito non ha alcuna correlazione con la mia risposta. Ho proposto che zero sia un oggetto definito dall'utente, definito in base alla classe, per indicare un oggetto vuoto (ma valido) di quella classe.
sospensione il

Il modo in cui scrivi "NIL è un oggetto" (la mia enfasi) piuttosto che dire "NIL può essere definito come un oggetto" fa sembrare che stai descrivendo una caratteristica del linguaggio, piuttosto che uno stile di programmazione. Tuttavia, se la tua risposta riguarda solo uno stile di programmazione, non è proprio sull'argomento, qui.
David Richerby,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.