Julia



Composite types          

I tipi compositi, o composite types nella dizione inglese sono gli equivalenti delle strutture in altri linguaggi, come ad esempio C o C#. E un tipo in pratica composto da uno o più campi che possono essere, grazie ad alcuni meccanismi, manipolati individualmente. In generale un tipo composto è formato da tipi primitivi del linguaggio o tramite altri tipi composti. In Julia essi sono largamente utilizzati. Gli oggetti, presenti in tanti altri linguaggi, sono esempi di tipi compositi ai quali sono spesso abbinati dei metodi. Julia prevede che tutti i valori sono oggetti ma il supporto che esso offre al multiple dispatch fa si che non vi siano metodi esclusivamente abbinati ad un oggetto. Dylan, Groovy, Seed7, sono alcuni linguaggi che, come Julia, supportano nativamente il multiple dispatch.
Per definire un nuovo tipo composto usiamo la keyword type, formalmente:

type Nometipo
campo-1
campo-2
....
campo-2
end


dove i campi eventualmente, come vedremo, sono opzionali anche se ovviamente di solito sono presenti. Esempio:

type NuovoTipo
  x
  y :: Int
  z :: Float64
end


In questo caso viene definito un tipo composito di nome NuovoTipo; esso presenta 3 campi a due dei quali è stato assegnato un tipo base di appartenenza mentre l'altro è a contenuto libero. Una volta creato il nostro nuovo tipo esso può essere istanziato semplicemente con le stesse modalità che usiamo quando richiamiamo una funzione, fornendo i corretti parametri:

  Esempio 7.1
1
2
3
4
5
6
7
type NewType
var
x2 :: Int
s1 :: String
end

nt01 = NewType(4.45, 3, "ciao")

Il numero di parametri passato deve necessariamente coincidere con i campi richiesti dal tipo, diversamente il compilatore segnala un errore che fa riferimento ad un metodo non trovato, questo fa capire la vicinanza tra funzioni e tipi.
Richiamare un campo di una nuova istanza di un certo tipo è molto semplice, si usa come separatore il classico . (punto) così diffuso nei linguaggi a oggetti:

Esempio 7.2
1
2
3
4
5
6
7
8
9
type NewType
var
x1 :: Int
s1 :: String
end

nt01 = NewType(null,3, "Ciao")
println(nt01.x1)
println(nt01.s1)

Da notare l'inizializzazione alla riga 7 che passa null al campo generico.
Anche l'assegnazione piò essere fatta nello stesso modo, ampliamo l'esempio 7.2:

  Esempio 7.3
1
2
3
4
5
6
7
8
9
10
11
type NewType
var
x1 :: Int
s1 :: String
end

nt01 = NewType(null,3, "Ciao")
println(nt01.x1)
println(nt01.s1)
nt01.var = 12
println(nt01.var + nt01.x1)

La riga 10 assegna un valore a var ma ovviamente potevamo riferirci anche un altro dei due campi anche se in quel caso avremmo avuto il limite, relativamente ai valori da attribuire, del tipo predefinito in fase di definizione (righe 3 e 4).
Julia prevede anche la possibilità di definire un tipo senza campi al suo interno; in questo caso il tipo sarà un singleton, cioè potrà esservi una sola istanza dello stesso.

type NewType
end


Quanto visto in questo breve paragrafo è solo introduttivo per quanto concerne di tipi composti. Più avanti amplieremo il discorso coinvolgendoli in ambiti più grandi.