Abbiamo visto tutti numeri interi, virgola mobile, stringa e il tipo decimale occasionale. Quali sono alcuni dei tipi più strani o unici o utili che hai incontrato, utili o no?
Abbiamo visto tutti numeri interi, virgola mobile, stringa e il tipo decimale occasionale. Quali sono alcuni dei tipi più strani o unici o utili che hai incontrato, utili o no?
Risposte:
Sarò basso:
Maybe a
a Haskell.
Con questo semplice costrutto, il linguaggio risolve il problema degli arresti anomali o NullPointerException
, elude ordinatamente il "One Million Mistake" di Tony Hoare :)
Francamente, una presenza opzionale controllata al momento della compilazione? È da sogno ...
Option
nome. Perché no Optional
! Forse perché non sono madrelingua, ma Option
non mi trasmette il significato "facoltativo".
Maybe
nome è carino: "Che cosa hai?" "Forse un Int". Tuttavia, il bit davvero pulito è che è sia un funzione che una monade che, in parole povere, significa che si ottiene gratuitamente la propagazione nulla. Non è mai necessario inserire controlli nulli all'interno delle funzioni o nel mezzo del codice; devi solo verificarlo alla fine del tuo codice, se non del tutto.
Maybe
monade per Ruby: lostechies.com/derickbailey/2010/10/10/the-maybe-monad-in-ruby
Sono perennemente affezionato void *
. Probabilmente è un sintomo di qualcosa di profondamente imperfetto in me.
void *
e Pascal / Delphi hanno Pointer
.
Lua ha un tavolo integrato che è davvero impressionante. Ha un hashtable incorporato e un vettore, e con l'uso di metatable può essere la base fondamentale per la programmazione orientata agli oggetti in un linguaggio procedurale.
Ogni indice di una tabella può ricevere una qualsiasi delle strutture linguistiche di base (numero, valore booleano, stringa, funzione-sì, funzioni sono tipi su lua - e tabelle).
Sono sorpreso che nessuno abbia ancora menzionato Monade o Tipi di dati algebrici.
Lisp ha due tipi interessanti: t
e nil
. La cosa interessante di loro è che tutto è un t
e niente è un nil
.
nil
un t
?
SNOBOL: modello (essenzialmente un albero parser LL (1), se lo ricordo correttamente).
Fortran ha blocchi comuni; è uno dei tipi di dati meno comuni nei linguaggi moderni o, piuttosto, un modo insolito per condividere i dati in modo efficiente.
Fortran 95 ha tipi di intervallo e aritmetica di intervallo incorporata.
L'elenco non sarebbe completo senza i tipi monadici trovati in Haskell. Per capirli hai bisogno di un po 'di sforzo.
Delphi ha set ( vedi anche ), che non credo siano implementati allo stesso modo in altre lingue.
Questo rende un gioco da ragazzi la memorizzazione di attributi multi-variabile nei database: D
Suppongo che sia davvero strano venire dalla programmazione su un'architettura classica, ma certamente uno dei tipi più difficili per me da cui mi sono girato la testa all'inizio era il registro quantico , che compare in QCL .
PL / SQL ti permette di dichiarare variabili di tipo my_table.some_column%type
... Trovo che sia dannatamente utile.
E C # ti consente di dichiarare gli oggetti come nullable o no, anche se non sono sicuro che conti come un tipo.
cursor%rowtype
è ancora più divertente: è un tipo di record formato dinamicamente che riflette quali colonne restituisce la query del cursore.
Avevo un debole nel mio cuore per i tipi di dati di Euphoria quando ero più giovane
È strutturato in questo modo:
Object
-> Atom
-> Sequence
Sequenza = una sequenza di oggetti
-- examples of atoms:
0
98.6
-1e6
-- examples of sequences:
{2, 3, 5, 7, 11, 13, 17, 19}
{1, 2, {3, 3, 3}, 4, {5, {6}}}
{{"jon", "smith"}, 52389, 97.25}
{} -- the 0-element sequence
Nota: "jon" è in realtà un modo breve di scrivere la sequenza di valori ASCII. Ad esempio "ABCDEFG"
è lo stesso di{65, 66, 67, 68, 69, 70, 71}
Felix ha tipi di somma anonimi. Il tipo è scritto come:
typedef il = int + long;
come sarebbe in teoria. I valori sono brutti:
case 0 of il (1)
case 1 of il (2L)
tranne forse per una somma unitaria come 3 = 1 + 1 + 1
case 0 of 3
case 1 of 3
che sfortunatamente usa il conteggio delle origini zero per la "compatibilità C". Somme anonime sono necessarie per tipi algebrici strutturalmente tipizzati, ad esempio:
(1 + T * li) as li
è un elenco (singolarmente collegato) di T. Tutte le altre lingue che conosco delle somme richieste tipicamente nominate, in cui sia il tipo stesso che i costruttori devono avere nomi.
La scorciatoia 3 usata sopra è carina, la seguente è nella libreria:
typedef void = 0;
typedef unit = 1;
typedef bool = 2;
e questa notazione:
T ^ 3
è un array di lunghezza statica 3 .. il 3 non è un numero intero ma una somma di 3 unità. Che peccato + non è associativo :)
q / kdb + ha tabelle integrate. Poiché è un linguaggio di programmazione e un database orientato alle colonne in uno, non è necessario LINQ o ORM.
Ad esempio, è possibile creare una tabella come questa (l'assegnazione viene ignorata :
anziché =
nella maggior parte delle lingue):
people:([]name:`Joe`Amy`Sarah; age:17 15 18; GPA:3.5 3.8 3.33)
Ora posso guardare il mio tavolo:
q)show people
name age GPA
--------------
Joe 17 3.5
Amy 15 3.8
Sarah 18 3.33
E posso interrogarlo:
q)select from people where GPA>3.4
name age GPA
------------
Joe 17 3.5
Amy 15 3.8
Ho scoperto che il sindacato in C ++ era "eccentrico" quando ne ho sentito parlare per la prima volta. Non ho ancora colpito uno scenario in cui sono la scelta ovvia da implementare.
Sto ancora cercando di capire cosa diventa una funzione multiparametrica in F # e in altri linguaggi funzionali. Fondamentalmente int f (Foo, Bar) diventa func f (Foo)
Questa è la funzione a due parametri che accetta un Foo e una barra e restituisce un int è in realtà una funzione a un parametro che accetta un Foo e restituisce una funzione a un parametro che prende una barra e restituisce un int. Ma in qualche modo puoi chiamarlo con due parametri se vuoi. Ho scritto un post al riguardo qui
f(Foo, Bar)
è uguale alla funzione f(Foo)
che restituisce un'altra funzione f'(Bar)
che restituisce il valore che f(Foo, Bar)
sarebbe restituito. Cioè, se si corregge l'argomento "Foo", ma non "Bar", si ha una funzione che non dipende da "Foo" ma dipende comunque dall'argomento "Bar". Questo è tipico per i linguaggi funzionali; si chiama "curry".
Sono oggetti estremamente potenti ma compatti.
Le lingue che li hanno integrati hanno una grande capacità di manipolare il testo (non sentiamo la parola analizzare che non sono così buone).
Una manciata di lingue nella famiglia funzionale ha una classe di tipi noti come Unity. La caratteristica distintiva dei tipi di Unity è che non contengono informazioni, sono tipi a zero bit. Un tipo di unità (in alcune varianti) è anche il suo unico valore o (nella maggior parte degli altri) ha un solo valore (che non è esso stesso un tipo).
Questi sono utili, tuttavia, perché sono tipi distinti. Dal momento che non è possibile convertire implicitamente da un tipo di unità a un altro, è possibile eseguire il controllo del tipo statico in modo molto efficiente ed espressivo.
L'unità è anche il modo in cui la maggior parte di tali linguaggi descrive Enum, consentendo a un nuovo tipo di appartenere a un insieme definito di altri tipi o di descrivere forse tipi, valori che possono essere sia un valore di un tipo tipico (diciamo, un numero intero) o hanno un valore che rappresenta nessun valore.
Alcune lingue che non impiegano la ricchezza di tipi di unità definiti dall'utente hanno ancora unità in loro, in un modo o nell'altro. Per esempio, Python ha almeno tre tipi di unità, NoneType
, NotImplementedType
, e EllipsisType
. È interessante notare che i primi due significano entrambi qualcosa come "Nessun valore", ma il terzo viene utilizzato in valori complessi (in particolare, espressioni di sezione) per rappresentare casi speciali interessanti.
Altri esempi interessanti di unità includono NULL
in sql e undefined
in javascript, ma non void
in C o C ++. void
non riesce. Anche se descrive un valore senza informazioni, ma nessun valore effettivo può essere di tipo void
.
Il symbol
tipo di Ruby è un po 'insolito. È essenzialmente una stringa che implementa il modello singleton. O qualcosa. Finora, ho scoperto che gli usi migliori per i simboli sono negli stati di tracciamento e nel passaggio dei nomi delle funzioni.
COBOL. Essenzialmente solo due tipi di dati, stringhe e numeri di base, ma devi specificare esattamente come sono disposti in memoria, ad es PIC S9(5)V99 COMP-3
.
S
= firmato, 9(5)
= 5 cifre, V
= punto decimale implicito, 99
= 2 cifre in più, COMP-3
= BCD + segno nybble.
Clipper aveva "Code Blocks", che erano simili ai metodi anonimi. Potrebbero essere passati in giro e valutati secondo necessità, di solito come una forma di callback. Li useresti spesso per cose come eseguire calcoli al volo quando presenti tabelle di dati.
VHDL ha tipi fisici. Un letterale di questo tipo include sia un valore che un'unità. Puoi anche definire subunità. Ad esempio, un tipo fisico predefinito è time
:
type time is range <machine dependant> to <machine dependant>
units
fs;
ps = 1000 fs;
ns = 1000 ps;
us = 1000 ns;
Ms = 1000 us;
sec = 1000 ms;
min = 60 sec;
hr = 60 min;
end units;
Insieme al sovraccarico dell'operatore, è possibile definire cose molto interessanti.
Clojure è interessante perché ha un meta-concetto di "astrazioni" che pervadono il linguaggio. Esempi:
In una certa misura, le astrazioni portano il " principio della responsabilità singola " all'estremo. Sta a te comporli per ottenere la funzionalità che desideri, ma puoi essere estremamente flessibile su come incollarli insieme.
Ad esempio, se si desidera un sistema OOP basato su classi con ereditarietà, è possibile crearne uno da queste astrazioni di base in modo relativamente rapido.
In pratica, le astrazioni stesse sono progettate in modo tale che siano possibili molteplici implementazioni, ad esempio attraverso interfacce specifiche come clojure.lang.ISeq per sequenze o clojure.lang.IFn per funzioni di ordine superiore.
C'è un video interessante su questo argomento: The Art of Abstraction
Googles Go ha un tipo di "canale" che è piuttosto unico.