SlideShare a Scribd company logo
1 of 30
Download to read offline
Overload di funzioni in Rust - Come ho
imparato a vivere felicemente senza
Nicola Musatti
nicola.musatti@gmail.com
@NMusatti
Rust Milano Meetup - 24 gennaio 2018
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Chi sono
• Un appassionato di C++ di vecchia data, disilluso dalla complessità sempre
maggiore del linguaggio
• Lavoro in Java e su attività non di programmazione
• Un principiante Rust di lungo corso
• Adoro anche Python!
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Cosa ci facciamo qui
• Cos’è l’overload di funzioni e cosa c’è di buono
• Cosa si può fare quando non è supportato
• Quali funzionalità di Rust possiamo usare per affrontare gli stessi problemi
• Alcune implicazioni di portata più ampia
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Un esempio semplice
• Un tipo semplice: Element
• Un tipo collezione di Element: Collection
• Vogliamo aggiungere singoli elementi a una collezione
• Vogliamo aggiungere ad una collezione tutti gli elementi di un’altra
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Come l’avremmo scritto in C
#define MAX_SIZE 100
struct Element {
};
struct Collection {
struct Element * elements[MAX_SIZE];
int size;
};
void add_element(struct Collection * self, struct Element * el) {
if (self->size < MAX_SIZE)
self->elements[self->size++] = el;
}
void add_collection(struct Collection * self, struct Collection * cl) {
int i;
for (i = 0; i < cl->size && self->size < MAX_SIZE; i++)
self->elements[self->size++] = cl->elements[i];
}
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Lo stesso in Rust
pub struct Element {
}
pub struct Collection {
pub elements: Vec<Element>
}
impl Collection {
pub fn add_element(& mut self, e: Element) {
self.elements.push(e);
}
pub fn add_collection(& mut self, c: Collection) {
self.elements.extend(c.elements);
}
}
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Qual è il problema
• Espressività ridotta: devo ripetere i nomi dei tipi solo per disambiguare
• I nomi sono più distanti dal dominio del problema
• Le funzioni non possono essere invocate in modo generico (problema specifico
C++)
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Una versione C++
#include <vector>
class Element {
};
class Collection {
public:
void add(Element const& e) {
elements.push_back(e);
}
void add(Collection const& c) {
elements.insert(elements.end(), c.elements.begin(), c.elements.end());
}
std::vector<Element> elements;
};
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Cos’è l’overload di funzioni
• La possibilità di definire due o più funzioni con lo stesso nome che prendono
parametri che differiscono per tipo e/o numero
• La possibilità di chiamare una «funzione» con tipi e/o numero di parametri diversi,
indipendentemente da come ciò è ottenuto
Chiamare è la cosa importante se definire non è troppo complicato
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Costrutti collegati
• Generici o template
• Argomenti di default
• «Duck typing»
• Ereditarietà (?)
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Un esempio con template C++
template <typename T> void add(Collection & c, T const & t) {
c.add(t);
}
int main() {
Element e;
Collection c;
add(c, e);
Collection c1;
c1.elements.insert(c1.elements.end(), 5, Element());
add(c, c1);
return c.elements.size() == 6 ? 0 : 1;
}
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Un esempio di «duck typing» in Python
class Element:
pass
class Collection:
def __init__(self):
self.elements = []
def add(self, arg):
if isinstance(arg, Collection):
self.elements.extend(arg.elements)
else:
self.elements.append(arg)
def test(self):
e = Element()
c = Collection()
c.add(e)
c1 = Collection()
c1.elements.append(Element())
c.add(c1)
self.assertTrue(len(c.elements) == 2)
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Un esempio in Python con argomenti di default
class Element:
pass
class Collection:
def __init__(self):
self.elements = []
def add(self, element=None, collection=None):
if collection is not None:
self.elements.extend(collection.elements)
else:
self.elements.append(element)
def test(self):
e = Element()
c = Collection()
c.add(e)
c1 = Collection()
c1.elements.append(Element())
c.add(collection=c1)
self.assertTrue(len(c.elements) == 2)
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Bé…
L’overload è meglio!
• E” più pulito
• Rispetta il principio Aperto/Chiuso
• Gli switch sui tipi sono malvisti nei linguaggi che non hanno gli enum di Rust
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
E Rust?
• Una forma limitata di overload può essere implementata coi trait:
• Il numero di parametri non può variare
• L’implementazione è un po” più complicata
• C’è una discrepanza concettuale: i trait forniscono un livello aggiuntivo di
astrazione, l’overload non dovrebbe
• Non supporta gli argomenti di default
• Non supporta il «duck typing»: Rust scoraggia o proibisce il completamento
casuale
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Esempio di overload in Rust
pub struct Element {
}
pub struct Collection {
pub elements: Vec<Element>
}
trait Addable<T> {
fn add(& mut self, t: T);
}
impl Addable<Element> for Collection {
fn add(& mut self, t: Element) {
self.elements.push(t);
}
}
impl Addable<Collection> for Collection {
fn add(& mut self, t: Collection) {
self.elements.extend(t.elements);
}
}
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Esempio di overload in Rust (cont.)
fn test() {
let e = Element{};
let mut c = Collection{ elements: Vec::new() };
let c1 = Collection{ elements: Vec::new() };
c.add(e);
c.add(c1);
}
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Anche l’overload ha i suoi problemi!
Supponiamo di voler implementare un tipo Point che possa essere costruito:
• Da coordinate cartesiane
• Da coordinate polari
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Un esempio (errato) in C++
#include <cmath>
class Point {
public:
Point(double x, double y) : x(x), y(y) {
}
Point(double r, double t) : x(r * std::cos(t)), y(r * std::sin(t)) {
}
private:
double x, y;
};
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Gli argomenti di default di Python sono di aiuto
class Point:
def __init__(self, x=None, y=None, r=None, t=None):
if x is not None and y is not None:
self.x = x
self.y = y
else:
self.x = r * math.cos(t)
self.y = r * math.sin(t)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
def test(self):
p1 = Point(x=2.0, y=0.0)
p2 = Point(r=2.0, t=0.0)
self.assertTrue(p1 == p2)
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Rust viene in soccorso
…o come per me dovrebbero essere implementate le funzioni sovraccaricate in Rust:
Un’unica funzione con un unico parametro enum che elenchi tutte le
combinazioni di argomenti da supportare
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
L’esempio del tipo Point in Rust
pub enum Coordinates {
Cartesian(f64, f64),
Polar(f64, f64)
}
#[derive(PartialEq)]
pub struct Point {
pub x: f64,
pub y: f64
}
impl Point {
pub fn new(c: Coordinates) -> Point {
use self::Coordinates::*;
match c {
Cartesian(x, y) => Point{x,y},
Polar(r, t) => Point{ x: r * t.cos(), y: r * t.sin() }
}
}
}
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Estendiamo l’esempio Point in Rust
pub enum Angle {
Degrees(f64),
Radians(f64)
}
pub enum Coordinates {
Cartesian(f64, f64),
Polar(f64, Angle)
}
#[derive(PartialEq)]
pub struct Point {
pub x: f64,
pub y: f64
}
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Estendiamo l’esempio Point in Rust (cont.)
impl Point {
pub fn new(c: Coordinates) -> Point {
use self::Coordinates::*;
use std::f64::consts::*;
match c {
Cartesian(x, y) => Point{x,y},
Polar(r, a) => {
let t = match a {
Angle::Degrees(d) => d * 2. * PI / 360.,
Angle::Radians(r) => r
};
Point{ x: r * t.cos(), y: r * t.sin() }
}
}
}
}
fn test() {
let c = Point::new(Coordinates::Cartesian(2.,0.));
let p = Point::new(Coordinates::Polar(2.,Angle::Radians(0.)));
assert!(c == p);
}
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
L’esempio originale in Rust
pub struct Element {
}
pub struct Collection {
pub elements: Vec<Element>
}
pub enum Args {
Elem(Element),
Coll(Collection)
}
impl Collection {
pub fn add(&mut self, args: Args) {
match args {
Args::Elem(e) => self.elements.push(e),
Args::Coll(c) => self.elements.extend(c.elements)
}
}
}
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Cosa non va
• Chiamare la funzione è un po” più prolisso dell’overload vero e proprio
• Viola il principio Aperto/Chiuso: aggiungere combinazioni di parametri richiede di
modificare codice esistente
• L’enum degli argomenti può risultare un po” artificiale
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Cosa c’è di buono
• Le alternative disponibili sono descritte in un unico posto
• L’intenzione è espressa esplicitamente attraverso la scelta dell’enumerazione
appropriata
• Rust impone che tutti i casi dichiarati siano gestiti
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
C’è di più
• Un aspetto fondamentale della tipizzazione statica è l’imposizione di vincoli sui
parametri
• E” meglio fare i controlli subito in modo che il type system inoltri i vincoli
automaticamente
• L’enum degli argomenti sposta il controllo dei parametri fuori dalla funzione
• Questo si potrebbe estendere ad altri controlli:
• Range di validità
• Vincoli combinati
• Purtroppo la mancanza di costruttori standard rende la sintassi non proprio ideale
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Un ultimo esempio
use num::Float;
pub struct Positive<T: Float> {
pub value: T
}
impl<T: Float> Positive<T> {
pub fn new(t: T) -> Positive<T> {
assert!(t >= T::zero());
Positive{ value : t }
}
}
pub fn sqrt<T: Float>(v: Positive<T>) -> T {
v.value.sqrt()
}
fn test() {
assert!(sqrt(Positive::new(4.0)) == 2.0);
}
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
Fine
Domande o pizza, questo è il dilemma
Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018

