D Programming Language: The Sudden Andrei Alexandrescu, Ph.D. - - PowerPoint PPT Presentation

d programming language the sudden
SMART_READER_LITE
LIVE PREVIEW

D Programming Language: The Sudden Andrei Alexandrescu, Ph.D. - - PowerPoint PPT Presentation

D Programming Language: The Sudden Andrei Alexandrescu, Ph.D. Research Scientist, Facebook aa@fb.com YOW 2014 1 / 44 2014 Andrei Alexandrescu. c Introduction 2 / 44 2014 Andrei Alexandrescu. c Introduction 3 / 44 2014


slide-1
SLIDE 1

c

2014– Andrei Alexandrescu.

1 / 44

D Programming Language: The Sudden

Andrei Alexandrescu, Ph.D. Research Scientist, Facebook

aa@fb.com

YOW 2014

slide-2
SLIDE 2

Introduction

c

2014– Andrei Alexandrescu.

2 / 44

slide-3
SLIDE 3

Introduction

c

2014– Andrei Alexandrescu.

3 / 44

slide-4
SLIDE 4

Sudden Sequels

c

2014– Andrei Alexandrescu.

4 / 44

  • Pronouncing “Melbourne” and “Brisbane”
slide-5
SLIDE 5

Sudden Sequels

c

2014– Andrei Alexandrescu.

4 / 44

  • Pronouncing “Melbourne” and “Brisbane”
  • Burn Identity
slide-6
SLIDE 6

Sudden Sequels

c

2014– Andrei Alexandrescu.

4 / 44

  • Pronouncing “Melbourne” and “Brisbane”
  • Burn Identity

Sequel to Bourne Identity and Burn Notice

slide-7
SLIDE 7

Sudden Sequels

c

2014– Andrei Alexandrescu.

4 / 44

  • Pronouncing “Melbourne” and “Brisbane”
  • Burn Identity

Sequel to Bourne Identity and Burn Notice

  • Airburn Infantry
slide-8
SLIDE 8

Sudden Sequels

c

2014– Andrei Alexandrescu.

4 / 44

  • Pronouncing “Melbourne” and “Brisbane”
  • Burn Identity

Sequel to Bourne Identity and Burn Notice

  • Airburn Infantry

Sequel to BoB and Operation Flamethrower

slide-9
SLIDE 9

Sudden Sequels

c

2014– Andrei Alexandrescu.

4 / 44

  • Pronouncing “Melbourne” and “Brisbane”
  • Burn Identity

Sequel to Bourne Identity and Burn Notice

  • Airburn Infantry

Sequel to BoB and Operation Flamethrower

  • Newburn
slide-10
SLIDE 10

Sudden Sequels

c

2014– Andrei Alexandrescu.

4 / 44

  • Pronouncing “Melbourne” and “Brisbane”
  • Burn Identity

Sequel to Bourne Identity and Burn Notice

  • Airburn Infantry

Sequel to BoB and Operation Flamethrower

  • Newburn

Sequel to Chucky and Spontaneous Combustion

slide-11
SLIDE 11

Sudden Sequels

c

2014– Andrei Alexandrescu.

4 / 44

  • Pronouncing “Melbourne” and “Brisbane”
  • Burn Identity

Sequel to Bourne Identity and Burn Notice

  • Airburn Infantry

Sequel to BoB and Operation Flamethrower

  • Newburn

Sequel to Chucky and Spontaneous Combustion

  • The Dark Knight Rises
slide-12
SLIDE 12

Sudden Sequels

c

2014– Andrei Alexandrescu.

4 / 44

  • Pronouncing “Melbourne” and “Brisbane”
  • Burn Identity

Sequel to Bourne Identity and Burn Notice

  • Airburn Infantry

Sequel to BoB and Operation Flamethrower

  • Newburn

Sequel to Chucky and Spontaneous Combustion

  • The Dark Knight Rises

Batman vs. Bun

slide-13
SLIDE 13
slide-14
SLIDE 14
slide-15
SLIDE 15

Motivation

c

2014– Andrei Alexandrescu.

