the d programming language cs 4450. what is d? a system programming language conceived in 1996 as a...
TRANSCRIPT
The D Programming The D Programming LanguageLanguageCS 4450
What is D?What is D?A system programming language
conceived in 1996 as a C++ replacement
Combines the power of C++ with the usability of languages like Java, C# and Python
If something works in C++, C# or Java, it probably works pretty much the same in D
“Often, programming teams will resort to a hybrid approach, where they will mix Python and C++, trying to get the productivity of Python and the performance of C++. The frequency of this approach indicates that there is a large unmet need in the programming language department.”
“D intends to fill that need. It combines the ability to do low-level manipulation of the machine with the latest technologies in building reliable, maintainable, portable, high-level code. D has moved well ahead of any other language in its abilities to support and integrate multiple paradigms like imperative, OOP, and generic programming.”
— Walter Bright, Co-designer of D
D is like C++D is like C++It supports static local variablesIt supports pointers
◦but you almost never need them (we won’t)It has templates
◦but they’re easier and more flexible than in C++
◦ it supports compile-time executionIt’s fast
◦compiles to native codeIt supports operator overloading
D is Like Java and C#D is Like Java and C#It supports garbage collection
◦the default, but you can opt-outIt supports explicit, user-defined
interfaces◦uses “:” for inheritance, like C#
It has inner classes, like Java and C#It has delegates
◦but more powerful than in C#It distinguishes reference and value
typesIt supports properties
D is Like Python and FP D is Like Python and FP LanguagesLanguagesIt has modules and packages
◦like Python’sIt supports nested functions and
closures◦including anonymous functions
It has a pure FP subset◦and the usual higher-order functions
reduce, map, filter, compose
◦supports lazy evaluation of function parameters
D is for Real ProgrammersD is for Real ProgrammersIt has software engineering support:
◦unit testing◦contract programming
invariants, preconditions, postconditions◦built-in constructs for exception-safe
transactions Supports concurrent programming
◦with thread-local storage◦both lock and lockless programming
Can interoperate with C and C++
D'iving InD'iving In
// hello.dimport std.stdio;
void main(string[] args) { if (args.length > 1) foreach (a; args[1..$]) writeln("Hello " ~ a); else writeln("Hello, Modern World");}
Chuck-Allisons-iMac-4:CCSC chuck$ dmd hello.dChuck-Allisons-iMac-4:CCSC chuck$ ./helloHello, Modern WorldChuck-Allisons-iMac-4:CCSC chuck$ ./hello John JaneHello JohnHello Jane
Primitive Data TypesPrimitive Data TypesType Meaning Default (.init)void no value n/abool Boolean value falsebyte signed 8 bits 0ubyte unsigned 8 bits 0short signed 16 bits 0ushort unsigned 16 bits 0int signed 32 bits 0uint unsigned 32 bits 0long signed 64 bits 0ulong unsigned 64 bits 0float 32-bit floating-point float. nandouble 64-bit floating-point double. nanreal largest in hardware real. nanchar unsigned 8-bit UTF-8 0xFFwchar unsigned 16-bit UTF-16 0xFFFFdchar unsigned 32-bit UTF-32 0x0000FFFF
Literals and Type Literals and Type InferenceInferenceUses the same suffixes as C/C++
◦f, l, u, etc.Uses the same prefixes
◦0123, 0x1CF◦Adds binary: 0b01001
Type inference with auto:auto targetSalary = 15_000_000;auto sq = (double x) { return x*x; };
ArraysArraysStatic arrays
◦Similar to arrays in C/C++◦int a[3];◦int[3] a; // Same thing
Dynamic Arrays◦Similar to vectors, ArrayLists, etc.
See staticarray.dInitialization:
◦int[3] a = [1:2, 3]; // [0,2,3]
Selected Array OperationsSelected Array OperationsIndexing with [ ]Concatenation with ~Copying with a.dupAssignment with =Length with .length
◦$ = .length in index expressions (a[2..$])◦m..n is an array slice (excludes n)◦can assign to .length to resize dynamic
arraysArray-wise operations (mathematical
vector operations)See mergesort.d, vector.d
StringsStringsStrings are dynamic arrays of
immutable characters◦ alias immutable(char)[] string;
◦string char (UTF-8)◦wstring wchar (UTF-16)◦dstring dchar (UTF-32)
foreach visits each character:◦ foreach (c; s) …
Associative ArraysAssociative ArraysA map (aka “dictionary”, “hash”, etc.)
◦Except it’s a built-in type (like dict in Python)
Uses array syntax:
void main() {int[string] mymap = ["one":1, "two":2];mymap["three"] = 3;foreach (k,v; mymap) writef("%s:%s ",k,v);
}
/* Output:three:3 one:1 two:2 */
Word Count Program Word Count Program OutputOutput/* Abbreviated output from the Gettysburg Address:But,: 1Four: 1…who: 3will: 1work: 1world: 1years: 1*/
A Word Count ProgramA Word Count Programimport std.stdio, std.array, std.file;
void wc(string filename) { string[] words = split(cast(string) read(filename)); int[string] counts; foreach (word; words) ++counts[word]; foreach (w; counts.keys.sort) writefln("%s: %d", w, counts[w]);}
void main(string[] args) { if (args.length == 2) wc(args[1]);}
TuplesTuplesDefined in std.typeconsTuple!(type1,type2,..)Helper function:
◦tuple(val1,val2,…)Can use 0-based position numbers
Can also use field namesSee tuple.d
Data QualifiersData QualifiersFor function parameters:
◦in | out | inout◦ref◦lazy
General declaration qualifiers:◦const◦immutable
Lazy ParametersLazy Parametersimport std.stdio;
void f(bool b, lazy void g) { if (b) { g(); }}
void main() { f(false, writeln("executing g")); f(true, writeln("executing g"));}
/* Output:executing g*/
ClosuresClosuresNested functions are returned as
(dynamic) closures◦aka “delegates” (a code-environment pair)◦The referencing environment could be a
function, class, or object◦Escaped activation records are moved
from the stack to the garbage-collected heap
Plain function pointers also supported:◦ int function(int) f; (vs. “int (*f)(int);” in C)
20
Plain Function PointersPlain Function Pointersint f1(int n) {return n+1;}int f2(int n) {return n+2;}int f3(int n) {return n+3;}
void main() { auto funs = [&f1, &f2, &f3]; foreach (f; funs) writeln(f(1));}
/* Output:234*/
Higher-Level Functions and Higher-Level Functions and ClosuresClosures
import std.stdio;
bool delegate(int) gtn(int n) { bool execute(int m) { return m > n; } return &execute;}
void main() { auto g5 = gtn(5); // Returns a ">5" delegate writeln(g5(1)); // false writeln(g5(6)); // true}
Lambda ExpressionsLambda Expressions
auto gtn(int n) { return delegate bool(int m) {return m > n;};}
// Preferred:auto gtn(int n) { return (int m) {return m > n;};}
An Object Calling An Object Calling EnvironmentEnvironment
void main() { class A { int fun() { return 42; } } A a = new A; auto dg = &a.fun; // A “bound method” writeln(dg()); // 42}
Parametric PolymorphismParametric PolymorphismCompile-time ParametersCompile-time Parameters
auto gtn(T)(T n) { return (T m) {return m > n;};}
void main() { auto g5 = gtn(5); writeln(g5(1)); writeln(g5(6));
auto g5s = gtn("baz"); writeln(g5s("bar")); writeln(g5s("foo"));}
Compile-Time ConstraintsCompile-Time Constraintsimport std.stdio, std.traits;
auto gtn(T)(T n) if (isNumeric!T) { return (T m) {return m > n;};}
void main() { auto g5 = gtn!int(5); writeln(g5(1)); writeln(g5(6));
auto g5s = gtn!string("baz"); // Error writeln(g5s("bar")); writeln(g5s("foo"));}
Compile-Time Function Compile-Time Function EvaluationEvaluation
// ctfe.d: Compile-time function executionimport std.stdio, std.conv; int square(int i) { return i * i; } void main() { static int n = square(3); // compile time writefln(text(n)); writefln(text(square(4))); // runtime}
Pure FunctionsPure FunctionsFor Referential TransparencyFor Referential Transparency
import std.stdio;import std.conv;
pure ulong fib(uint n) { if (n == 0 || n == 1) return n; ulong a = 1, b = 1; foreach (i; 2..n) { auto t = b; b += a; a = t; } return b;}
void main(string[] args) { if (args.length > 1) writeln(fib(to!(uint)(args[1])));}
Selected Higher-Level Selected Higher-Level FunctionsFunctionsint[] nums = [1,2,3,4,5];
auto squarelist(int[] list) { // 1 4 9 16 25 return map!("a*a")(list);}
auto sqsum2(int[] list) { // 55 return reduce!("a + b*b")(0,list); // (list)}
auto evens(int[] list) { // 2 4 return filter!("a % 2 == 0")(list);}
alias compose!("a/3.0","a*a","a+1.0") comp;writeln(comp(2.0)); // 3 = (2+1)^2 / 3alias pipe!(div3,sq,pls1) pip; // fns in scopewriteln(pip(2.0)); // 1.4444 = (2/3)^2+1
std.functional.memoizestd.functional.memoizeMemoization is a technique
where a cache of input-output pairs is kept for function calls
Avoids recomputing function values
See fib.d
Variable-length Argument Variable-length Argument ListsListsUse “…” in the parameter definitionHomogeneous
◦use “…” in the runtime parameter list◦passes a dynamic array
Heterogeneous◦use “…” in the compile-time parameter
list◦passes a tuple
See varargs.d
An Unsafe FunctionAn Unsafe Function
void g() { risky_op1(); // May acquire resources… risky_op2(); risky_op3(); writeln("g succeeded");}
Assume further that these functions must run to completion or not at all.
An Unsavory SolutionAn Unsavory Solutionvoid g() { risky_op1(); try { risky_op2(); } catch (Exception x) { undo_risky_op1(); // Back-out op1 throw x; // Rethrow exception } try { risky_op3(); writeln("g succeeded"); } catch (Exception x) { // Back-out op1 and op2 in reverse order undo_risky_op2(); undo_risky_op1(); throw x; }}
DD ’’s s scopescope Statement StatementOptions: Options: exitexit | | successsuccess | | failurefailure
void g() { risky_op1(); scope(failure) undo_risky_op1(); risky_op2(); scope(failure) undo_risky_op2(); risky_op3(); writeln("g succeeded");}
Contract Programming Contract Programming ExampleExampleAlso illustrates value types, operator overloading, Also illustrates value types, operator overloading, and unit testingand unit testingimport std.math; // For abs()
struct Rational { private int num = 0; private int den = 1; // Local helper function static int gcd(int m, int n) { return n == 0 ? abs(m) : gcd(abs(n), abs(m)%abs(n)); } // Class invariant invariant() { assert(den > 0 && gcd(num, den) == 1); }
Contract Programming Contract Programming ExampleExample(continued)(continued)
// Constructor this(int n, int d = 1) // Constructor precondition in { assert(d != 0); } body { num = n; den = d; auto div = gcd(num, den); if (den < 0) div = -div; num /= div; den /= div; }
Contract Programming Contract Programming ExampleExample(concluded)(concluded) // ("if" form evaluated at compile time) Rational opBinary(string op)(Rational r) if (op == "+”) { return Rational(num*r.den + den*r.num, den*r.den); }}
unittest { // Compile with –unittest option auto r1 = Rational(1,2), r2 = Rational(3,4), r3 = r1 + r2; assert(r3.num == 5 && r3.den == 4);}
void main(){}
Variant TypesVariant TypesSometimes you want to hold any type
◦hopefully not too often!Variant can hold any typeYou can only get out what was last
put in◦see variant.d
Bounded, discriminated unions with Algebraic◦like ML unions◦see variant2.d
ThreadsThreadsA thread is a path of execution
inside a running program (process)
A thread is launched on a function basis
Using the std.concurrency.spawn
See concur1.d
Message PassingMessage Passing
A paradigm for thread-to-thread communication
Threads send/receive data to/from each other
Less problematic (and less flexible) than sharing data via mutexesSee concur1,2,3.d
Infinite Streams in DInfinite Streams in DThreads and Message Passing
naturally support streams
See stream.d