More Related Content

Similar to Overload di funzioni in Rust - Come ho imparato a vivere felicemente senza

Introduzione a R
Introduzione a RIntroduzione a R
Introduzione a R
MCalderisi
 
Lezione 16 (2 aprile 2012)
Lezione 16 (2 aprile 2012)Lezione 16 (2 aprile 2012)
Lezione 16 (2 aprile 2012)
STELITANO
 
Lezione design patterns 2011 (Peron)
Lezione design patterns 2011 (Peron)Lezione design patterns 2011 (Peron)
Lezione design patterns 2011 (Peron)
lukebonham
 

Similar to Overload di funzioni in Rust - Come ho imparato a vivere felicemente senza (20)

Aspettando Go.2 - Meetup golang milano - 27 settembre 2018
Aspettando Go.2 - Meetup golang milano - 27 settembre 2018Aspettando Go.2 - Meetup golang milano - 27 settembre 2018
Aspettando Go.2 - Meetup golang milano - 27 settembre 2018
 
Corso python 2020 - Lezione 1
Corso python 2020 - Lezione 1Corso python 2020 - Lezione 1
Corso python 2020 - Lezione 1
 
Introduzione a R
Introduzione a RIntroduzione a R
Introduzione a R
 
Rest sdk
Rest sdkRest sdk
Rest sdk
 
