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