# D Programming - Functions

Advertisements

This chapter describes the functions used in D programming.

## Function Definition in D

A basic function definition consists of a function header and a function body.

### Syntax

```return_type function_name( parameter list ) {
body of the function
}
```

Here are all the parts of a function −

• Return Type − A function may return a value. The return_type is the data type of the value the function returns. Some functions perform the desired operations without returning a value. In this case, the return_type is the keyword void.

• Function Name − This is the actual name of the function. The function name and the parameter list together constitute the function signature.

• Parameters − A parameter is like a placeholder. When a function is invoked, you pass a value to the parameter. This value is referred to as actual parameter or argument. The parameter list refers to the type, order, and number of the parameters of a function. Parameters are optional; that is, a function may contain no parameters.

• Function Body − The function body contains a collection of statements that define what the function does.

## Calling a Function

You can a call a function as follows −

```function_name(parameter_values)
```

## Function Types in D

D programming supports a wide range of functions and they are listed below.

• Pure Functions
• Nothrow Functions
• Ref Functions
• Auto Functions
• Variadic Functions
• Inout Functions
• Property Functions

The various functions are explained below.

## Pure Functions

Pure functions are functions which cannot access global or static, mutable state save through their arguments. This can enable optimizations based on the fact that a pure function is guaranteed to mutate nothing which is not passed to it, and in cases where the compiler can guarantee that a pure function cannot alter its arguments, it can enable full, functional purity, that is, the guarantee that the function will always return the same result for the same arguments).

```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));
}
```

When the above code is compiled and executed, it produces the following result −

```Value returned from pure function : 30
```

## Nothrow Functions

Nothrow functions do not throw any exceptions derived from class Exception. Nothrow functions are covariant with throwing ones.

Nothrow guarantees that a function does not emit any exception.

```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));
}
```

When the above code is compiled and executed, it produces the following result −

```adding
Added value is 30
```

## Ref Functions

Ref functions allow functions to return by reference. This is analogous to ref function parameters.

```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);
}
```

When the above code is compiled and executed, it produces the following result −

```a: 1, b: 12
```

## Auto Functions

Auto functions can return value of any type. There is no restriction on what type to be returned. A simple example for auto type function is given below.

```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));
}
```

When the above code is compiled and executed, it produces the following result −

```add(a,b) = 3.5
```

## Variadic Functions

Variadiac functions are those functions in which the number of parameters for a function is determined in runtime. In C, there is a limitation of having atleast one parameter. But in D programming, there is no such limitation. A simple example is shown below.

```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);
}
```

When the above code is compiled and executed, it produces the following result −

```int 2
long 3
double 4.5
```

## Inout Functions

The inout can be used both for parameter and return types of functions. It is like a template for mutable, const, and immutable. The mutability attribute is deduced from the parameter. Means, inout transfers the deduced mutability attribute to the return type. A simple example showing how mutability gets changed is shown below.

```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);
}
```

When the above code is compiled and executed, it produces the following result −

```char[] "test a"
const(char)[] "test b"
string "test c"
```

## Property Functions

Properties allow using member functions like member variables. It uses the @property keyword. The properties are linked with related function that return values based on requirement. A simple example for property is shown below.

```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);
}
```

When the above code is compiled and executed, it produces the following result −

```The area is 200
Value set!
Modified width is 30
```
Advertisements