Lezione 16 (2 aprile 2012)
Lezione 16 (2 aprile 2012)Lezione 16 (2 aprile 2012)
Lezione 16 (2 aprile 2012)
 
Vb.Net
Vb.NetVb.Net
Vb.Net
 
Love Your Database (ESC 2k16)
Love Your Database (ESC 2k16)Love Your Database (ESC 2k16)
Love Your Database (ESC 2k16)
 
Javaday 2006: Java 5
Javaday 2006: Java 5Javaday 2006: Java 5
Javaday 2006: Java 5
 
TypeScript, ovvero JavaScript che "non si rompe"
TypeScript, ovvero JavaScript che "non si rompe"TypeScript, ovvero JavaScript che "non si rompe"
TypeScript, ovvero JavaScript che "non si rompe"
 
Mobile APPs con Objective-C (iOS 3.1+) - Day 01/02
Mobile APPs con Objective-C (iOS 3.1+) - Day 01/02Mobile APPs con Objective-C (iOS 3.1+) - Day 01/02
Mobile APPs con Objective-C (iOS 3.1+) - Day 01/02
 
R Vectors
R VectorsR Vectors
R Vectors
 
Introduzione a scala prima parte
Introduzione a scala   prima parteIntroduzione a scala   prima parte
Introduzione a scala prima parte
 
