Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Three, no, Four Cool Things About D

1,662 views

Published on

Published in: Software, Technology, Education
  • Be the first to comment

Three, no, Four Cool Things About D

  1. 1. c 2014– Andrei Alexandrescu. 1 / 47 Three Cool Things About D Andrei Alexandrescu, Ph.D. Research Scientist, Facebook aa@fb.com NDC Oslo 2014
  2. 2. c 2014– Andrei Alexandrescu. 2 / 47 ThreeFour Cool Things About D Andrei Alexandrescu, Ph.D. Research Scientist, Facebook aa@fb.com NDC Oslo 2014
  3. 3. What’s the Deal?? c 2014– Andrei Alexandrescu. 3 / 47
  4. 4. D is. . . c 2014– Andrei Alexandrescu. 4 / 47 • Efficient when it can • Convenient when it should • Safe when it must
  5. 5. Basics c 2014– Andrei Alexandrescu. 5 / 47 • Statically typed Use deduction wherever possible • Sininimp-Mulinint object-oriented style • Gray-box modularity: ◦ Python-inspired modules for “classic” entities ◦ White-box parameterized types and functions • Heterogeneous translation of parameterized code
  6. 6. Turtles all the way down c 2014– Andrei Alexandrescu. 6 / 47
  7. 7. Hello, World! c 2014– Andrei Alexandrescu. 7 / 47 #!/usr/bin/rdmd import std.stdio; void main() { writeln("Hello, world!"); } • “Meh”worthy • However: ◦ Simple ◦ Correct ◦ Scriptable ◦ Features turtles
  8. 8. Them turtles c 2014– Andrei Alexandrescu. 8 / 47 #!/usr/bin/rdmd void main() { import std.stdio; writeln("Hello, world!"); } • Most everything can be scoped everywhere • Better scoping, reasoning, dependency mgmt • Functions • Types (Voldermort types) • Even generics
  9. 9. Segue into generics c 2014– Andrei Alexandrescu. 9 / 47 void log(T)(T stuff) { import std.datetime, std.stdio; writeln(Clock.currTime(), ’ ’, stuff); } void main() { log("hello"); } • If not instantiated, no import • imports cached once realized • Generics faster to build, import • Less pressure on linker
  10. 10. Approach to Safety c 2014– Andrei Alexandrescu. 10 / 47
  11. 11. Memory Safety c 2014– Andrei Alexandrescu. 11 / 47 • All data is read with the type it was written • Eliminates unpleasant class of errors • Makes bugs reproducible • Preserves the integrity of the type system
  12. 12. Challenge c 2014– Andrei Alexandrescu. 12 / 47 • System-level languages must: ◦ Forge pointers (linkers/loaders) ◦ Magically change type of memory (allocators/GCs) ◦ Recycle memory “early” ◦ Circumvent type system
  13. 13. Attack c 2014– Andrei Alexandrescu. 13 / 47 • All of D can’t be safe • Define a safe subset • Safe subset usable for large portions or entire programs • Tagged with @safe attribute @safe double cube(double x) { return x * x * x; } • Unsafe functions tagged with @system @system void free(void*);
  14. 14. But wait c 2014– Andrei Alexandrescu. 14 / 47 • Important case: safe functions with unknown/unprovable implementation ◦ fopen, malloc, isAlpha ◦ Small buffer optimization ◦ Tagged union implementation • Define attribute @trusted
  15. 15. Rules c 2014– Andrei Alexandrescu. 15 / 47 • @safe functions cannot: ◦ call @system functions ◦ escape addresses of locals ◦ forge pointers ◦ cast pointers around ◦ do pointer arithmetic • N.B. Not all rules completely implemented ◦ Some on the conservative side ◦ A few details in flux
  16. 16. Resulting setup c 2014– Andrei Alexandrescu. 16 / 47 • Low notational overhead: entire modules or portions thereof can be annotated • Deduction for generics • Application divided in: ◦ Safe part, uses GC, easy to write and debug ◦ Trusted part, encapsulated unsafe manipulation, proven by means of code review ◦ System part, non-encapsulated unsafe manipulation, only when solidly justified
  17. 17. Approach to Purity c 2014– Andrei Alexandrescu. 17 / 47
  18. 18. Thesis c 2014– Andrei Alexandrescu. 18 / 47 • Writing entire programs in pure style difficult • Writing fragments of programs in pure style easy, useful • + Easier to verify useful properties, debug • + Better code generation • − Challenge: interfacing pure and impure code
  19. 19. Functional Factorial (yawn) c 2014– Andrei Alexandrescu. 19 / 47 ulong factorial(uint n) { return n <= 1 ? 1 : n * factorial(n - 1); } • It’s PSPACE! • Somebody should do hard time for this
  20. 20. However, it’s pure c 2014– Andrei Alexandrescu. 20 / 47 pure ulong factorial(uint n) { return n <= 1 ? 1 : n * factorial(n - 1); } • Pure is good
  21. 21. Functional Factorial, Fixed c 2014– Andrei Alexandrescu. 21 / 47 pure ulong factorial(uint n) { ulong crutch(uint n, ulong result) { return n <= 1 ? result : crutch(n - 1, n * result); } return crutch(n, 1); } • Threads state through as parameters • You know what? I don’t care for it
  22. 22. Honest Factorial c 2014– Andrei Alexandrescu. 22 / 47 ulong factorial(uint n) { ulong result = 1; foreach (uint i = 2; i <= n; ++i) { result *= i; } return result; } • But no longer pure! • Well allow me to retort
  23. 23. Pure is as pure does c 2014– Andrei Alexandrescu. 24 / 47 • “Pure functions always return the same result for the same arguments” • No reading and writing of global variables ◦ (Global constants okay) • No calling of impure functions • Who said anything about local, transient state inside the function?
  24. 24. Transitive State c 2014– Andrei Alexandrescu. 25 / 47 pure void reverse(T)(T[] a) { foreach (i; 0 .. data.length / 2) { swap(data[i], data[$ - i - 1]); } } • Possibility: disallow • More useful: relaxed rule • Operate with transitive closure of state reachable through parameter • Not functional pure, but an interesting superset • No need for another annotation, it’s all in the signature!
  25. 25. User-defined types c 2014– Andrei Alexandrescu. 26 / 47 pure BigInt factorial(uint n) { BigInt result = 1; for (; n > 1; --n) { result *= n; } return result; } • Works, but not in released version • Most of stdlib “purified”
  26. 26. Aftermath c 2014– Andrei Alexandrescu. 27 / 47 • If parameters reach mutable state: ◦ Relaxed pure—no globals, no I/O, no impure calls • If parameters can’t reach mutable state: ◦ “Haskell-grade” observed purity ◦ Yet imperative implementation possible ◦ As long as it’s local only
  27. 27. The Generative Connection: mixin c 2014– Andrei Alexandrescu. 28 / 47
  28. 28. Generative programming c 2014– Andrei Alexandrescu. 29 / 47 • In brief: code that generates code • Generic programming often requires algorithm specialization • Specification often present in a DSL
  29. 29. Embedded DSLs c 2014– Andrei Alexandrescu. 30 / 47 Force into host language’s syntax?
  30. 30. Embedded DSLs c 2014– Andrei Alexandrescu. 31 / 47 • Formatted printing?
  31. 31. Embedded DSLs c 2014– Andrei Alexandrescu. 31 / 47 • Formatted printing? • Regular expressions?
  32. 32. Embedded DSLs c 2014– Andrei Alexandrescu. 31 / 47 • Formatted printing? • Regular expressions? • EBNF?
  33. 33. Embedded DSLs c 2014– Andrei Alexandrescu. 31 / 47 • Formatted printing? • Regular expressions? • EBNF? • PEG?
  34. 34. Embedded DSLs c 2014– Andrei Alexandrescu. 31 / 47 • Formatted printing? • Regular expressions? • EBNF? • PEG? • SQL?
  35. 35. Embedded DSLs c 2014– Andrei Alexandrescu. 31 / 47 • Formatted printing? • Regular expressions? • EBNF? • PEG? • SQL? • . . . Pasta for everyone!
  36. 36. Embedded DSLs c 2014– Andrei Alexandrescu. 32 / 47 Here: use with native grammar Process during compilation Generate D code accordingly
  37. 37. Compile-Time Evaluation c 2014– Andrei Alexandrescu. 33 / 47 • A large subset of D available for compile-time evaluation ulong factorial(uint n) { ulong result = 1; for (; n > 1; --n) result *= n; return result; } ... auto f1 = factorial(10); // run-time static f2 = factorial(10); // compile-time
  38. 38. Code injection with mixin c 2014– Andrei Alexandrescu. 34 / 47 mixin("writeln("hello, world");"); mixin(generateSomeCode()); • Not as glamorous as AST manipulation but darn effective • Easy to understand and debug • Now we have compile-time evaluation AND mixin. . .
  39. 39. c 2014– Andrei Alexandrescu. 35 / 47 Wait a minute!
  40. 40. Example: bitfields in library c 2014– Andrei Alexandrescu. 36 / 47 struct A { int a; mixin(bitfields!( uint, "x", 2, int, "y", 3, uint, "z", 2, bool, "flag", 1)); } A obj; obj.x = 2; obj.z = obj.x;
  41. 41. Example: boilerplate c 2014– Andrei Alexandrescu. 37 / 47 string forward(string p, string[] names...) { string r; foreach (n; names) { r ~= "static if (hasMember!(typeof("~p~ "), ‘"~n~"‘)" ~ ") auto ref "~n~ "(T_...)(T_ t_) { return "~ p~"."~n~"(t_); }n"; } return r; }
  42. 42. Example: boilerplate c 2014– Andrei Alexandrescu. 38 / 47 struct A { int fun(int, string) { ... } int gun(int, string, double) { ... } } struct B { A a; //pragma(msg, forward("a", "fun", "gun")); mixin(forward("a", "fun", "gun")); }
  43. 43. Parser c 2014– Andrei Alexandrescu. 39 / 47 import pegged.grammar; // by Philippe Sigaud mixin(grammar(" Expr < Factor AddExpr* AddExpr < (’+’/’-’) Factor Factor < Primary MulExpr* MulExpr < (’*’/’/’) Primary Primary < Parens / Number / Variable / ’-’ Primary Parens < ’(’ Expr ’)’ Number <~ [0-9]+ Variable <- Identifier "));
  44. 44. Usage c 2014– Andrei Alexandrescu. 40 / 47 // Parsing at compile-time: static parseTree1 = Expr.parse( "1 + 2 - (3*x-5)*6"); pragma(msg, parseTree1.capture); // Parsing at run-time: auto parseTree2 = Expr.parse(readln()); writeln(parseTree2.capture);
  45. 45. Scaling up c 2014– Andrei Alexandrescu. 41 / 47 1000 lines of D grammar → 3000 lines D parser
  46. 46. c 2014– Andrei Alexandrescu. 42 / 47 Highly integrated lex+yacc
  47. 47. c 2014– Andrei Alexandrescu. 43 / 47 What about regexen?
  48. 48. Compile-time regular expressions c 2014– Andrei Alexandrescu. 44 / 47 • GSoC project by Dmitry Olshansky, merged into std • Fully UTF capable, no special casing for ASCII • Two modes sharing the same backend: auto r1 = regex("^.*/([^/]+)/?$"); static r2 = ctRegex!("^.*/([^/]+)/?$"); • Run-time version uses intrinsics in a few places • Static version generates specialized automaton, then compiles it
  49. 49. Summary c 2014– Andrei Alexandrescu. 46 / 47
  50. 50. Summary c 2014– Andrei Alexandrescu. 47 / 47 • Turtles • Safe subset • Pure functions • Generative programming

×