Programmazione D - Funzioni
Questo capitolo descrive le funzioni utilizzate nella programmazione D.
Definizione di funzione in D
Una definizione di funzione di base consiste in un'intestazione di funzione e un corpo di funzione.
Sintassi
return_type function_name( parameter list ) {
body of the function
}
Ecco tutte le parti di una funzione:
Return Type- Una funzione può restituire un valore. Ilreturn_typeè il tipo di dati del valore restituito dalla funzione. Alcune funzioni eseguono le operazioni desiderate senza restituire un valore. In questo caso, return_type è la parola chiavevoid.
Function Name- Questo è il nome effettivo della funzione. Il nome della funzione e l'elenco dei parametri insieme costituiscono la firma della funzione.
Parameters- Un parametro è come un segnaposto. Quando viene richiamata una funzione, si passa un valore al parametro. Questo valore viene indicato come parametro o argomento effettivo. L'elenco dei parametri si riferisce al tipo, all'ordine e al numero dei parametri di una funzione. I parametri sono opzionali; ovvero, una funzione non può contenere parametri.
Function Body - Il corpo della funzione contiene una raccolta di istruzioni che definiscono cosa fa la funzione.
Chiamare una funzione
Puoi chiamare una funzione come segue:
function_name(parameter_values)
Tipi di funzione in D
La programmazione D supporta un'ampia gamma di funzioni e sono elencate di seguito.
- Funzioni pure
- Funzioni Nothrow
- Funzioni di riferimento
- Funzioni automatiche
- Funzioni variadiche
- Funzioni di Inout
- Funzioni di proprietà
Di seguito vengono spiegate le varie funzioni.
Funzioni pure
Le funzioni pure sono funzioni che non possono accedere allo stato mutabile globale o statico, salvo tramite i loro argomenti. Questo può consentire ottimizzazioni basate sul fatto che una funzione pura è garantita per non mutare nulla che non le viene passato, e nei casi in cui il compilatore può garantire che una funzione pura non possa alterare i suoi argomenti, può abilitare la purezza completa, funzionale, che è la garanzia che la funzione restituirà sempre lo stesso risultato per gli stessi argomenti).
import std.stdio;
int x = 10;
immutable int y = 30;
const int* p;
pure int purefunc(int i,const char* q,immutable int* s) {
//writeln("Simple print"); //cannot call impure function 'writeln'
debug writeln("in foo()"); // ok, impure code allowed in debug statement
// x = i; // error, modifying global state
// i = x; // error, reading mutable global state
// i = *p; // error, reading const global state
i = y; // ok, reading immutable global state
auto myvar = new int; // Can use the new expression:
return i;
}
void main() {
writeln("Value returned from pure function : ",purefunc(x,null,null));
}
Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:
Value returned from pure function : 30
Funzioni Nothrow
Le funzioni Nothrow non generano eccezioni derivate dalla classe Exception. Le funzioni di Nothrow sono covarianti con quelle di lancio.
Nothrow garantisce che una funzione non generi alcuna eccezione.
import std.stdio;
int add(int a, int b) nothrow {
//writeln("adding"); This will fail because writeln may throw
int result;
try {
writeln("adding"); // compiles
result = a + b;
} catch (Exception error) { // catches all exceptions
}
return result;
}
void main() {
writeln("Added value is ", add(10,20));
}
Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:
adding
Added value is 30
Funzioni di riferimento
Le funzioni Ref consentono alle funzioni di restituire per riferimento. Questo è analogo ai parametri della funzione ref.
import std.stdio;
ref int greater(ref int first, ref int second) {
return (first > second) ? first : second;
}
void main() {
int a = 1;
int b = 2;
greater(a, b) += 10;
writefln("a: %s, b: %s", a, b);
}
Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:
a: 1, b: 12
Funzioni automatiche
Le funzioni automatiche possono restituire valori di qualsiasi tipo. Non ci sono restrizioni sul tipo da restituire. Di seguito viene fornito un semplice esempio per la funzione di tipo automatico.
import std.stdio;
auto add(int first, double second) {
double result = first + second;
return result;
}
void main() {
int a = 1;
double b = 2.5;
writeln("add(a,b) = ", add(a, b));
}
Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:
add(a,b) = 3.5
Funzioni variadiche
Le funzioni Variadiac sono quelle funzioni in cui il numero di parametri per una funzione è determinato in runtime. In C, c'è una limitazione di avere almeno un parametro. Ma nella programmazione D, non esiste tale limitazione. Di seguito viene mostrato un semplice esempio.
import std.stdio;
import core.vararg;
void printargs(int x, ...) {
for (int i = 0; i < _arguments.length; i++) {
write(_arguments[i]);
if (_arguments[i] == typeid(int)) {
int j = va_arg!(int)(_argptr);
writefln("\t%d", j);
} else if (_arguments[i] == typeid(long)) {
long j = va_arg!(long)(_argptr);
writefln("\t%d", j);
} else if (_arguments[i] == typeid(double)) {
double d = va_arg!(double)(_argptr);
writefln("\t%g", d);
}
}
}
void main() {
printargs(1, 2, 3L, 4.5);
}
Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:
int 2
long 3
double 4.5
Funzioni di Inout
L'inout può essere utilizzato sia per i tipi di parametri che per quelli restituiti. È come un modello per mutable, const e immutable. L'attributo mutabilità è dedotto dal parametro. Significa che inout trasferisce l'attributo mutabilità dedotto al tipo restituito. Di seguito è mostrato un semplice esempio che mostra come la mutabilità viene modificata.
import std.stdio;
inout(char)[] qoutedWord(inout(char)[] phrase) {
return '"' ~ phrase ~ '"';
}
void main() {
char[] a = "test a".dup;
a = qoutedWord(a);
writeln(typeof(qoutedWord(a)).stringof," ", a);
const(char)[] b = "test b";
b = qoutedWord(b);
writeln(typeof(qoutedWord(b)).stringof," ", b);
immutable(char)[] c = "test c";
c = qoutedWord(c);
writeln(typeof(qoutedWord(c)).stringof," ", c);
}
Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:
char[] "test a"
const(char)[] "test b"
string "test c"
Funzioni di proprietà
Le proprietà consentono di utilizzare le funzioni membro come le variabili membro. Utilizza la parola chiave @property. Le proprietà sono collegate alla funzione correlata che restituisce valori in base al requisito. Di seguito è mostrato un semplice esempio di proprietà.
import std.stdio;
struct Rectangle {
double width;
double height;
double area() const @property {
return width*height;
}
void area(double newArea) @property {
auto multiplier = newArea / area;
width *= multiplier;
writeln("Value set!");
}
}
void main() {
auto rectangle = Rectangle(20,10);
writeln("The area is ", rectangle.area);
rectangle.area(300);
writeln("Modified width is ", rectangle.width);
}
Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:
The area is 200
Value set!
Modified width is 30