Systems Programming & Beyond using C++ and D Three Unlikely Successful Features of D Andrei Alexandrescu andrei@erdani.com Prepared for LASER Summer School 2012 1 / 42 � 2012– Andrei Alexandrescu. c
1. The scope Statement: Casual Correct Code 2 / 42 � 2012– Andrei Alexandrescu. c
� action � 3 / 42 � 2012– Andrei Alexandrescu. c
� action � � cleanup � 3 / 42 � 2012– Andrei Alexandrescu. c
� action � � cleanup � � next � 3 / 42 � 2012– Andrei Alexandrescu. c
� action � � cleanup � � next � � rollback � 3 / 42 � 2012– Andrei Alexandrescu. c
C if ( � action � ) { if (! � next � ) { � rollback � } � cleanup � } 4 / 42 � 2012– Andrei Alexandrescu. c
C++ class RAII { RAII() { � action � } ~RAII() { � cleanup � } }; ... RAII raii; try { � next � } catch (...) { � rollback � throw; } 5 / 42 � 2012– Andrei Alexandrescu. c
Java, C# � action � try { � next � } catch (Exception e) { � rollback � throw e; } finally { � cleanup � } 6 / 42 � 2012– Andrei Alexandrescu. c
Go result, error := � action � if error != nil { defer � cleanup � if ! � next � � rollback � } 7 / 42 � 2012– Andrei Alexandrescu. c
Composition
C if ( � action 1 � ) { if ( � action 2 � ) { if (! � next 2 � ) { � rollback 2 � � rollback 1 � } � cleanup 2 � } else { � rollback 1 � } � cleanup 1 � } 9 / 42 � 2012– Andrei Alexandrescu. c
C++ class RAII1 { RAII1() { � action 1 � } ~RAII1() { � cleanup 1 � } }; class RAII2 { RAII2() { � action 2 � } ~RAII2() { � cleanup 2 � } }; ... 10 / 42 � 2012– Andrei Alexandrescu. c
C++ RAII1 raii1; try { RAII2 raii2; try { � next 2 � } catch (...) { � rollback 2 � throw; } } catch (...) { � rollback 1 � throw; } 11 / 42 � 2012– Andrei Alexandrescu. c
Java, C# � action 1 � try { � action 2 � try { � next 2 � } catch (Exception e) { � rollback 2 � throw e; } finally { � cleanup 2 � } } catch (Exception e) { � rollback 1 � throw e; } finally { � cleanup 1 � } 12 / 42 � 2012– Andrei Alexandrescu. c
Go result1, error := � action 1 � if error != nil { defer � cleanup 1 � result2, error := � action 2 � if error != nil { defer � cleanup 2 � if ! � next 2 � � rollback 2 � } else { � rollback 2 � } } 13 / 42 � 2012– Andrei Alexandrescu. c
Dislocation + Nesting = Fail 14 / 42 � 2012– Andrei Alexandrescu. c
“Programs must be written for people to read, and only incidentally for machines to execute.” – Abelson/Sussman, SICP 15 / 42 � 2012– Andrei Alexandrescu. c
“Error handling is about maintaining program invariants, and only incidentally about dealing with the error itself.” – I. Meade Etop 16 / 42 � 2012– Andrei Alexandrescu. c
Enter D � action � scope(failure) � rollback � scope(exit) � cleanup � 17 / 42 � 2012– Andrei Alexandrescu. c
But wait, there’s more (of the same) � action 1 � scope(failure) � rollback 1 � scope(exit) � cleanup 1 � � action 2 � scope(failure) � rollback 2 � scope(exit) � cleanup 2 � 18 / 42 � 2012– Andrei Alexandrescu. c
Three’s a charm � action 1 � scope(failure) � rollback 1 � scope(exit) � cleanup 1 � � action 2 � scope(failure) � rollback 2 � scope(exit) � cleanup 2 � � action 3 � scope(failure) � rollback 3 � scope(exit) � cleanup 3 � ... moar please ... 19 / 42 � 2012– Andrei Alexandrescu. c
Transactional File Copy import std.exception, std.file, std.stdio; void main(string[] args) { enforce(args.length == 3, "Usage: ..."); scope(success) rename(args[2] ~ ".tmp", args[2]); auto src = File(args[1]), tgt = File(args[2] ~ ".tmp", "w"); scope(failure) remove(args[2] ~ ".tmp"); foreach (chunk; src.byChunk(1024 * 64)) { tgt.rawWrite(chunk); } } 20 / 42 � 2012– Andrei Alexandrescu. c
2-5x improvement on relevant metrics 21 / 42 � 2012– Andrei Alexandrescu. c
. . . on code you write 22 / 42 � 2012– Andrei Alexandrescu. c
Straight line + Implicit flow = Win 23 / 42 � 2012– Andrei Alexandrescu. c
2. Built-in Arrays 24 / 42 � 2012– Andrei Alexandrescu. c
Systems-Level Language 25 / 42 � 2012– Andrei Alexandrescu. c
Pointers? 26 / 42 � 2012– Andrei Alexandrescu. c
Unsafe iteration Unsafe arithmetic Efficient 27 / 42 � 2012– Andrei Alexandrescu. c
D array = pointer + length a · · · · · · 1 5 2 3 6 b 28 / 42 � 2012– Andrei Alexandrescu. c
Safe iteration Safe indexing Efficient Enabling 29 / 42 � 2012– Andrei Alexandrescu. c
Cheap, type-preserving slicing b = b[1 .. $ - 1]; a · · · · · · 1 5 2 3 6 b 30 / 42 � 2012– Andrei Alexandrescu. c
Convenient bool palindrome(T)(T[] a) { for (; a.length > 1; a = a[1 .. $ - 1]) { if (a[0] != a[$ - 1]) return false; } return true; } 31 / 42 � 2012– Andrei Alexandrescu. c
Value Range Propagation 32 / 42 � 2012– Andrei Alexandrescu. c
Integral types • The usual menagerie: 8, 16, 32, 64 signed and unsigned integrals • 32, 64 and sometimes 80-bit floating point types • The C operator paraphernalia ◦ Defined the same way in all implementations ◦ C code: either compiles and runs with same results, or doesn’t compile 33 / 42 � 2012– Andrei Alexandrescu. c
Conversions • Many type widths beget conversion problems short a; byte b; uint c; auto d = a * b + c; // what’s the type of d? • auto increases the cost of complicated rules • Each language tried to work it out its own set of rules 34 / 42 � 2012– Andrei Alexandrescu. c
C Rules • Default result of operators is int • Unless a long is involved • Unless an unsigned is within a mile radius • Unless the unsigned is shorter than the result type computed as above • Bottom line: everything is (u)int or (u)long • Trust the programmer ⇒ long to char is implicit! 35 / 42 � 2012– Andrei Alexandrescu. c
High Level/Scripting Languages • Generally use unbounded-length integrals • Devise representation based on actual magnitude • That path can’t be taken by a systems language • However, D has a heavily optimized library type BigInt 36 / 42 � 2012– Andrei Alexandrescu. c
Java, C# • Start from C’s rules • Play it Safe ⇒ No narrowing conversions allowed // This is not D code byte a, b, c; a = (byte) (a | b & c); b = (byte) (b | 1); • Net result: casts galore 37 / 42 � 2012– Andrei Alexandrescu. c
Value Range Propagation (VRP) • During an expression, maintain the min/max values of intermediate results • For compile-time constants: min_c = max_c = c • For variables: the representable limits byte a, b, c; a = a | b & c; // range -128..127 b = b | 1; // range 0..1 • No casts needed • Yet typeof(b | 1) is int ! 38 / 42 � 2012– Andrei Alexandrescu. c
VRP Never Truncates • D allows implicit narrowing if and only if the range fits within the target type byte a, b, c; a = a | b + c; // error b = c * 2; // error 39 / 42 � 2012– Andrei Alexandrescu. c
VRP Is Imperfect • No “memory” beyond one statement byte a, b, c; a = 1; b = c | a; // error • However, it practically works surprisingly well • Can be improved to work across statements • Can be improved to account for control flow • Extra compilation costs (time, memory) must be justifiable 40 / 42 � 2012– Andrei Alexandrescu. c
Summary 41 / 42 � 2012– Andrei Alexandrescu. c
Summary 1. The scope statement 42 / 42 � 2012– Andrei Alexandrescu. c
Summary 1. The scope statement 2. Built-in arrays 42 / 42 � 2012– Andrei Alexandrescu. c
Summary 1. The scope statement 2. Built-in arrays 3. Value range propagation 42 / 42 � 2012– Andrei Alexandrescu. c
Recommend
More recommend