7 / 44

  • Systems-level programming a necessity
  • Several application categories
  • Faster is better—no “good enough” limit
  • Ever-growing modeling needs
  • No room below, no escape: all in same language
  • Runtime support
  • Machine, device interface
  • Base library
  • This is (literally) where the buck stops
slide-16
SLIDE 16

D Design Principles

c

2014– Andrei Alexandrescu.

8 / 44

  • Leave no room below
  • share memory model with C
  • statically typed
  • Multi-paradigm; balanced
  • Practical
  • Principled
  • Avoid arcana
slide-17
SLIDE 17

Why?

c

2014– Andrei Alexandrescu.

9 / 44

  • Party line
  • convenience
  • modeling power
  • efficiency
  • Actual reasons
  • Produces fast binaries, fast
  • Easier to get into than alternatives
  • Fun
slide-18
SLIDE 18

Why not?

c

2014– Andrei Alexandrescu.

10 / 44

  • Party line
  • Actual reasons
  • Poor on formal specification
  • Little corporate pickup, support
  • Dearth of libraries
  • Large
slide-19
SLIDE 19

The “Meh”

c

2014– Andrei Alexandrescu.

11 / 44

#!/usr/bin/rdmd import std.stdio; void main() { writeln("Hello, world!"); }

  • Why the std.std stutter?
  • Why import stuff for everything?
  • Why no code at top level?
  • However:
  • Simple
  • Correct
  • Scriptable
slide-20
SLIDE 20

The Innocently Plausible

c

2014– Andrei Alexandrescu.

12 / 44

void main() { import std.stdio; writeln("Hello, world!"); }

  • Doesn’t work in Java, C#
  • Career-limiting move in Python, C, C++
  • In D, most everything can be scoped everywhere
  • Functions
  • Types (Voldermort types)
  • Even generics
  • Better modularity, reasoning
slide-21
SLIDE 21

The Unexpected Emergent

c

2014– Andrei Alexandrescu.

13 / 44

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
slide-22
SLIDE 22

Heck, add variadics too

c

2014– Andrei Alexandrescu.

14 / 44

void log(T...)(T stuff) { import std.datetime, std.stdio; writeln(Clock.currTime(), ’ ’, stuff); } void main() { log("Reached Nirvana level: ", 9); }

slide-23
SLIDE 23

Suddenly

c

2014– Andrei Alexandrescu.

15 / 44

Natural lexical scoping leads to faster builds

slide-24
SLIDE 24

Approach to Purity

c

2014– Andrei Alexandrescu.

16 / 44

slide-25
SLIDE 25

Thesis

c

2014– Andrei Alexandrescu.

17 / 44

  • Writing entire programs in pure style challenging
  • Writing fragments of programs in pure style easy, useful
  • + Easier to verify useful properties, debug
  • + Better code generation
  • − Challenge: interfacing pure and impure code
slide-26
SLIDE 26

Functional Factorial (yawn)

c

2014– Andrei Alexandrescu.

18 / 44

ulong factorial(uint n) { return n <= 1 ? 1 : n * factorial(n - 1); }

  • It’s PSPACE!
  • Somebody should do hard time for this
slide-27
SLIDE 27

However, it’s pure

c

2014– Andrei Alexandrescu.

19 / 44

pure ulong factorial(uint n) { return n <= 1 ? 1 : n * factorial(n - 1); }

  • Pure is good
slide-28
SLIDE 28

Functional Factorial, Fixed

c

2014– Andrei Alexandrescu.

20 / 44

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
slide-29
SLIDE 29

Honest Factorial

c

2014– Andrei Alexandrescu.

21 / 44

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
slide-30
SLIDE 30
slide-31
SLIDE 31

Pure is as pure does

c

2014– Andrei Alexandrescu.

23 / 44

  • “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?

slide-32
SLIDE 32

Transitive State

c

2014– Andrei Alexandrescu.

24 / 44

