Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
D (programming language)
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
===Programming paradigms=== D supports five main [[programming paradigm]]s: * [[Concurrent programming language|Concurrent]] ([[actor model]]) * [[Object-oriented programming|Object-oriented]] * [[Imperative programming|Imperative]] * [[Functional programming|Functional]] * [[Metaprogramming]] ====Imperative==== Imperative programming in D is almost identical to that in C. Functions, data, statements, declarations and expressions work just as they do in C, and the C runtime library may be accessed directly. On the other hand, unlike C, D's [[foreach|<code>foreach</code>]] loop construct allows looping over a collection. D also allows [[nested function]]s, which are functions that are declared inside another function, and which may access the enclosing function's [[local variable]]s. <syntaxhighlight lang="D"> import std.stdio; void main() { int multiplier = 10; int scaled(int x) { return x * multiplier; } foreach (i; 0 .. 10) { writefln("Hello, world %d! scaled = %d", i, scaled(i)); } } </syntaxhighlight> ====Object-oriented==== Object-oriented programming in D is based on a single [[Inheritance (object-oriented programming)|inheritance]] hierarchy, with all classes derived from class Object. D does not support multiple inheritance; instead, it uses Java-style [[interface (Java)|interfaces]], which are comparable to C++'s pure abstract classes, and [[mixin]]s, which separate common functionality from the inheritance hierarchy. D also allows the defining of static and final (non-virtual) methods in interfaces. Interfaces and inheritance in D support [[Covariance and contravariance (computer science)|covariant types]] for return types of overridden methods. D supports type forwarding, as well as optional custom [[dynamic dispatch]]. Classes (and interfaces) in D can contain [[Class invariant|invariants]] which are automatically checked before and after entry to public methods, in accordance with the [[design by contract]] methodology. Many aspects of classes (and structs) can be [[Type introspection|introspected]] automatically at compile time (a form of [[reflective programming]] (reflection) using <code>type traits</code>) and at run time (RTTI / <code>TypeInfo</code>), to facilitate generic code or automatic code generation (usually using compile-time techniques). ====Functional==== D supports [[functional programming]] features such as [[anonymous function|function literals]], [[Closure (computer science)|closures]], recursively-immutable objects and the use of [[higher-order function]]s. There are two syntaxes for anonymous functions, including a multiple-statement form and a "shorthand" single-expression notation:<ref name="short">{{cite web |title=Expressions |url=http://dlang.org/expression.html#Lambda |publisher=Digital Mars |access-date=27 December 2012}}</ref> <syntaxhighlight lang="D"> int function(int) g; g = (x) { return x * x; }; // longhand g = (x) => x * x; // shorthand </syntaxhighlight> There are two built-in types for function literals, <code>function</code>, which is simply a pointer to a stack-allocated function, and <code>delegate</code>, which also includes a pointer to the relevant [[stack frame]], the surrounding ‘environment’, which contains the current local variables. Type inference may be used with an anonymous function, in which case the compiler creates a <code>delegate</code> unless it can prove that an environment pointer is not necessary. Likewise, to implement a closure, the compiler places enclosed local variables on the [[Heap (data structure)|heap]] only if necessary (for example, if a closure is returned by another function, and exits that function's scope). When using type inference, the compiler will also add attributes such as <code>pure</code> and <code>nothrow</code> to a function's type, if it can prove that they apply. Other functional features such as [[currying]] and common higher-order functions such as [[map (higher-order function)|map]], [[filter (higher-order function)|filter]], and [[fold (higher-order function)|reduce]] are available through the standard library modules <code>std.functional</code> and <code>std.algorithm</code>. <syntaxhighlight lang="D"> import std.stdio, std.algorithm, std.range; void main() { int[] a1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; int[] a2 = [6, 7, 8, 9]; // must be immutable to allow access from inside a pure function immutable pivot = 5; int mySum(int a, int b) pure nothrow /* pure function */ { if (b <= pivot) // ref to enclosing-scope return a + b; else return a; } // passing a delegate (closure) auto result = reduce!mySum(chain(a1, a2)); writeln("Result: ", result); // Result: 15 // passing a delegate literal result = reduce!((a, b) => (b <= pivot) ? a + b : a)(chain(a1, a2)); writeln("Result: ", result); // Result: 15 } </syntaxhighlight> Alternatively, the above function compositions can be expressed using Uniform function call syntax (UFCS) for more natural left-to-right reading: <syntaxhighlight lang="D"> auto result = a1.chain(a2).reduce!mySum(); writeln("Result: ", result); result = a1.chain(a2).reduce!((a, b) => (b <= pivot) ? a + b : a)(); writeln("Result: ", result); </syntaxhighlight> ====Parallelism==== Parallel programming concepts are implemented in the library, and do not require extra support from the compiler. However the D type system and compiler ensure that data sharing can be detected and managed transparently. <syntaxhighlight lang="D"> import std.stdio : writeln; import std.range : iota; import std.parallelism : parallel; void main() { foreach (i; iota(11).parallel) { // The body of the foreach loop is executed in parallel for each i writeln("processing ", i); } } </syntaxhighlight> <code>iota(11).parallel</code> is equivalent to <code>std.parallelism.parallel(iota(11))</code> by using UFCS. The same module also supports <code>taskPool</code> which can be used for dynamic creation of parallel tasks, as well as map-filter-reduce and fold style operations on ranges (and arrays), which is useful when combined with functional operations. <code>std.algorithm.map</code> returns a lazily evaluated range rather than an array. This way, the elements are computed by each worker task in parallel automatically. <syntaxhighlight lang="D"> import std.stdio : writeln; import std.algorithm : map; import std.range : iota; import std.parallelism : taskPool; /* On Intel i7-3930X and gdc 9.3.0: * 5140ms using std.algorithm.reduce * 888ms using std.parallelism.taskPool.reduce * * On AMD Threadripper 2950X, and gdc 9.3.0: * 2864ms using std.algorithm.reduce * 95ms using std.parallelism.taskPool.reduce */ void main() { auto nums = iota(1.0, 1_000_000_000.0); auto x = taskPool.reduce!"a + b"( 0.0, map!"1.0 / (a * a)"(nums) ); writeln("Sum: ", x); } </syntaxhighlight> ====Concurrency==== Concurrency is fully implemented in the library, and it does not require support from the compiler. Alternative implementations and methodologies of writing concurrent code are possible. The use of D typing system does help ensure memory safety. <syntaxhighlight lang="D"> import std.stdio, std.concurrency, std.variant; void foo() { bool cont = true; while (cont) { receive( // Delegates are used to match the message type. (int msg) => writeln("int received: ", msg), (Tid sender) { cont = false; sender.send(-1); }, (Variant v) => writeln("huh?") // Variant matches any type ); } } void main() { auto tid = spawn(&foo); // spawn a new thread running foo() foreach (i; 0 .. 10) tid.send(i); // send some integers tid.send(1.0f); // send a float tid.send("hello"); // send a string tid.send(thisTid); // send a struct (Tid) receive((int x) => writeln("Main thread received message: ", x)); } </syntaxhighlight> ====Metaprogramming==== [[Metaprogramming]] is supported through templates, compile-time function execution, [[tuple]]s, and string mixins. The following examples demonstrate some of D's compile-time features. Templates in D can be written in a more imperative style compared to the C++ functional style for templates. This is a regular function that calculates the [[factorial]] of a number: <syntaxhighlight lang="D"> ulong factorial(ulong n) { if (n < 2) return 1; else return n * factorial(n-1); } </syntaxhighlight> Here, the use of <code>static if</code>, D's compile-time conditional construct, is demonstrated to construct a template that performs the same calculation using code that is similar to that of the function above: <syntaxhighlight lang="D"> template Factorial(ulong n) { static if (n < 2) enum Factorial = 1; else enum Factorial = n * Factorial!(n-1); } </syntaxhighlight> In the following two examples, the template and function defined above are used to compute factorials. The types of constants need not be specified explicitly as the compiler [[type inference|infers their types]] from the right-hand sides of assignments: <syntaxhighlight lang="D"> enum fact_7 = Factorial!(7); </syntaxhighlight> This is an example of [[compile-time function execution]] (CTFE). Ordinary functions may be used in constant, compile-time expressions provided they meet certain criteria: <syntaxhighlight lang="D"> enum fact_9 = factorial(9); </syntaxhighlight> The <code>std.string.format</code> function performs [[printf|<code>printf</code>]]-like data formatting (also at compile-time, through CTFE), and the "msg" [[Directive (programming)|pragma]] displays the result at compile time: <syntaxhighlight lang="D"> import std.string : format; pragma(msg, format("7! = %s", fact_7)); pragma(msg, format("9! = %s", fact_9)); </syntaxhighlight> String mixins, combined with compile-time function execution, allow for the generation of D code using string operations at compile time. This can be used to parse [[domain-specific language]]s, which will be compiled as part of the program: <syntaxhighlight lang="D"> import FooToD; // hypothetical module which contains a function that parses Foo source code // and returns equivalent D code void main() { mixin(fooToD(import("example.foo"))); } </syntaxhighlight>
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)