tour of language landscape (katsconf)

Post on 14-Apr-2017

6.541 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

tour guide : Yan Cui @theburningmonk

Hi, my name is Yan Cui.

1MILLION USERS

ACTIVEDAILY

250MILLION DAY

PERREQUEST

agenda

Type Provider Pipes

Statically Resolved TP Implicit Interface Implementation

Borrowed Pointers Dependent Types

Uniqueness Types

Bit SyntaxSignals

Macros

Unit-of-Measure

Actor Model

F#ClojureErlang

Go

RustElm Idris

F#ClojureErlang

Go

RustElm Idris

disclaimers

“Programming languages have a devious influence: they shape our thinking

habits.”

- Edsger W. Dijkstra

“One of the most disastrous thing we can learn is the first programming language, even

if it's a good programming language.”

- Alan Kay

“The limits of my language means the limits

of my world.”

- Ludwig Wittgenstein

“We cannot solve our problems with the same thinking we used when

we created them.”

- Albert Einstein

F#ClojureErlang

Go

RustElm Idris

your app

your app

CSVCSVCSV

CSVCSVXML

your app

CSVCSVCSV

CSVCSVXML

some service

your app

CSVCSVCSV

CSVCSVXML

some service

DB

1. define DTO types!2. I/O!3. marshal data into DTO!4. do useful work

1. define DTO types!2. I/O!3. marshal data into DTO!4. do useful work

compilerprovideexternal

data source typed info

type providers

intellisense!tooltips!

compile time validation

no code generation

R

FunScript AzureAmazon S3

CSVSQLiteSQL Server

WSDL

WorldBank

RegexODATA IKVM

FacebookApiary

XAMLFreebaseHadoop

Oracle

Minesweeper

Don SymePowershell

JSON

Fizzbuzz

Mixin

RSS

MatlabDates

NorthPole

XML

Python

pipes

“…a clean design is one that supports visual thinking so

people can meet their informational needs with a

minimum of conscious effort.”

- Daniel Higginbotham (www.visualmess.com)

Whilst talking with an ex-colleague, a question came up on how to implement the Stable Marriage problem using a message passing approach. Naturally, I wanted to answer that question with Erlang!!!Let’s first dissect the problem and decide what processes we need and how they need to interact with one another.!!The stable marriage problem is commonly stated as:!Given n men and n women, where each person has ranked all members of the opposite sex with a unique number between 1 and n in order of preference, marry the men and women together such that there are no two people of opposite sex who would both rather have each other than their current partners. If there are no such people, all the marriages are “stable”. (It is assumed that the participants are binary gendered and that marriages are not same-sex).!From the problem description, we can see that we need:!* a module for man!* a module for woman!* a module for orchestrating the experiment!In terms of interaction between the different modules, I imagined something along the lines of…

how we read ENGLISH

see also http://bit.ly/1KN8cd0

Whilst talking with an ex-colleague, a question came up on how to implement the Stable Marriage problem using a message passing approach. Naturally, I wanted to answer that question with Erlang!!!Let’s first dissect the problem and decide what processes we need and how they need to interact with one another.!!The stable marriage problem is commonly stated as:!Given n men and n women, where each person has ranked all members of the opposite sex with a unique number between 1 and n in order of preference, marry the men and women together such that there are no two people of opposite sex who would both rather have each other than their current partners. If there are no such people, all the marriages are “stable”. (It is assumed that the participants are binary gendered and that marriages are not same-sex).!From the problem description, we can see that we need:!* a module for man!* a module for woman!* a module for orchestrating the experiment!In terms of interaction between the different modules, I imagined something along the lines of…

2. top-to-bottom1.left-to-right

how we read ENGLISH

see also http://bit.ly/1KN8cd0

how we read CODE

public void DoSomething(int x, int y)!{! Foo(y,! Bar(x,! Zoo(Monkey())));!}

see also http://bit.ly/1KN8cd0

how we read CODE

public void DoSomething(int x, int y)!{! Foo(y,! Bar(x,! Zoo(Monkey())));!}

2. bottom-to-top

