Slide 1

Slide 1 text

LevviBraun IvanRublev ivanrublev.me How Elixir helps Erlang for better Engineering Some differences between languages running on the same platform 2020

Slide 2

Slide 2 text

OTP / BEAM VM • Ericsson - 1990 / 1998 / 2006 • Actor Model • Lightweight isolated processes • Asynchronous messages • Erlang • Process links / Supervisors • Distributed nodes • Schedulers / Preemptive multitasking • Swiss army knife platform for building messaging systems Elixir ?

Slide 3

Slide 3 text

Erlang • https://github.com/IvanRublev/ year_progress_bot

Slide 4

Slide 4 text

Syntax send_message(Id, ProgressDate, Pause) -> R = telegram:send_message(Id, ProgressDate), lager:debug("Send message to chat_id: ~p, pause: ~p", [Id, Pause]), util:pause(Pause), R. def send_message(id, progress_date, pause) do r = Telegram.send_message(id, progress_date) Logger.debug("Send message to chat_id: #{id}, pause: #{pause}") :util.pause(pause) r end 1> Atom = atom. 2> [atom, Atom]. [atom,atom] 1> atom = :atom 2> [:atom, atom] [:atom, :atom]

Slide 5

Slide 5 text

Data Structures #{"dog" => "winston", "fish" => "mrs.blub"}. %{"dog" => "winston", "fish" => "mrs.blub"} [{size,2697}, {type,regular}]. -module(records). -compile(export_all). -record(robot, {name, type=industrial}). 1> A=#robot{}. 2> A#robot.type. industrial defmodule Robot do defstruct name: nil, type: :industrial end 1> a=%Robot{} 2> a.type :industrial [size: 2697, type: :regular]

Slide 6

Slide 6 text

Tuples [ {year_progress_bot, [ {host, "${HOST}"}, {port, ${PORT}}, ]}, {sumo_db, [ {wpool_opts, [{overrun_warning, 100}]}, {log_queries, true} ]} ]. sys.config.src config.exs config :year_progress_bot, host: "${HOST}", port: ${PORT}, config :sumo_db, :wpool_opts, overrun_warning: 100 config :sumo_db, log_queries: true

Slide 7

Slide 7 text

