+ All Categories
Home > Documents > Thursday, 3 July 14 - erlang-factory.com€¦ · Thursday, 3 July 14. We Have A Problem • We are...

Thursday, 3 July 14 - erlang-factory.com€¦ · Thursday, 3 July 14. We Have A Problem • We are...

Date post: 21-Apr-2020
Category:
Upload: others
View: 2 times
Download: 0 times
Share this document with a friend
93
Thursday, 3 July 14
Transcript

Thursday, 3 July 14

Catalyze Change

José Valim @josevalim

Dave Thomas @pragdave

2

Thursday, 3 July 14

We Have A Problem

• We are sitting on the solution to many of today's problems

• We've had these solutions for 15 years

• Yet we are still marginal

3

Thursday, 3 July 14

Why?

4

Thursday, 3 July 14

Dear Abbey…5

Thursday, 3 July 14

I keep trying to apply Elixir/Erlang to problems I have, and I keep running up against issues with the terrible state of the ecosystem. Whatever the Erlang devs have been up to for the last 25 years, it certainly wasn't focusing on being a citizen of the modern internet.

I've killed many, many hours deciphering bad documentation and fighting bugs in XML and HTTP libraries over the past several weeks. Most recently I thought I had an idea which would be a perfect application of Elixir/Erlang, and then discovered that its sole IMAP client library is moribund and considered unusable by the one person I could find who has tried it.

Now, obviously, "the libraries suck" is a bad argument against a language - Ruby was in just as bad a state back in 2001 when I came to it. But there were compelling reasons to want to change that situation. In the case of Ruby, the reason was "it's a joy to code in".

As I understand it, the compelling reason for Erlang is that "it has a great VM for concurrent/distributed development".

But here's where I run into a problem. 5 years ago, that argument made a ton of sense. But now Clojure is a thing, and Go is a thing. Scala too, for that matter. Clojure and Scala have the full Java ecosystem behind them. Go can call directly into C code, so it has the whole C/C++ ecosystem to draw from.

None of them have Erlang's semantic quirks, like its obsession with arity. And all of them have Actor/CSP/Pi Calculus concurrency abstractions baked-in, just like Erlang.

Given all this, it seems like the sole reason to invest time into Elixir over some of these other languages is on the faith that the VM is simply that much better than the JVM, or the Go runtime.

At this point, my intuition is screaming at me to ditch the Erlang VM and focus my concurrent language energy on Clojure and/or Go. I keep worrying that I'll fight my way through the ecosystem issues, only to find myself with a bunch of code that runs on a VM that isn't materially better than the JVM, and can't be instrumented and tuned the way the JVM can.

6

Thursday, 3 July 14

I keep trying to apply Elixir/Erlang to problems I have, and I keep running up against issues with the terrible state of the ecosystem. Whatever the Erlang devs have been up to for the last 25 years, it certainly wasn't focusing on being a citizen of the modern internet.

I've killed many, many hours deciphering bad documentation and fighting bugs in XML and HTTP libraries over the past several weeks. Most recently I thought I had an idea which would be a perfect application of Elixir/Erlang, and then discovered that its sole IMAP client library is moribund and considered unusable by the one person I could find who has tried it.

Now, obviously, "the libraries suck" is a bad argument against a language - Ruby was in just as bad a state back in 2001 when I came to it. But there were compelling reasons to want to change that situation. In the case of Ruby, the reason was "it's a joy to code in".

As I understand it, the compelling reason for Erlang is that "it has a great VM for concurrent/distributed development".

But here's where I run into a problem. 5 years ago, that argument made a ton of sense. But now Clojure is a thing, and Go is a thing. Scala too, for that matter. Clojure and Scala have the full Java ecosystem behind them. Go can call directly into C code, so it has the whole C/C++ ecosystem to draw from.

None of them have Erlang's semantic quirks, like its obsession with arity. And all of them have Actor/CSP/Pi Calculus concurrency abstractions baked-in, just like Erlang.

Given all this, it seems like the sole reason to invest time into Elixir over some of these other languages is on the faith that the VM is simply that much better than the JVM, or the Go runtime.