1.right-to-left

see also http://bit.ly/1KN8cd0

Whilst talking with an ex-colleague, a question came up on how to implement the Stable Marriage problem using a message passing approach. Naturally, I wanted to answer that question with Erlang!!!Let’s first dissect the problem and decide what processes we need and how they need to interact with one another.!!The stable marriage problem is commonly stated as:!Given n men and n women, where each person has ranked all members of the opposite sex with a unique number between 1 and n in order of preference, marry the men and women together such that there are no two people of opposite sex who would both rather have each other than their current partners. If there are no such people, all the marriages are “stable”. (It is assumed that the participants are binary gendered and that marriages are not same-sex).!From the problem description, we can see that we need:!* a module for man!* a module for woman!* a module for orchestrating the experiment!In terms of interaction between the different modules, I imagined something along the lines of…

2. top-to-bottom

1.left-to-right

how we read ENGLISH

public void DoSomething(int x, int y)!{! Foo(y,! Bar(x,! Zoo(Monkey())));!}

2. top-to-bottom

1.right-to-left

how we read CODE

see also http://bit.ly/1KN8cd0

“…a clean design is one that supports visual thinking so

people can meet their informational needs with a

minimum of conscious effort.”

|>

how we read CODE

let drawCircle x y radius = radius |> circle |> filled (rgb 150 170 150) |> alpha 0.5 |> move (x, y)

see also http://bit.ly/1KN8cd0

how we read CODE

let drawCircle x y radius = radius |> circle |> filled (rgb 150 170 150) |> alpha 0.5 |> move (x, y)

2. top-to-bottom1.left-to-right

see also http://bit.ly/1KN8cd0

let drawCircle x y radius = circle radius |> filled (rgb 150 170 150) |> alpha 0.5 |> move (x, y)

see also http://bit.ly/1KN8cd0

let drawCircle x y radius = circle radius |> filled (rgb 150 170 150) |> alpha 0.5 |> move (x, y)

see also http://bit.ly/1KN8cd0

let drawCircle x y radius = circle radius |> filled (rgb 150 170 150) |> alpha 0.5 |> move (x, y)

see also http://bit.ly/1KN8cd0

NASA orbiter crashed because one engineer accidentally used miles instead of kilometres

you’re never too smart to make mistakes

unit-of-measure

[<Measure>]!type Pence

e.g.! 42<Pence>!! 153<Pence>!! …

10<Meter> / 2<Second> ! = 5<Meter/Second>!10<Meter> * 2<Second> ! = 20<Meter Second> !10<Meter> + 10<Meter> ! = 20<Meter>!10<Meter> * 10! ! ! = 100<Meter>!10<Meter> * 10<Meter> ! = 100<Meter2>!10<Meter> + 2<Second> ! // error!10<Meter> + 2 ! ! ! // error

10<Meter> / 2<Second> ! = 5<Meter/Second>!10<Meter> * 2<Second> ! = 20<Meter Second> !10<Meter> + 10<Meter> ! = 20<Meter>!10<Meter> * 10! ! ! = 100<Meter>!10<Meter> * 10<Meter> ! = 100<Meter2>!10<Meter> + 2<Second> ! // error!10<Meter> + 2 ! ! ! // error

F#ClojureErlang

Go

RustElm Idris

!?

Duck Typing

If it looks like a duck and quacks like a duck, it's a duck

def say_quack(duck): duck.quack()

def say_quack(duck): duck.quack()

