learnxinyminutes-docs/d.html.markdown

243 lines
5.4 KiB
Markdown
Raw Normal View History

2015-06-08 05:30:16 +03:00
---
2015-06-08 05:39:01 +03:00
language: D
2015-06-08 05:30:16 +03:00
filename: learnd.d
contributors:
- ["Nick Papanastasiou", "www.nickpapanastasiou.github.io"]
lang: en
---
2015-06-10 19:21:11 +03:00
If you're like me and spend way too much time on the internet, odds are you've heard
2015-06-08 05:30:16 +03:00
about [D](http://dlang.org/). The D programming language is a modern, general-purpose,
multi-paradigm language with fantastic support for OOP, functional programming, metaprogramming,
and easy concurrency and parallelism, and runs the gamut from low-level features such as
memory management, inline assembly, and pointer arithmetic, to high-level constructs
such as higher-order functions and generic structures and functions via templates, all with
a pleasant syntax, and blazing fast performance!
D is actively developed by Walter Bright and Andrei Alexandrescu, two super smart, really cool
dudes. With all that out of the way, let's look at some examples!
2015-06-08 05:39:01 +03:00
```d
2015-06-08 05:30:16 +03:00
// You know what's coming...
2015-06-10 18:54:16 +03:00
module hello;
2015-06-08 05:30:16 +03:00
import std.stdio;
// args is optional
void main(string[] args) {
writeln("Hello, World!");
}
// Conditionals and loops work as expected.
import std.stdio;
void main() {
for(int i = 0; i < 5; i++) {
writeln(i);
}
auto n = 1; // use auto for type inferred variables
while(n < 10_000) {
n += n;
}
do {
n -= (n / 2);
} while(n > 0);
// For and while are nice, but in D-land we prefer foreach
foreach(i; 1..int.max) { // The .. creates a continuous range
if(n % 2 == 0)
writeln(i);
}
2015-06-08 05:50:05 +03:00
foreach_reverse(i; 1..short.max) {
2015-06-10 19:18:45 +03:00
if(n % 2 == 1) {
2015-06-08 05:30:16 +03:00
writeln(i);
2015-06-10 19:18:45 +03:00
} else {
2015-06-08 05:30:16 +03:00
writeln("No!");
2015-06-10 19:18:45 +03:00
}
2015-06-08 05:30:16 +03:00
}
}
2015-06-08 05:50:05 +03:00
```
We can define new types and functions with `struct`, `class`, `union`, and `enum`. Structs and unions
are passed to functions by value (i.e. copied) and classes are passed by reference. Futhermore,
we can use templates to parameterize all of these on both types and values!
2015-06-08 05:52:34 +03:00
```d
2015-06-08 05:50:05 +03:00
// Here, T is a type parameter. Think <T> from C++/C#/Java
2015-06-10 18:54:16 +03:00
struct LinkedList(T) {
2015-06-08 05:50:05 +03:00
T data = null;
LinkedList!(T)* next; // The ! is used to instaniate a parameterized type. Again, think <T>
}
class BinTree(T) {
T data = null;
BinTree!T left;
BinTree!T right;
}
enum Day {
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
}
// Use alias to create abbreviations for types
alias IntList = LinkedList!int;
alias NumTree = BinTree!double;
2015-06-08 05:30:16 +03:00
2015-06-10 18:54:16 +03:00
// We can create function templates as well!
T max(T)(T a, T b) {
if(a < b)
return b;
return a;
}
// Use the ref keyword to pass by referece
void swap(T)(ref T a, ref T b) {
auto temp = a;
a = b;
2015-06-10 19:42:10 +03:00
b = temp;
2015-06-10 18:54:16 +03:00
}
// With templates, we can also parameterize on values, not just types
2015-06-10 19:21:11 +03:00
class Matrix(uint m, uint n, T = int) {
2015-06-10 18:54:16 +03:00
T[m] rows;
T[n] columns;
}
2015-06-10 19:21:11 +03:00
2015-06-10 19:42:10 +03:00
auto mat = new Matrix!(3, 3); // We've defaulted T to int
2015-06-10 19:21:11 +03:00
2015-06-08 05:39:01 +03:00
```
2015-06-10 18:54:16 +03:00
Speaking of classes, let's talk about properties for a second. A property
is roughly a function that may act like an lvalue, so we can
have the syntax of POD structures (`structure.x = 7`) with the semantics of
getter and setter methods (`object.setX(7)`)!
2015-06-10 19:18:45 +03:00
```d
// Consider a class parameterized on a types T, U
class MyClass(T, U) {
T _data;
U _other;
}
// We define "setter" methods as follows
class MyClass(T, U) {
T _data;
U _other;
@property void data(T t) {
_data = t;
}
@property void other(U u) {
_other = u;
}
}
// And "getter" methods like so
class MyClass(T, U) {
T _data;
U _other;
// Constructors are always named `this`
this(T t, U u) {
data = t;
other = u;
}
// getters
@property T data() {
return _data;
}
@property U other() {
return _other;
}
// setters
@property void data(T t) {
_data = t;
}
@property void other(U u) {
_other = u;
}
}
// And we use them in this manner
void main() {
auto mc = MyClass!(int, string);
mc.data = 7;
mc.other = "seven";
writeln(mc.data);
writeln(mc.other);
}
```
With properties, we can add any amount of validation to
our getter and setter methods, and keep the clean syntax of
accessing members directly!
2015-06-10 19:42:10 +03:00
Other object-oriented goodness for all your enterprise needs
include `interface`s, `abstract class`es,
and `override`ing methods.
We've seen D's OOP facilities, but let's switch gears. D offers
functional programming with first-class functions, `pure`
functions, and immutable data. In addition, all of your favorite
functional algorithms (map, filter, reduce and friends) can be
found in the wonderful `std.algorithm` module!
```d
import std.algorithm;
void main() {
// We want to print the sum of a list of squares of even ints
// from 1 to 100. Easy!
// Just pass lambda expressions as template parameters!
auto num = iota(1, 101).filter!(x => x % 2 == 0)
.map!(y => y ^^ 2)
.reduce!((a, b) => a + b);
writeln(num);
}
```
Notice how we got to build a nice Haskellian pipeline to compute num?
That's thanks to a D innovation know as Uniform Function Call Syntax.
With UFCS, we can choose whether to write a function call as a method
or free function all. In general, if we have a function
```d
f(A, B, C, ...)
```
Then we may write
```d
A.f(B, C, ...)
```
and the two are equivalent! No more fiddling to remember if it's
str.length or length(str)!