At this point, my intuition is screaming at me to ditch the Erlang VM and focus my concurrent language energy on Clojure and/or Go. I keep worrying that I'll fight my way through the ecosystem issues, only to find myself with a bunch of code that runs on a VM that isn't materially better than the JVM, and can't be instrumented and tuned the way the JVM can.

6

Thursday, 3 July 14

Not a Random Rant

• We hear it a lot

• From well-known, knowledgeable people

7

Thursday, 3 July 14

We Need to Reconcile

we are sitting on the solution to many of today's problems

"ditch the Erlang VM and focus my concurrent language

energy on Clojure and/or Go”

vs.

8

Thursday, 3 July 14

Why Do We Care?

• We're happy

• We have what we need

• It works for us

• Someone else's problem

9

Thursday, 3 July 14

But We Should Care

• For the good of ourselves

• For the long-term survival of our culture.

• More conferences, more companies, more jobs, more clever ideas…

• For the good of world!

10

Thursday, 3 July 14

We’re Better

• We have the best VM and the best language

• So we don't have to worry about the surface features.

11

Thursday, 3 July 14

But the barriers to entry are too high

12

Thursday, 3 July 14

Activation EnergyEx

tern

al E

nerg

y

Energy needed to get started

13

Thursday, 3 July 14

Activation EnergyEx

tern

al E

nerg

y

Energy needed to get started

13

Thursday, 3 July 14

Activation EnergyEx

tern

al E

nerg

y

Gain in benefit

13

Thursday, 3 July 14

Hmmm… Erlang looks interesting

14

Thursday, 3 July 14

This is harder than I thought

15

Thursday, 3 July 14

I hate feeling stupid

16

Thursday, 3 July 14

http://us.cdn281.fansshare.com/photos/keanureeves/keanu-reeves-wallpaper-1469967791.jpg

http://images2.fanpop.com/image/photos/9200000/Keanu-Reeves-keanu-reeves-9231566-1280-1024.jpghttp://wallpaperhdfree.com/wp-content/uploads/2013/03/Angry-Keanu-Reeves.jpg

http://halfagiraffe.tv/wp-content/uploads/2010/10/KeanuReeves1.jpghttp://us.cdn200.fansshare.com/photo/keanureeves/keanu-reeves-83926830.jpg

http://wallpaperhdfree.com/wp-content/uploads/2013/03/Keanu-Reeves-Best-2013-Wallpaper.jpg

I’m happy as I was

17

Thursday, 3 July 14

And that’s why the Matrixis written

in Java

18

Thursday, 3 July 14

Lower the BarrierEx

tern

al E

nerg

y

19

Thursday, 3 July 14

Catalyst Reduces InputEx

tern

al E

nerg

y

20

Thursday, 3 July 14

You Are The Catalyst

21

Thursday, 3 July 14

So Let’s Put On our

Outsider Hats

22

Thursday, 3 July 14

23

Thursday, 3 July 14

create erlang application

23

Thursday, 3 July 14

24

Thursday, 3 July 14

24

Thursday, 3 July 14

25

Thursday, 3 July 14

25

Thursday, 3 July 14

26

Thursday, 3 July 14

26

Thursday, 3 July 14

27

Thursday, 3 July 14

28

Thursday, 3 July 14

28

Thursday, 3 July 14

29

Thursday, 3 July 14

29

Thursday, 3 July 14

$ git clone git://github.com/rebar/rebar.gitCloning into 'rebar'...Resolving deltas: 100% (3633/3633), done.$ cd rebar$ ./bootstrap Recompile: src/rebarRecompile: src/rebar_abnfc_compilerRecompile: src/rebar_app_utilsRecompile: src/rebar_appups. . .Recompile: src/rebar_xref==> rebar (compile)==> rebar (escriptize)Congratulations! You now have a self-contained script called "rebar" in your current working directory. Place this script anywhere in your path and you can use rebar to build OTP-compliant apps.$

30

Thursday, 3 July 14

$ ./rebar create-app app-id=my-app==> rebar (create-app)Writing src/myapp.app.srcWriting src/myapp_app.erlWriting src/myapp_sup.erl

