Un po' di linguaggio Dart - 4

Nel post precedente abbiamo visto come Dart gestisce le collezioni, attraverso ListMap e Set. Con questo articolo, terminiamo i richiami sul linguaggio Dart, introducendo la definizione delle funzioni.

Come per altri linguaggi anche Dart prevede la possibilità di definire delle funzioni, ovvero parti di codice da riutilizzare, che in generale, possono essere considerate come dei blocchi che trasformano zero o più parametri di ingresso in zero o più risultati.

La particolarità delle definizione di funzioni in Dart risiede nel modo con cui è possibile definire i parametri.

Le "arrow function" e le funzioni anonime

Le arrow function permettono di scrivere in modo semplificato funzioni che sono composte da una singola espressione, usando la speciale notazione => e senza indicare return. E' possibile anche definire funzioni che non hanno un nome. Entrambe sono utili spesso come funzioni callback di metodi iterativi. 


void main() {
  print(somma(3, 5));
  print(sottrazione(5, 4));

  var numeri = [10, 20, 30, 40];
  numeri.forEach((elemento) => print(elemento));

  var parole = ['acqua', 'terra', 'fuoco', 'aria'];
  parole.forEach((String parola) {
    print('$parola è composta da ${parola.length} caratteri');
  });

}

// definizione arrow function
int somma(int x, int y) => x + y;

// definizione arrow function
int sottrazione(int x, int y) => x - y;

Passaggio di parametri per valore e per riferimento

Nel linguaggio Dart tutti i parametri dei tipi primitivi (int, bool, string, ...) sono passati per valore, mentre per gli oggetti o in generali per i tipi non primitivi, il passaggio avviene per riferimento.


void main() {

  int x = 10;
  print(10);

  incremento(x);
  print(10);  // stamperà ancora 10

  Valore cls = Valore();
  print(cls.x);
  quadrato(cls);
  print(cls.x);

}

// esempio di passaggio per valore
int incremento(int x) {
  x = x + 1;
}

// esempio di passaggio per riferimento
void quadrato(Valore obj) {
  obj.x = obj.x*obj.x;
}

class Valore {
  double x = 10.0;  
}


Parametri posizionali opzionali 

Normalmente i parametri di una funzione vanno valorizzati nell'ordine in cui sono indicati nella definizione della funzione stessa (ovvero sono posizionali). Utilizzando le parentesi quadre è possibile indicare che uno o più parametri sono opzionali.


void main() {
  print(potenza(2, 2));
  print(potenza(2, 3));
  print(potenza(3));

  print(somma(10));
  print(somma(10, 20));
  print(somma(10, 20, 30));

}

// il parametro y è opzionale
int potenza(int x, [int y = 2]) {
  int r = 1;
  for (int i = 0; i < y; i++) {
    r *= x;
  }
  return r;
}

// i parametri y e z sono opzionali
int somma(int x, [int y = 0, int z = 0]) {
  return x + y + z;
}


Per indicare uno dei parametri opzioni, occorre aver indicato anche tutti quelli precedenti.

Parametri nominali opzionali 

L'assegnazione dei parametri segue normalmente l'ordine posizionale. In Dart è possibile, nel richiamare una funzione, esplicitare il nome del parametro che si sta valorizzando. Per indicare che il parametro può essere identificato attraverso il nome, nella definizione, occorre usare le parentesi graffe {}.


void main() {
  var nome = "Rossi Mario";
  var provincia = "RM";

  info(nome, provincia: provincia);
}

// il secondo e il terzo parametro sono nominali ed opzionali
void info(String nome, {String luogo, String provincia}) {
  print("$nome abita in $luogo ($provincia)");
}


SPOILER: Questa tipo di notazione tornerà comoda quando utilizzeremo le classi di Flutter che, pur utilizzando molti parametri, permettono di passare solo quelli desiderati, identificando ogni parametro con il proprio nome.

Con questo post, concludiamo l'esame del linguaggio Dart, ma certo non lo abbandoneremo, perché lo ritroveremo nello sviluppo Flutter: nel prossimo articolo passeremo all'installazione dell'ambiente di sviluppo.

Come per gli articoli precedenti potete trovare gli script utilizzati negli esempi tra le mie repo GitHub: https://github.com/luigimicco/dart-base

Commenti

Posta un commento