Functions
7.1 Basics
int add(int a, int b) { return a + b; }
void greet(string name = "World") { writeln("Hello, ", name); } // default argument
auto multiply(int a, int b) => a * b; // short syntax (2.098+)
auto inferred(int x) { return x * 2.5; } // return type inference7.2 Parameter Storage Classes
Pass by value (copy) Pass by reference (alias the caller's variable)
Reference, reset to .init on entry: output parameter const scope (read-only input; with -preview=in it may pass by ref)
Argument evaluated only when used (a delegate under the hood)
Reference won't escape the function (DIP1000) return ref / return scope
Returned reference tied to the parameter's lifetime (templates) ref for lvalues, value for rvalues
const / immutable / shared / inout
void increment(ref int x) { x++; }
void getPair(out int a, out int b) { a = 1; b = 2; }
void log(lazy string msg) { if (debugEnabled) writeln(msg); } // msg is only evaluated if needed
int v = 1;
increment(v);
int p, q;
getPair(p, q);
log("expensive " ~ computeString());7.3 Variadic Functions
int sum(int[] nums...) { int t; foreach (n; nums) t += n; return t; } // typesafe variadic
writeln(sum(1, 2, 3));
void printAll(T...)(T args) { foreach (a; args) write(a, " "); } // variadic template
printAll(1, "two", 3.0);
extern(C) int printf(const char*, ...); // C-style variadics7.4 Nested Functions and Function Literals
int outer(int x)
{
int helper(int y) { return x + y; } // nested: can access outer's locals
return helper(10);
}
auto f = function int(int a) { return a * 2; }; // function pointer (no context)
auto g = delegate int(int a) { return a * 2; }; // delegate (has context)
auto h = (int a) => a * 2; // lambda
alias Fn = int function(int);7.5 Overloading
Overload resolution: exact match > match with qualifier conversion > implicit conversion.
void show(int x) { writeln("int"); }
void show(string x) { writeln("string"); }
void show(double x) { writeln("double"); }7.6 Returning Multiple Values
import std.typecons : tuple, Tuple;
auto divmod(int a, int b) { return tuple(a / b, a % b); }
auto res = divmod(17, 5);
writeln(res[0], " ", res[1]);
auto named = Tuple!(int, "q", int, "r")(3, 2);
writeln(named.q);7.7 Properties
Any function with zero (or one, for setters) arguments can be called without parentheses. @property is mostly conventional.
struct Temperature
{
private double celsius;
@property double fahrenheit() const { return celsius * 9 / 5 + 32; }
@property void fahrenheit(double f) { celsius = (f - 32) * 5 / 9; }
}
Temperature t;
t.fahrenheit = 212;
writeln(t.fahrenheit);7.8 Recursion
ulong factorial(ulong n) { return n <= 1 ? 1 : n * factorial(n - 1); }