Record e funzioni
Raggruppare i dati in record e chiamare le funzioni con argomenti espliciti.
Un record raggruppa campi con nomi e tipi. Quando lo passi a una funzione, la funzione riceve una copia indipendente, come accade con un numero.
Come si dichiara
# A position on the integer grid.
record Point
x: i64
y: i64
Ogni campo dichiara un nome e un tipo su una riga indentata. Può contenere anche un altro record: Rect contiene due valori di tipo punto:
# A rectangle, by two corners.
record Rect
corner: Point
extent: Point
Come si costruisce: ogni campo ha il suo nome
C’è un modo solo di fare un record, e nomina ogni campo:
function main()
a = Point(x: 0, y: 0)
b = Point(x: 3, y: 4)
print("distance squared: ", a.dist2(b: b))
print("midpoint x: ", a.midpoint(b: b).x)
Point(3, 4) non è una forma valida: mancano i nomi dei campi. Il compilatore segnala l’errore e suggerisce la correzione:
$ heroes check points.hero
error[missing_label]: `Point`'s fields are always named — this one is `x`
at points.hero:46:15
|
46 | a = Point(0, 0)
| ^
fix (certain): write `x: `
Con i nomi dei campi, Point(y: 4, x: 3) e Point(x: 3, y: 4) indicano lo stesso punto. L’ordine degli argomenti non cambia quale valore viene assegnato a ciascun campo.
Le funzioni, e dove i nomi diventano obbligatori
function dist2(a: Point, b: Point) -> i64
dx = a.x - b.x
dy = a.y - b.y
return dx * dx + dy * dy
La dichiarazione di una funzione specifica il tipo di ogni parametro e, dopo ->, il tipo del risultato. Nel corpo, dx = … associa un nome a un valore e il compilatore ne deduce il tipo. Per conoscere i tipi in ingresso e in uscita basta quindi leggere la dichiarazione.
Quando due parametri della stessa funzione hanno lo stesso tipo, la chiamata deve nominarli. La regola si applica a dist2, che riceve due Point:
$ heroes check points.hero
error[needs_label]: two of `dist2`'s parameters are `Point`, so every one of them is named at the call site — this one is `b`
at points.hero:48:41
|
48 | print("distance squared: ", a.dist2(b))
| ^
fix (certain): write `b: `
Il tipo da solo non distingue due argomenti dello stesso tipo. I nomi rendono esplicito il ruolo di ciascuno. Se i tipi sono diversi, il compilatore può distinguerli e le etichette sono facoltative.
Chiamate con il punto
x.f(y) equivale a f(x, y). La sintassi con il punto permette di scrivere una normale chiamata di funzione. Non definisce un metodo, cioè una funzione associata a un tipo; il compilatore stabilisce quale funzione chiamare prima dell’esecuzione.
# Reads as a sentence, and it is one function call: `translate(r, by)`.
function translate(r: Rect, by: Point) -> Rect
moved = Point(x: r.corner.x + by.x, y: r.corner.y + by.y)
return Rect(corner: moved, extent: r.extent)
unit.translate(p).area() e area(translate(unit, p)) eseguono le stesse chiamate. Puoi scegliere la forma più leggibile; quella con il punto permette di leggere le operazioni da sinistra a destra.
I test stanno accanto a quello che provano
test "the 3-4-5 triangle"
assert dist2(a: Point(x: 0, y: 0), b: Point(x: 3, y: 4)) == 25
test "a rectangle keeps its size when it moves"
unit = Rect(corner: Point(x: 0, y: 0), extent: Point(x: 2, y: 3))
assert unit.translate(Point(x: 10, y: 10)).area() == unit.area()
Un blocco test si dichiara fuori dalle funzioni, accanto al codice da verificare. La compilazione ordinaria lo ignora. Qui il secondo test verifica che spostare un rettangolo non ne cambi l’area.
$ heroes test examples/gallery/01-points.hero
ok "the 3-4-5 triangle"
ok "a rectangle keeps its size when it moves"
2 tests, all passed
I limiti delle funzioni
Heroes non prevede ereditarietà, interfacce, overloading, cioè più funzioni con lo stesso nome, né valori predefiniti per i parametri. Non puoi definire funzioni con un numero variabile di argomenti. Questi limiti riducono le regole necessarie per capire una chiamata.
Poi: Variant e match, dove un valore può avere più forme e dimenticarne una ferma la compilazione. Torna all’elenco dei capitoli. ← Prima: Errori
Esegui un programma tuo: bastano quattro comandi. Oppure prendi tutto il linguaggio in un file solo, e tutti i programmi già scritti.