Python@Unina - Exercises
Python@Unina - ExercisesPython@Unina - Exercises
Python@Unina - Exercises
 
Java Symbolic Regression - Machine Learining
Java Symbolic Regression - Machine LeariningJava Symbolic Regression - Machine Learining
Java Symbolic Regression - Machine Learining
 
Qt Lezione0: uso del C++ per scrivere applicazioni Qt
Qt Lezione0: uso del C++ per scrivere applicazioni QtQt Lezione0: uso del C++ per scrivere applicazioni Qt
Qt Lezione0: uso del C++ per scrivere applicazioni Qt
 
A brief intro to TDD for a JUG-TAA event
A brief intro to TDD for a JUG-TAA eventA brief intro to TDD for a JUG-TAA event
A brief intro to TDD for a JUG-TAA event
 
Dal c a Java (3/3)
Dal c a Java (3/3)Dal c a Java (3/3)
Dal c a Java (3/3)
 
Lezione design patterns 2011 (Peron)
Lezione design patterns 2011 (Peron)Lezione design patterns 2011 (Peron)
Lezione design patterns 2011 (Peron)
 
Two months of Kotlin
Two months of KotlinTwo months of Kotlin
Two months of Kotlin
 
Vogliamo programmatori stupidi e pigri!
Vogliamo programmatori stupidi e pigri!Vogliamo programmatori stupidi e pigri!
Vogliamo programmatori stupidi e pigri!
 