class Duck: def quack(self): print("quack quack!”)

class Duck: def quack(self): print("quack quack!”) !

duck = Duck() say_quack(duck) !

> quack quack!

class Bird: def quack(self): print(“tweet tweet!”)

class Bird: def quack(self): print(“tweet tweet!”) !

bird = Bird() say_quack(bird) !

> tweet tweet!

ConvenienceSafety

what if…

Convenience Safety

see also http://bit.ly/1H2fN9i

implicit interface!

implementation

type Duck interface { Quack() }

see also http://bit.ly/1ER5zVs

func sayQuack(duck Duck) { duck.Quack() }

see also http://bit.ly/1ER5zVs

type Donald struct { } func (d Donald) Quack() { fmt.Println(“quack quack!”) }

see also http://bit.ly/1ER5zVs

type Bird struct { } func (b Bird) Quack() { fmt.Println(“tweet tweet!”) }

see also http://bit.ly/1ER5zVs

func main() { donald := Donald{} sayQuack(donald) bird := Bird{} sayQuack(bird) }

see also http://bit.ly/1ER5zVs

quack quack!

func main() { donald := Donald{} sayQuack(donald) bird := Bird{} sayQuack(bird) }

tweet tweet!

func main() { donald := Donald{} sayQuack(donald) bird := Bird{} sayQuack(bird) }

type Dog struct { } func (d Dog) Bark() { fmt.Println(“woof woof!”) }

see also http://bit.ly/1ER5zVs

func main() { dog := Dog{} sayQuack(dog) }

main.go:40: cannot use dog (type Dog) as type Duck in argument to sayQuack:!! Dog does not implement Duck (missing Quack method)

see also http://bit.ly/1ER5zVs

patterns are observed after the fact

see also http://bit.ly/1ER5zVs

system building is also a process of learning

and discovery

see also http://bit.ly/1ER5zVs

implementation package

interface packagesee also http://bit.ly/1ER5zVs

encourages precise interface definitions

see also http://bit.ly/1ER5zVs

F#ClojureErlang

Go

RustElm Idris

!?

Homoiconicity

…homoiconicity is a property of some programming languages in which the program structure is similar to its syntax, and therefore the program’s internal representation can be

inferred by reading the text’s layout…

code is data data is code

(let [x 1] (inc x))

see also http://bit.ly/1PpIrjS

(let [x 1] (inc x)) !

=> 2

see also http://bit.ly/1PpIrjS

list (1 2 3) vector [1 2 3]

see also http://bit.ly/1PpIrjS

(let [x 1] (inc x)) !

list

see also http://bit.ly/1PpIrjS

(let [x 1] (inc x)) !

symbol

see also http://bit.ly/1PpIrjS

(let [x 1] (inc x)) !

vector

see also http://bit.ly/1PpIrjS

(let [x 1] (inc x)) !

list

see also http://bit.ly/1PpIrjS

form : code as data structure

see also http://bit.ly/1PpIrjS

code data

quote

eval

see also http://bit.ly/1PpIrjS

quote

(+ 1 2) => 3

see also http://bit.ly/1PpIrjS

quote

(+ 1 2) => 3 (quote (+ 1 2)) => (+ 1 2)

see also http://bit.ly/1PpIrjS

quote

(+ 1 2) => 3 (quote (+ 1 2)) => (+ 1 2) ‘(+ 1 2) => (+ 1 2)see also http://bit.ly/1PpIrjS

eval

‘(+ 1 2) => (+ 1 2) (eval ‘(+ 1 2)) => 3

see also http://bit.ly/1PpIrjS

macros

(defmacro assert-equals [actual expected] ‘(let [actual-val# ~actual] (when-not (= actual-val# ~expected) (throw (AssertionError. (str “FAIL in “ ‘~actual “\n expected: “ ‘~expected “\n actual: “ actual-val#))))))

see also http://bit.ly/1PpIrjS

(assert-equals (inc 1) 2) ; => nil (assert-equals (inc 1) (+ 0 1)) ; => AssertionError FAIL in (inc 1) ; expected: (+ 0 1) ; actual: 2

see also http://bit.ly/1PpIrjS

(assert-equals (inc 1) 2) ; => nil (assert-equals (inc 1) (+ 0 1)) ; => AssertionError FAIL in (inc 1) ; expected: (+ 0 1) ; actual: 2

see also http://bit.ly/1PpIrjS

(assert-equals (inc 1) 2) ; => nil (assert-equals (inc 1) (+ 0 1)) ; => AssertionError FAIL in (inc 1) ; expected: (+ 0 1) ; actual: 2

see also http://bit.ly/1PpIrjS

huh?? where? what? how?

(defmacro assert-equals [actual expected] ‘(let [actual-val# ~actual] (when-not (= actual-val# ~expected) (throw (AssertionError. (str “FAIL in “ ‘~actual “\n expected: “ ‘~expected “\n actual: “ actual-val#))))))

(assert-equals (inc 1) (+ 0 1))

see also http://bit.ly/1PpIrjS

(defmacro assert-equals [actual expected] ‘(let [actual-val# ~actual] (when-not (= actual-val# ~expected) (throw (AssertionError. (str “FAIL in “ ‘~actual “\n expected: “ ‘~expected “\n actual: “ actual-val#))))))

(assert-equals (inc 1) (+ 0 1))

see also http://bit.ly/1PpIrjS

(defmacro assert-equals [actual expected] ‘(let [actual-val# ~actual] (when-not (= actual-val# ~expected) (throw (AssertionError. (str “FAIL in “ ‘~actual “\n expected: “ ‘~expected “\n actual: “ actual-val#))))))

(assert-equals (inc 1) (+ 0 1))

see also http://bit.ly/1PpIrjS

see also http://bit.ly/1PpIrjS

(defmacro assert-equals [actual expected] ‘(let [actual-val# ~actual] (when-not (= actual-val# ~expected) (throw (AssertionError. (str “FAIL in “ ‘~actual “\n expected: “ ‘~expected “\n actual: “ actual-val#))))))

see also http://bit.ly/1PpIrjS

(defmacro assert-equals [actual expected] ‘(let [actual-val# ~actual] (when-not (= actual-val# ~expected) (throw (AssertionError. (str “FAIL in “ ‘~actual “\n expected: “ ‘~expected “\n actual: “ actual-val#))))))

‘(

expanded at compile time

see also http://bit.ly/1PpIrjS

see also http://bit.ly/1PpIrjS

(macroexpand '(assert-equals (inc 1) (+ 0 1))) ; => ; (let* [actual-value__16087__auto__ (inc 1)] ; (clojure.core/when-not ; (clojure.core/= actual-value__16087__auto__ (+ 0 1)) ; (throw (java.lang.AssertionError. ; (clojure.core/str ; "FAIL in " (quote (inc 1)) ; "\nexpected: " (quote (+ 0 1)) ; "\n actual: " actual-value__16087__auto__)))))

F#ClojureErlang

Go

RustElm Idris

GC is great

runtime cost

ownership

see also http://bit.ly/1F6WBVD

memory safety without GC

see also http://bit.ly/1F6WBVD

ZERO runtime cost

see also http://bit.ly/1F6WBVD

safety + speed

see also http://bit.ly/1F6WBVD

fn foo() { // v has ownership of the vector let v = vec![1, 2, 3]; // mutable binding let mut v2 = vec![]; } // vector is deallocated at the // end of scope, // this happens deterministically

see also http://bit.ly/1F6WBVD

immutable by default

see also http://bit.ly/1F6WBVD

// take ownership let v = vec![1, 2, 3];

see also http://bit.ly/1F6WBVD

// take ownership let v = vec![1, 2, 3]; !// moved ownership to v2 let v2 = v;

see also http://bit.ly/1F6WBVD

// take ownership let v = vec![1, 2, 3]; !// moved ownership to v2 let v2 = v; !println!("v[0] is {}", v[0]); // error: use of moved value: `v` // println!("v[0] is {}", v[0]); // ^

see also http://bit.ly/1F6WBVD

fn take(v : Vec<i32>) { // ownership of vector transferred // to v in this scope }

see also http://bit.ly/1F6WBVD

// take ownership let v = vec![1, 2, 3]; !// moved ownership take(v);

see also http://bit.ly/1F6WBVD

// take ownership let v = vec![1, 2, 3]; !// moved ownership take(v); !println!("v[0] is {}", v[0]); // error: use of moved value: `v` // println!("v[0] is {}", v[0]); // ^

see also http://bit.ly/1F6WBVD

see also http://bit.ly/1F6WBVD

see also http://bit.ly/1F6WBVD

let me buy your book

see also http://bit.ly/1F6WBVD

sure thing!

see also http://bit.ly/1F6WBVD

thanks

see also http://bit.ly/1F6WBVD

BURN!!! !>:D

see also http://bit.ly/1F6WBVD

but I still need it..!

:’(

borrowing

see also http://bit.ly/1F6WBVD

// note we're taking a reference, // &Vec<i32>, instead of Vec<i32> fn take(v : &Vec<i32>) { // no need to deallocate the vector // after we go out of scope here }

see also http://bit.ly/1F6WBVD

// take ownership let v = vec![1, 2, 3]; !// notice we're passing a reference, // &v, instead of v take(&v); // borrow ownership !println!("v[0] is {}", v[0]); // v[0] is 1

see also http://bit.ly/1F6WBVD

see also http://bit.ly/1F6WBVD

let me borrow your

book

see also http://bit.ly/1F6WBVD

sure thing!

see also http://bit.ly/1F6WBVD

thanks

see also http://bit.ly/1F6WBVD

I’m done, here you go

see also http://bit.ly/1F6WBVD

thanks

see also http://bit.ly/1F6WBVD

immutable by default

fn take(v : &Vec<i32>) { v.push(5); } !let v = vec![]; take(&v); // cannot borrow immutable borrowed // content `*v` as mutable // v.push(5); // ^

see also http://bit.ly/1F6WBVD

fn take(v : &mut Vec<i32>) { v.push(5); } !let mut v = vec![]; take(&mut v); !println!("v[0] is {}", v[0]); // v[0] is 5

see also http://bit.ly/1F6WBVD

borrowing rules

see also http://bit.ly/1F6WBVD

see also http://bit.ly/1F6WBVD

Rule 1.!!

the borrower’s scope must not outlast the owner

see also http://bit.ly/1F6WBVD

Rule 2.!!

one of the following, but not both:! 2.1 0 or more refs to a resource! 2.2 exactly 1 mutable ref

see also http://bit.ly/1F6WBVD

data race

There is a ‘data race’ when two or more pointers access the same memory location at the same time, where at least one of them is writing, and

the operations are not synchronised.

see also http://bit.ly/1F6WBVD

data race

a. two or more pointers to the same resource!b. at least one is writing!c. operations are not synchronised

see also http://bit.ly/1F6WBVD

Data Race Conditions!a. two or more pointers to the same resource!b. at least one is writing!c. operations are not synchronised

Borrowing Rules!one of the following, but not both:!

! 2.1 0 or more refs to a resource! ! 2.2 exactly 1 mutable ref

see also http://bit.ly/1F6WBVD

Data Race Conditions!a. two or more pointers to the same resource!b. at least one is writing!c. operations are not synchronised

Borrowing Rules!one of the following, but not both:!

! 2.1 0 or more refs to a resource! ! 2.2 exactly 1 mutable ref

see also http://bit.ly/1F6WBVD

F#ClojureErlang

Go

RustElm Idris

!!!

seen generics?aka parametric polymorphism

List<T>

List<T>List<int> List<Cat>

List<string>

what if…

types that depend on arbitrary values?

Vect n avector of n elements of type a

zipWith : (a -> b -> c) -> Vect n a -> Vect n b -> Vect n c

zipWith f [] [] = [] zipWith f (x :: xs) (y :: ys) = f x y :: zipWith f xs ys

Type Driven Development

making invalid state UNREPRESENTABLE

see also https://vimeo.com/123606435

F#ClojureErlang

Go

RustElm Idris

Functional Reactive Programming

Value over Time

Time

Value

Signals

Move Up

Move Down

private var arrowKeyUp:Bool; private var arrowKeyDown:Bool; !private var platform1:Platform; private var platform2:Platform; private var ball:Ball;

function keyDown(event:KeyboardEvent):Void { if (currentGameState == Paused && event.keyCode == 32) { setGameState(Playing); } else if (event.keyCode == 38) { ! ! arrowKeyUp = true;! }else if (event.keyCode == 40) { ! ! arrowKeyDown = true;! } }

function keyUp(event:KeyboardEvent):Void { if (event.keyCode == 38) { ! ! arrowKeyUp = false;! } else if (event.keyCode == 40) { ! ! arrowKeyDown = false;! } }

function everyFrame(event:Event):Void { if(currentGameState == Playing){ if (arrowKeyUp) { platform1.y -= platformSpeed; } if (arrowKeyDown) { platform1.y += platformSpeed; } if (platform1.y < 5) platform1.y = 5; if (platform1.y > 395) platform1.y = 395; } }

function everyFrame(event:Event):Void { if(currentGameState == Playing){ if (arrowKeyUp) { platform1.y -= platformSpeed; } if (arrowKeyDown) { platform1.y += platformSpeed; } if (platform1.y < 5) !! ! ! platform1.y = 5;!! ! if (platform1.y > 395) !! ! ! platform1.y = 395;! } }

source files

state changes

source files execution

source files execution

mental model

input state new state behaviour

{ x; y } { x; y-speed }

{ x; y } { x; y+speed }

timer { x; y } { x; y } draw platform

… … … …

transformation

let y = f(x)

Imperative Functional

x.f()

mutation

transformations simplify problem

decomposition

Move Up

Move Down

type alias Platform = {x:Int, y:Int} defaultPlatform = {x=5, y=0} !delta = Time.fps 20 input = Signal.sampleOn delta Keyboard.arrows !cap x = max 5 <| min x 395 !p1 : Signal Platform p1 = foldp (\{x, y} s -> {s | y <- cap <| s.y + 5*y}) defaultPlatform input

type alias Platform = {x:Int, y:Int}!defaultPlatform = {x=5, y=0} !delta = Time.fps 20 input = Signal.sampleOn delta Keyboard.arrows !cap x = max 5 <| min x 395 !p1 : Signal Platform p1 = foldp (\{x, y} s -> {s | y <- cap <| s.y + 5*y}) defaultPlatform input

type alias Platform = {x:Int, y:Int} defaultPlatform = {x=5, y=0} !delta = Time.fps 20 input = Signal.sampleOn delta Keyboard.arrows !cap x = max 5 <| min x 395 !p1 : Signal Platform p1 = foldp (\{x, y} s -> {s | y <- cap <| s.y + 5*y}) defaultPlatform input

Keyboard.arrowsUP { x=0, y=1 } DOWN { x=0, y=-1 } LEFT { x=-1, y=0 } RIGHT { x=1, y=0 }

type alias Platform = {x:Int, y:Int} defaultPlatform = {x=5, y=0} !delta = Time.fps 20 input = Signal.sampleOn delta Keyboard.arrows !cap x = max 5 <| min x 395 !p1 : Signal Platform!p1 = foldp (\{x, y} s -> {s | y <- cap <| s.y + 5*y}) defaultPlatform input

type alias Platform = {x:Int, y:Int} defaultPlatform = {x=5, y=0} !delta = Time.fps 20 input = Signal.sampleOn delta Keyboard.arrows !cap x = max 5 <| min x 395 !p1 : Signal Platform p1 = foldp (\{x, y} s -> {s | y <- cap <| s.y + 5*y}) defaultPlatform input

type alias Platform = {x:Int, y:Int} defaultPlatform = {x=5, y=0} !delta = Time.fps 20 input = Signal.sampleOn delta Keyboard.arrows !cap x = max 5 <| min x 395 !p1 : Signal Platform p1 = foldp (\{x, y} s -> {s | y <- cap <| s.y + 5*y}) defaultPlatform input

type alias Platform = {x:Int, y:Int} defaultPlatform = {x=5, y=0} !delta = Time.fps 20 input = Signal.sampleOn delta Keyboard.arrows !cap x = max 5 <| min x 395 !p1 : Signal Platform p1 = foldp (\{x, y} s -> {s | y <- cap <| s.y + 5*y}) defaultPlatform input

see also http://oreil.ly/1i5CyhO

“I thought of objects being like biological cells and/or

individual computers on a network, only able to

communicate with messages.”

- Alan Kay

“OOP to me means only messaging, local retention and protection and hiding of state-

process, and extreme late-binding of all things.”

- Alan Kay

F#ClojureErlang

Go

RustElm Idris

!?

actor model

actor

state mailbox

actors share nothing

actor

state mailboxactor

actor

state mailboxactor

processing!storage!

communication

loop (Map) ->! receive! {get, Key, Pid} ->! Pid ! maps:get(Key, Map, not_found),! loop(Map);! {set, Key, Value} ->! loop(maps:put(Key, Value, Map))! end.

loop (Map) ->! receive! {get, Key, Pid} ->! Pid ! maps:get(Key, Map, not_found),! loop(Map);! {set, Key, Value} ->! loop(maps:put(Key, Value, Map))! end.

loop (Map) ->! receive! {get, Key, Pid} ->! Pid ! maps:get(Key, Map, not_found),! loop(Map);! {set, Key, Value} ->! loop(maps:put(Key, Value, Map))! end.

loop (Map) ->! receive! {get, Key, Pid} ->! Pid ! maps:get(Key, Map, not_found),! loop(Map);! {set, Key, Value} ->! loop(maps:put(Key, Value, Map))! end.

client (N, Pid) ->! Pid ! {set, N, N},! Pid ! {get, N, self()},! receive! not_found -> io:format(“~p :-(~n”, [N]);! N -> io:format(“~p :-)~n”, [N]);! _ -> io:format(“~p …~n”, [N])! end.

client (N, Pid) ->! Pid ! {set, N, N},! Pid ! {get, N, self()},! receive! not_found -> io:format(“~p :-(~n”, [N]);! N -> io:format(“~p :-)~n”, [N]);! _ -> io:format(“~p …~n”, [N])! end.

client (N, Pid) ->! Pid ! {set, N, N},! Pid ! {get, N, self()},! receive! not_found -> io:format(“~p :-(~n”, [N]);! N -> io:format(“~p :-)~n”, [N]);! _ -> io:format(“~p …~n”, [N])! end.

start(N) ->! Kvs = spawn(mod, loop, [#{}]),! [spawn(mod, client, [X, Kvs]) ! || X <- lists:seq(1,N)].

actors are cheap

no locks!

need state?!talk to the actor!

location transparency

makes you !THINK !

about !distributed systems

messaging promotes failure thinking

Distributed

Computing

Network is reliable!Latency is zero!

Bandwidth is infinite!Network is secure!

Topology doesn't change!There is one administrator!

Transport cost is zero!The network is homogeneous

8 fallacies of distributed computing

supervise & restart

F#ClojureErlang

Go

RustElm Idris

10,000 hours to be good at something

see also http://bit.ly/1KN7SLq

10,000 hours to be good at something

see also http://bit.ly/1KN7SLq

10,000 hours to reach top of an ultra-

competitive field

see also http://bit.ly/1KN7SLq

the first 20 hours - how to learn anything

see also http://bit.ly/1KN7SLq

Practice Time

How

goo

d yo

u ar

e

see also http://bit.ly/1KN7SLq

1.Deconstruct the skill

see also http://bit.ly/1KN7SLq

1.Deconstruct the skill!2.Learn enough to self-correct

see also http://bit.ly/1KN7SLq

1.Deconstruct the skill!2.Learn enough to self-correct!3.Remove practice barriers

see also http://bit.ly/1KN7SLq

1.Deconstruct the skill!2.Learn enough to self-correct!3.Remove practice barriers!4.Practice at least 20 hrs

see also http://bit.ly/1KN7SLq

learn a new paradigm!not a new syntax

see also http://bit.ly/1IzXVSo

logic programming

stack-oriented programming

array programming

“A language that doesn't affect the way you think

about programming, is not worth knowing.”

- Alan Perlis

see also http://bit.ly/1IzXVSo

see also http://bit.ly/1IzXVSo

“Learning is an act of creation itself, because something happens in you that wasn't

there before.”

- Alan Kay

@theburningmonktheburningmonk.comgithub.com/theburningmonk

top related