pure void reverse(T)(T[] a) { foreach (i; 0 .. a.length / 2) { swap(a[i], a[$ - 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!
slide-33
SLIDE 33

User-defined types

c

2014– Andrei Alexandrescu.

25 / 44

pure BigInt factorial(uint n) { BigInt result = 1; for (; n > 1; --n) { result *= n; } return result; }

  • Better yet: purity deduced for generics and lambdas
slide-34
SLIDE 34

Aftermath

c

2014– Andrei Alexandrescu.

26 / 44

  • 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
slide-35
SLIDE 35

Suddenly

c

2014– Andrei Alexandrescu.

27 / 44

Combining purity with mutability improves both

slide-36
SLIDE 36

The Generative Connection

c

2014– Andrei Alexandrescu.

28 / 44

slide-37
SLIDE 37

Generative programming

c

2014– Andrei Alexandrescu.

29 / 44

  • In brief: code that generates code
  • Generic programming often requires algorithm

specialization

  • Specification often present in a DSL
slide-38
SLIDE 38

Embedded DSLs

c

2014– Andrei Alexandrescu.

30 / 44

Force into host language’s syntax?

slide-39
SLIDE 39

Embedded DSLs

c

2014– Andrei Alexandrescu.

31 / 44

  • Formatted printing?
slide-40
SLIDE 40

Embedded DSLs

c

2014– Andrei Alexandrescu.

31 / 44

  • Formatted printing?
  • Regular expressions?
slide-41
SLIDE 41

Embedded DSLs

c

2014– Andrei Alexandrescu.

31 / 44

  • Formatted printing?
  • Regular expressions?
  • EBNF?
slide-42
SLIDE 42

Embedded DSLs

c

2014– Andrei Alexandrescu.

31 / 44

  • Formatted printing?
  • Regular expressions?
  • EBNF?
  • PEG?
slide-43
SLIDE 43

Embedded DSLs

c

2014– Andrei Alexandrescu.

31 / 44

  • Formatted printing?
  • Regular expressions?
  • EBNF?
  • PEG?
  • SQL?
slide-44
SLIDE 44

Embedded DSLs

c

2014– Andrei Alexandrescu.

31 / 44

  • Formatted printing?
  • Regular expressions?
  • EBNF?
  • PEG?
  • SQL?
  • . . . Pasta for everyone!
slide-45
SLIDE 45

Embedded DSLs

c

2014– Andrei Alexandrescu.

32 / 44

Here: use with native grammar Process during compilation Generate D code accordingly

slide-46
SLIDE 46

Compile-Time Evaluation

c

2014– Andrei Alexandrescu.

33 / 44

  • 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

slide-47
SLIDE 47

Code injection with mixin

c

2014– Andrei Alexandrescu.

34 / 44

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. . .
slide-48
SLIDE 48

c

2014– Andrei Alexandrescu.

35 / 44

Wait a minute!

slide-49
SLIDE 49

Example: bitfields in library

c

2014– Andrei Alexandrescu.

36 / 44

struct A { int a; mixin(bitfields!( uint, "x", 2, int, "y", 3, uint, "z", 2, bool, "flag", 1)); } A obj;

  • bj.x = 2;
  • bj.z = obj.x;
slide-50
SLIDE 50

Parser

c

2014– Andrei Alexandrescu.

37 / 44

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 "));

slide-51
SLIDE 51

Usage

c

2014– Andrei Alexandrescu.

38 / 44

// 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);

slide-52
SLIDE 52

Scaling up

c

2014– Andrei Alexandrescu.

39 / 44

1000 lines of D grammar → 3000 lines D parser

slide-53
SLIDE 53

c

2014– Andrei Alexandrescu.

40 / 44

Highly integrated lex+yacc

slide-54
SLIDE 54

c

2014– Andrei Alexandrescu.

41 / 44

What about regexen?

slide-55
SLIDE 55

Compile-time regular expressions

c

2014– Andrei Alexandrescu.

42 / 44

  • 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

slide-56
SLIDE 56
slide-57
SLIDE 57

Summary

c

2014– Andrei Alexandrescu.

44 / 44

  • Modularity + scoping
  • Purity + sinning
  • Compile-time evaluation + mixing code in