Strings jiffy:encode({[ {<<"method">>, <<"sendMessage">>}, {<<"text">>, <<"""/utf8>>}, {<<"chat_id">>, ChatId} ]}). Jason.encode([ %{"method" => "sendMessage", "text" => """, "chat_id" => chat_id} ]) "hełło" [104, 101, 322, 322, 111] 'hełło' [104, 101, 322, 322, 111] List of Unicode code points / Charlist Binary string UTF-8 Latin1 (0-255) UTF-x

Slide 8

Slide 8 text

Tests -module(endpoint_tests). -include_lib("eunit/include/eunit.hrl"). start_test_() -> {foreach, fun() -> meck:new(db, [{stub_all, ok}]) end, fun(_) -> meck:unload(db) end, [fun should_record_chat_id_on_start/1, ...]}. should_record_chat_id_on_start(_) -> endpoint:init({}, #{}), ?_assert(meck:called(db, add_notified_chat, [123456, …])). ... -module(endpoint_tests_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib ("etest_http/include/etest_http.hrl"). suite() -> [{timetrap,{seconds,30}}]. init_per_suite(Config) -> {ok, _} = application:ensure_all_started(cowboy). end_per_suite(_Config) -> application:stop(cowboy). init_per_testcase(_TestCase, Config) -> meck:new(calendar, [unstick, passthrough]), Config. end_per_testcase(_TestCase, _Config) -> meck:unload(calendar). all() -> [should_reply_to_chat_id_received_on_start, ...].
 should_reply_to_chat_id_received_on_start(Config) -> Res = ?perform_post(...), ?assert_json_value(<<"chat_id">>, 1213141, Res). ... Common Tests EUnit Tests defmodule TwitterWallWeb.FeedLive.Test do use TwitterWallWeb.ConnCase, async: true import Mox setup_all do on_exit(fn -> # cleanup end) :ok end describe "GET / response should" do setup %{conn: conn} do stub_with(TwitterWall.Double, 
 TwitterWall.Stub) {:ok, conn: get(conn, "/")} end test "have status 200", %{conn: conn} do assert html_response(conn, 200) end ... end end ExUnit

Slide 9

Slide 9 text

Macros Enum.each(0..@prehandle, fn i -> def parse( <<_::binary-size(unquote(i)), ?\n, rest::binary>>, %{bc: bc, wc: wc, lc: lc, ns?: ns} ), do: parse(rest, acc!(unquote(i), bc, wc, lc + 1, ns)) def parse( <<_::binary-size(unquote(i)), ?\s, rest::binary>>, %{bc: bc, wc: wc, lc: lc, ns?: ns} ), do: parse(rest, acc!(unquote(i), bc, wc, lc, ns)) end) https://gist.github.com/am-kantox/afd52c2ee4c95ea25eff464e8692ac15#file-wc-ex-L57-L77 wc utility equivalent. 
 Specific functions generation, 6x times faster comparing to general recursion. -define(macro1(X, Y), {a, X, b, Y}). bar(X) -> ?macro1(a, b), ?macro1(X, 123) ---------------- bar(X) -> {a,a,b,b}, {a,X,b,123}. Function level Module level

Slide 10

Slide 10 text

Configuration defmodule AnApp.MixProject do use Mix.Project def project do [ app: :twitter_wall, version: "0.1." <> File.read!("BUILD.MD"), elixir: "~> 1.5”,
 ... ] end
 end Reading build version number from a file % Append build number to version number in config {ok, File} = file:open("BUILD",[read]), {ok, BuildStr} = file:read(File,1024), file:close(File), io:format("App build number is: ~s, REBAR_PROFILE is: ~s~n", [BuildStr, os:getenv("REBAR_PROFILE", "undef")]), {value, RelxTup, _} = lists:keytake(relx, 1, CONFIG), {relx, Relx} = RelxTup, {value, ReleaseTup, _} = lists:keytake(release, 1, Relx), {release, Release, Opts} = ReleaseTup, {AppName, Ver} = Release, VerUpd = Ver ++ BuildStr, ReleaseUpd = {AppName, VerUpd}, ReleaseTupUpd = {release, ReleaseUpd, Opts}, RelxUpd = lists:keystore(release, 1, Relx, ReleaseTupUpd), RelxTupUpd = {relx, RelxUpd}, CONFIG_UPD = lists:keystore(relx, 1, CONFIG, RelxTupUpd), CONFIG_UPD. rebar.config.script {erl_opts, [debug_info]}. {deps, [ {cowboy, "2.7.0"},
 ... ]}. {relx, [{release, {year_progress_bot, "0.1."}, [year_progress_bot, sasl]},
 ... }. rebar.config mix.exs

Slide 11

Slide 11 text

Documentation http://erlang.org/doc/search https://hexdocs.pm/elixir Generated using a bunch of templates, scripts, and Makefiles.
 
 https://github.com/erlang/otp/tree/maint/system/doc/top Generated with ExDoc from modules comment.
 That is used on hexdocs.pm

Slide 12

Slide 12 text

Elegant Elixir helps Erlang • Less brackets • UTF-8 Strings • Compact Tests • Code generation with Macros • Project configuration as a code

Slide 13

Slide 13 text

Links • https://t.me/yrpb_bot • https://elixir-lang.org/getting-started/binaries-strings-and- char-lists.html • https://adoptingerlang.org/docs/development/ hard_to_get_right/#handling-strings-in-erlang • https://chrispenner.ca/posts/wc • https://gist.github.com/am-kantox/ afd52c2ee4c95ea25eff464e8692ac15