31

Thursday, 3 July 14

$ ./rebar create-app app-id=my-app==> rebar (create-app)Writing src/myapp.app.srcWriting src/myapp_app.erlWriting src/myapp_sup.erl

31

$ cd my-app No such file or directory: my-app

Thursday, 3 July 14

$ ./rebar create-app app-id=my-app==> rebar (create-app)Writing src/myapp.app.srcWriting src/myapp_app.erlWriting src/myapp_sup.erl

31

$ cd my-app No such file or directory: my-app

$ cd src $ lsmyapp.app.src! ! ! ! rebar_file_utils.erlmyapp_app.erl! ! ! ! rebar_getopt.erlmyapp_sup.erl! ! ! !rebar_lfe_compiler.erlrebar.erl!! ! ! rebar_log.erlrebar_abnfc_compiler.erl! ! rebar_mustache.erlrebar_app_utils.erl!! !! rebar_neotoma_compiler.erlrebar_appups.erl! ! ! rebar_otp_app.erl

Thursday, 3 July 14

$ ./rebar create-app app-id=my_app==> MyApp (create-app)Writing src/my_app.app.srcWriting src/my_app_app.erlWriting src/my_app_sup.erl

$ ./rebar compile==> MyApp (compile)Compiled src/my_app_app.erlCompiled src/my_app_sup.erl

$ erl -pa ebin -s my_appErlang/OTP 17 [RELEASE CANDIDATE 1] [erts-6.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe][kernel-poll:false]

{"init terminating in do_boot",{undef,[{my_app,start,[],[]},{init,start_it,1,[]},{init,start_em,1,[]}]}}

Crash dump was written to: erl_crash.dumpinit terminating in do_boot ()

32

Thursday, 3 July 14

$ erl -pa ebin -s my_app. . .{"init terminating in do_boot",{undef,[{my_app,start,[],[]},{init,start_it,1,[]},{init,start_em,1,[]}]}}

Crash dump was written to: erl_crash.dumpinit terminating in do_boot ()

• Why are errors displayed as Erlang terms?

• What is the error

• (remember, I’m new to Erlang)

• What should I do next?

33

Thursday, 3 July 14

Erlang user

Exte

rnal

Ene

rgy

Me

34

Thursday, 3 July 14

Erlang user

Exte

rnal

Ene

rgy

Me

34

Thursday, 3 July 14

Erlang user

Exte

rnal

Ene

rgy

Me Me: Happy user of something else

34

Thursday, 3 July 14

This is just the mechanics

Thinking in Erlang is hard, too…- Pattern matching- Recursion- Higher Order Functions- Anonymous functions- Expression-based conditionals (case/if)- Single Assignment- Immutability (and the lack for while and for loops)- Not using objects

(Fred Herbert 2/13/14)

35

Thursday, 3 July 14

Nested Data Structures

36

Thursday, 3 July 14

#{ RoomId => #room{ users=#{ UserId => [Codes] } }}.

37

Thursday, 3 July 14

User joins a room

Rooms#{RoomId}#room.users#{UserId} += [NewCode]

38

Thursday, 3 July 14

