Programação D - Funções
Este capítulo descreve as funções usadas na programação D.
Definição de Função em D
Uma definição de função básica consiste em um cabeçalho e um corpo de função.
Sintaxe
return_type function_name( parameter list ) {
body of the function
}
Aqui estão todas as partes de uma função -
Return Type- Uma função pode retornar um valor. oreturn_typeé o tipo de dados do valor que a função retorna. Algumas funções realizam as operações desejadas sem retornar um valor. Neste caso, o return_type é a palavra-chavevoid.
Function Name- Este é o nome real da função. O nome da função e a lista de parâmetros juntos constituem a assinatura da função.
Parameters- Um parâmetro é como um espaço reservado. Quando uma função é chamada, você passa um valor para o parâmetro. Esse valor é conhecido como parâmetro ou argumento real. A lista de parâmetros se refere ao tipo, ordem e número dos parâmetros de uma função. Os parâmetros são opcionais; ou seja, uma função pode não conter parâmetros.
Function Body - O corpo da função contém uma coleção de instruções que definem o que a função faz.
Chamando uma função
Você pode chamar uma função da seguinte maneira -
function_name(parameter_values)
Tipos de função em D
A programação em D suporta uma ampla gama de funções e elas estão listadas abaixo.
- Funções puras
- Funções do Nothrow
- Funções Ref
- Funções Automáticas
- Funções Variadic
- Funções Inout
- Funções de propriedade
As várias funções são explicadas a seguir.
Funções puras
Funções puras são funções que não podem acessar o estado global ou estático, mutável, exceto por meio de seus argumentos. Isso pode permitir otimizações com base no fato de que uma função pura tem a garantia de não alterar nada que não seja passado a ela, e nos casos em que o compilador pode garantir que uma função pura não pode alterar seus argumentos, pode permitir pureza funcional completa, que ou seja, a garantia de que a função sempre retornará o mesmo resultado para os mesmos argumentos).
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 o código acima é compilado e executado, ele produz o seguinte resultado -
Value returned from pure function : 30
Funções do Nothrow
As funções do Nothrow não lançam nenhuma exceção derivada da classe Exception. As funções do Nothrow são covariantes com as de arremesso.
Nothrow garante que uma função não emita nenhuma exceção.
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 o código acima é compilado e executado, ele produz o seguinte resultado -
adding
Added value is 30
Funções Ref
As funções Ref permitem que as funções retornem por referência. Isso é análogo aos parâmetros da função 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 o código acima é compilado e executado, ele produz o seguinte resultado -
a: 1, b: 12
Funções Automáticas
As funções automáticas podem retornar valores de qualquer tipo. Não há restrição quanto ao tipo a ser retornado. Um exemplo simples para a função de tipo automático é fornecido abaixo.
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 o código acima é compilado e executado, ele produz o seguinte resultado -
add(a,b) = 3.5
Funções Variadic
Funções Variadiac são aquelas funções nas quais o número de parâmetros para uma função é determinado em tempo de execução. Em C, há uma limitação de ter pelo menos um parâmetro. Mas na programação D, não existe essa limitação. Um exemplo simples é mostrado abaixo.
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 o código acima é compilado e executado, ele produz o seguinte resultado -
int 2
long 3
double 4.5
Funções Inout
O inout pode ser usado para parâmetros e tipos de retorno de funções. É como um modelo para mutável, const e imutável. O atributo de mutabilidade é deduzido do parâmetro. Significa que inout transfere o atributo de mutabilidade deduzido para o tipo de retorno. Um exemplo simples mostrando como a mutabilidade é alterada é mostrado abaixo.
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 o código acima é compilado e executado, ele produz o seguinte resultado -
char[] "test a"
const(char)[] "test b"
string "test c"
Funções de propriedade
As propriedades permitem o uso de funções de membro como variáveis de membro. Ele usa a palavra-chave @property. As propriedades são vinculadas a funções relacionadas que retornam valores com base no requisito. Um exemplo simples de propriedade é mostrado abaixo.
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 o código acima é compilado e executado, ele produz o seguinte resultado -
The area is 200
Value set!
Modified width is 30