Overload di funzioni in Rust - Come ho imparato a vivere felicemente senza

  • 1. Overload di funzioni in Rust - Come ho imparato a vivere felicemente senza Nicola Musatti nicola.musatti@gmail.com @NMusatti Rust Milano Meetup - 24 gennaio 2018 Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 2. Chi sono • Un appassionato di C++ di vecchia data, disilluso dalla complessità sempre maggiore del linguaggio • Lavoro in Java e su attività non di programmazione • Un principiante Rust di lungo corso • Adoro anche Python! Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 3. Cosa ci facciamo qui • Cos’è l’overload di funzioni e cosa c’è di buono • Cosa si può fare quando non è supportato • Quali funzionalità di Rust possiamo usare per affrontare gli stessi problemi • Alcune implicazioni di portata più ampia Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 4. Un esempio semplice • Un tipo semplice: Element • Un tipo collezione di Element: Collection • Vogliamo aggiungere singoli elementi a una collezione • Vogliamo aggiungere ad una collezione tutti gli elementi di un’altra Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 5. Come l’avremmo scritto in C #define MAX_SIZE 100 struct Element { }; struct Collection { struct Element * elements[MAX_SIZE]; int size; }; void add_element(struct Collection * self, struct Element * el) { if (self->size < MAX_SIZE) self->elements[self->size++] = el; } void add_collection(struct Collection * self, struct Collection * cl) { int i; for (i = 0; i < cl->size && self->size < MAX_SIZE; i++) self->elements[self->size++] = cl->elements[i]; } Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 6. Lo stesso in Rust pub struct Element { } pub struct Collection { pub elements: Vec<Element> } impl Collection { pub fn add_element(& mut self, e: Element) { self.elements.push(e); } pub fn add_collection(& mut self, c: Collection) { self.elements.extend(c.elements); } } Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 7. Qual è il problema • Espressività ridotta: devo ripetere i nomi dei tipi solo per disambiguare • I nomi sono più distanti dal dominio del problema • Le funzioni non possono essere invocate in modo generico (problema specifico C++) Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 8. Una versione C++ #include <vector> class Element { }; class Collection { public: void add(Element const& e) { elements.push_back(e); } void add(Collection const& c) { elements.insert(elements.end(), c.elements.begin(), c.elements.end()); } std::vector<Element> elements; }; Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 9. Cos’è l’overload di funzioni • La possibilità di definire due o più funzioni con lo stesso nome che prendono parametri che differiscono per tipo e/o numero • La possibilità di chiamare una «funzione» con tipi e/o numero di parametri diversi, indipendentemente da come ciò è ottenuto Chiamare è la cosa importante se definire non è troppo complicato Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 10. Costrutti collegati • Generici o template • Argomenti di default • «Duck typing» • Ereditarietà (?) Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 11. Un esempio con template C++ template <typename T> void add(Collection & c, T const & t) { c.add(t); } int main() { Element e; Collection c; add(c, e); Collection c1; c1.elements.insert(c1.elements.end(), 5, Element()); add(c, c1); return c.elements.size() == 6 ? 0 : 1; } Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 12. Un esempio di «duck typing» in Python class Element: pass class Collection: def __init__(self): self.elements = [] def add(self, arg): if isinstance(arg, Collection): self.elements.extend(arg.elements) else: self.elements.append(arg) def test(self): e = Element() c = Collection() c.add(e) c1 = Collection() c1.elements.append(Element()) c.add(c1) self.assertTrue(len(c.elements) == 2) Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 13. Un esempio in Python con argomenti di default class Element: pass class Collection: def __init__(self): self.elements = [] def add(self, element=None, collection=None): if collection is not None: self.elements.extend(collection.elements) else: self.elements.append(element) def test(self): e = Element() c = Collection() c.add(e) c1 = Collection() c1.elements.append(Element()) c.add(collection=c1) self.assertTrue(len(c.elements) == 2) Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 14. Bé… L’overload è meglio! • E” più pulito • Rispetta il principio Aperto/Chiuso • Gli switch sui tipi sono malvisti nei linguaggi che non hanno gli enum di Rust Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 15. E Rust? • Una forma limitata di overload può essere implementata coi trait: • Il numero di parametri non può variare • L’implementazione è un po” più complicata • C’è una discrepanza concettuale: i trait forniscono un livello aggiuntivo di astrazione, l’overload non dovrebbe • Non supporta gli argomenti di default • Non supporta il «duck typing»: Rust scoraggia o proibisce il completamento casuale Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 16. Esempio di overload in Rust pub struct Element { } pub struct Collection { pub elements: Vec<Element> } trait Addable<T> { fn add(& mut self, t: T); } impl Addable<Element> for Collection { fn add(& mut self, t: Element) { self.elements.push(t); } } impl Addable<Collection> for Collection { fn add(& mut self, t: Collection) { self.elements.extend(t.elements); } } Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 17. Esempio di overload in Rust (cont.) fn test() { let e = Element{}; let mut c = Collection{ elements: Vec::new() }; let c1 = Collection{ elements: Vec::new() }; c.add(e); c.add(c1); } Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 18. Anche l’overload ha i suoi problemi! Supponiamo di voler implementare un tipo Point che possa essere costruito: • Da coordinate cartesiane • Da coordinate polari Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 19. Un esempio (errato) in C++ #include <cmath> class Point { public: Point(double x, double y) : x(x), y(y) { } Point(double r, double t) : x(r * std::cos(t)), y(r * std::sin(t)) { } private: double x, y; }; Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 20. Gli argomenti di default di Python sono di aiuto class Point: def __init__(self, x=None, y=None, r=None, t=None): if x is not None and y is not None: self.x = x self.y = y else: self.x = r * math.cos(t) self.y = r * math.sin(t) def __eq__(self, other): return self.x == other.x and self.y == other.y def test(self): p1 = Point(x=2.0, y=0.0) p2 = Point(r=2.0, t=0.0) self.assertTrue(p1 == p2) Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 21. Rust viene in soccorso …o come per me dovrebbero essere implementate le funzioni sovraccaricate in Rust: Un’unica funzione con un unico parametro enum che elenchi tutte le combinazioni di argomenti da supportare Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 22. L’esempio del tipo Point in Rust pub enum Coordinates { Cartesian(f64, f64), Polar(f64, f64) } #[derive(PartialEq)] pub struct Point { pub x: f64, pub y: f64 } impl Point { pub fn new(c: Coordinates) -> Point { use self::Coordinates::*; match c { Cartesian(x, y) => Point{x,y}, Polar(r, t) => Point{ x: r * t.cos(), y: r * t.sin() } } } } Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 23. Estendiamo l’esempio Point in Rust pub enum Angle { Degrees(f64), Radians(f64) } pub enum Coordinates { Cartesian(f64, f64), Polar(f64, Angle) } #[derive(PartialEq)] pub struct Point { pub x: f64, pub y: f64 } Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 24. Estendiamo l’esempio Point in Rust (cont.) impl Point { pub fn new(c: Coordinates) -> Point { use self::Coordinates::*; use std::f64::consts::*; match c { Cartesian(x, y) => Point{x,y}, Polar(r, a) => { let t = match a { Angle::Degrees(d) => d * 2. * PI / 360., Angle::Radians(r) => r }; Point{ x: r * t.cos(), y: r * t.sin() } } } } } fn test() { let c = Point::new(Coordinates::Cartesian(2.,0.)); let p = Point::new(Coordinates::Polar(2.,Angle::Radians(0.))); assert!(c == p); } Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 25. L’esempio originale in Rust pub struct Element { } pub struct Collection { pub elements: Vec<Element> } pub enum Args { Elem(Element), Coll(Collection) } impl Collection { pub fn add(&mut self, args: Args) { match args { Args::Elem(e) => self.elements.push(e), Args::Coll(c) => self.elements.extend(c.elements) } } } Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 26. Cosa non va • Chiamare la funzione è un po” più prolisso dell’overload vero e proprio • Viola il principio Aperto/Chiuso: aggiungere combinazioni di parametri richiede di modificare codice esistente • L’enum degli argomenti può risultare un po” artificiale Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 27. Cosa c’è di buono • Le alternative disponibili sono descritte in un unico posto • L’intenzione è espressa esplicitamente attraverso la scelta dell’enumerazione appropriata • Rust impone che tutti i casi dichiarati siano gestiti Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 28. C’è di più • Un aspetto fondamentale della tipizzazione statica è l’imposizione di vincoli sui parametri • E” meglio fare i controlli subito in modo che il type system inoltri i vincoli automaticamente • L’enum degli argomenti sposta il controllo dei parametri fuori dalla funzione • Questo si potrebbe estendere ad altri controlli: • Range di validità • Vincoli combinati • Purtroppo la mancanza di costruttori standard rende la sintassi non proprio ideale Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 29. Un ultimo esempio use num::Float; pub struct Positive<T: Float> { pub value: T } impl<T: Float> Positive<T> { pub fn new(t: T) -> Positive<T> { assert!(t >= T::zero()); Positive{ value : t } } } pub fn sqrt<T: Float>(v: Positive<T>) -> T { v.value.sqrt() } fn test() { assert!(sqrt(Positive::new(4.0)) == 2.0); } Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018
  • 30. Fine Domande o pizza, questo è il dilemma Nicola Musatti - Function Overloading in Rust - Rust Milano Meetup - Mikamai - 24 January 2018