join_room(#{RoomId := Room} = Rooms, RoomId, UserId, NewCode) -> Rooms#{RoomId := join_room(Room, UserId, NewCode)}.

join_room(#room{users=Users} = Room, UserId, NewCode) -> Room#room{users=join_room(Users, UserId, NewCode)};

join_room(#{UserId := Codes} = Users, UserId, NewCode) -> Users#{UserId := join_room(Codes, NewCode)}.

join_room(Codes, NewCode) -> [NewCode|Codes].

User joins a room

39

Thursday, 3 July 14

Is this the correct design?

40

Thursday, 3 July 14

Clojure

• get_in

• assoc_in

• update_in

41

Thursday, 3 July 14

In Erlang

update_in(Rooms, [RoomId, #room.users, UserId], fun(Codes) -> [NewCode|Codes] end)

42

Thursday, 3 July 14

Haskell Lenses

https://github.com/jlouis/erl-lenses

43

Thursday, 3 July 14

OTP

44

Thursday, 3 July 14

45

I need to write an application

Thursday, 3 July 14

45

I need to write an applicationOT

P!

Thursday, 3 July 14

46

I need to handle events

Thursday, 3 July 14

46

I need to handle eventsOT

P!

Thursday, 3 July 14

47

I need to do what is best for my customer

Thursday, 3 July 14

47

I need to do what is best for my customerOT

P!

Thursday, 3 July 14

48

I need to store state

Thursday, 3 July 14

48

I need to store stateOT

P!

Thursday, 3 July 14

49

I need world peace

Thursday, 3 July 14

49

I need world peace

OTP!

Thursday, 3 July 14

50

OTP!

Thursday, 3 July 14

50

OTP!

Thursday, 3 July 14

50

OTP!

Thursday, 3 July 14

OTP is Cool, But…

• High ceremony

• Steep learning curve

• Much duplication

• cut and paste code

• API vs. handler

51

Thursday, 3 July 14

Simple Problem

• Need to parse a configuration file and access its data throughout the application life cycle

52

Thursday, 3 July 14

-module(config).

-behaviour(gen_server).

%% API-export([start_link/0]).

%% gen_server callbacks-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

-define(SERVER, ?MODULE).

start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

init([]) -> {ok, parse_config()}.

handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}.

handle_cast(_Msg, State) -> {noreply, State}.

handle_info(_Info, State) -> {noreply, State}.

terminate(_Reason, _State) -> ok.

code_change(_OldVsn, State, _Extra) -> {ok, State}.

Config Server

53

Thursday, 3 July 14

(def config (agent (parse-config)))

(await (send config ...))

@config

Config using Agents

54

Thursday, 3 July 14

Futures

55

Thursday, 3 July 14

Futures

55

Thursday, 3 July 14

(new Future(getUsers)) .onSuccess(...) .onFailure(...)

56

Thursday, 3 July 14

Erlang mismatch

• Callback soup

• Conflated error handling

57

Thursday, 3 July 14

They want to start a computation, asynchronously,and later read its value back

58

Thursday, 3 July 14

task = new Task(action)// some computationtask.Wait()

.NET Task Parallel Library

59

Thursday, 3 July 14

From = self(),Pid = spawn_link(fun() -> From ! {self(), Action()} end),

% some computation

receive {Pid,Res} -> Resend;

In Erlang

60

Thursday, 3 July 14

task(Action) -> From = self(), Ref = erlang:make_ref(), spawn_link(fun() -> case (catch Action()) of {'EXIT', Why} -> From ! {Ref, {error, Why}}; Reply -> From ! {Ref, {ok, Reply}} end end), Ref.

61

Thursday, 3 July 14

wait(Ref) when is_reference(Ref) -> receive {Ref, {error, Why}} -> error(Why); {Ref, {ok, Reply}} -> Reply end.

62

Thursday, 3 July 14

We can implement tasksin about 15 LOC

63

Thursday, 3 July 14

Can we expect someone with 2 weeks of Erlang experience to

write this code?

64

Thursday, 3 July 14

The Erlang Gap

65

Thursday, 3 July 14

Lower The Barriers

66

Thursday, 3 July 14

Lower The Barriers

• My First Erlang Program

• should take 10 minutes from Erlang install to success

• recommended tutorials, videos, and downloads to point the way

67

Thursday, 3 July 14

Lower The Barriers

• Error messages should be aimed at humans, not file:consult/1

• {error, enoent} is cool, but which file?

• (Maybe include lager by default?)

68

Thursday, 3 July 14

Lower The Barriers

• Provide modern abstractions

• such as Clojure’s get_in, assoc_in, update_in

• built-in implementations of things such as agents, tasks, (reactive APIs, etc…)

69

Thursday, 3 July 14

Lower The Barriers

70

Think like a newcomer

Thursday, 3 July 14

Lower The Barriers

71

Thursday, 3 July 14

Lower The Barriers

Share the Love

71

Thursday, 3 July 14


Recommended