00:00:16.600
before we get started I actually want to talk a little bit about what earling is uh so does anyone here has anyone here
00:00:21.720
written earling before few okay so some of this is going to be some of the topics we discussed
00:00:28.080
should be pretty straightforward to you for everyone else probably going to feel like programming 101 when I was getting
00:00:33.640
into Elixir trying to like think recursively in a functional language is really like difficult at first and I
00:00:39.040
felt like really stupid uh but once it clicks um it will kind of change the way you think about writing programs coming
00:00:44.719
from like an object oriented background and uh we can't talk about Elixir before talking about earling uh
00:00:50.840
so earling is a language that's been somewhat um obscure at least for me I come from a I have a computer science
00:00:56.520
degree but I never heard of earling or really touched it uh in college um but really they were kind of like
00:01:01.840
this they had this nugget of like Innovation for like the last 20 years and uh they've been largely ignored by
00:01:07.000
the programming community at large at least objectoriented programming community and uh earling was developed
00:01:12.960
by company uh Ericson to build like Telecom telecommunication systems and uh
00:01:18.560
it was it's really unique because in like 1986 when it was developed they had like a few set of requirements that even
00:01:25.479
languages today don't really follow uh they needed to build something that was uh kind of distributed uh at its heart
00:01:32.079
so you be able to run on a bunch of Telecom switches distributively uh something that was highly concurrent and
00:01:37.360
something that was highly fault tolerant and even a lot of languages today don't really hit the like Trifecta of those three requirements at least as their
00:01:43.960
focus uh you may say some languages are like fault tolerant because they're stable um but Elixir or but earling
00:01:50.200
actually has um mechanisms built in to like restart if something crashes and
00:01:55.320
they really focus on the fault tolerance uh so if you make a phone call today for example there's about 50% chance it's
00:02:00.520
running through an earling system uh so earling is like tried and true it's out there and just to prove its fault
00:02:06.000
tolerance you've never had a phone company call you it's like a joke uh your phone company never calls and says
00:02:11.920
hey tonight you can't make a phone call from 800 to 10 p.m. because we're going down for scheduled maintenance like you've never heard of that and uh we
00:02:18.840
half of our web services that we use have like downtime and scheduled maintenance uh so earling has mechanisms
00:02:24.440
built in to do like hot code uploading so like literally like zero downtime deploys where you can upgrade code live
00:02:29.840
production and go from one state to the next and um you can run programs distributively that have like no extra
00:02:35.720
Fan Fair about riding um jumping through hoops to run things distributedly you write code against one machine you can
00:02:40.879
run it on 50 and it all just works uh so let's get started with Elixir uh Elixir is if you're familiar
00:02:48.200
with closure how closure relates to Java uh Elixir relates to earling so Elixir
00:02:53.680
compiles to the earling virtual machine bite code and you can write Elixir call it from your earling code and we can
00:02:59.599
call call earling code from our Elixir code uh so Elixir isn't trying to reinvent the wheel it's trying to build
00:03:05.200
on top of all the Innovation that earling in the earling virtual machine has basically brought for the last 20
00:03:11.159
years and the reason why I really love Elixir is it brings uh some pretty
00:03:16.560
awesome features to the table like uh meta programming erling doesn't really have any great mechanism for like macers
00:03:21.959
or meta programming and as rubius I think all of us are here partially because we love meta programming so luir
00:03:28.560
focuses on that adds a polymorphic layer through protocols so we're not writing
00:03:34.840
objectoriented code but we don't have to throw away polymorphism in Elixir you're familiar with closures protocols that's
00:03:40.519
what Elixir protocols were inspired by and we'll touch on what protocols are this afternoon and
00:03:46.720
elixir also gives us a focus on like ease of use uh so a lot of us come from
00:03:52.079
rails we're at a rails conference and rails is all about being easy to use um having really nice features and llang I
00:03:58.560
think has a uh history of being a little bit difficult to get into because they were focusing on U more gadier problems historically
00:04:07.360
so a lot of the ramp up is much more difficult so earling or Elixir has a focus on um ramping up quickly and
00:04:13.000
getting U beginners started easily uh so for us to get started uh we
00:04:18.519
need to touch on touch a terminology and then we'll get into some code uh just so you know what I'm talking about uh the
00:04:25.160
term uh term is used all over the place and that when we say an Elixir term it basically means an element of any data
00:04:31.800
type in Elixir and you'll see that in documentation everywhere literal is just a value of a term uh when you hear the
00:04:39.320
term binary it's basically going to be a string of bits and this comes from
00:04:44.800
earling and uh when we think of binaries in Elixir uh it almost always is used to
00:04:49.840
store like a uh utf8 encoded string and uh we you use a term aity
00:04:55.919
which you may not be familiar with and that's the number of arguments a function accepts so if you understand those four or five
00:05:02.199
terms uh we should be pretty good as far as discussing the rest of the
00:05:07.680
concepts uh one thing you might like is everything is an expression which uh after I got into Ruby I had never been
00:05:14.360
familiar with that but once I basically got oned everything as an expression if I go to a language that doesn't abide by
00:05:20.800
this I kind of feel like I'm I'm not quite getting the power of it uh so here's an if condition in Elixir uh we
00:05:27.160
can store it as a result variable and it works like you would just expect in Ruby uh it has this uh do here which is
00:05:34.800
about the only difference if you were write this in Ruby uh some people uh take a look at Elixir and think it's just Ruby syntax on earling um don't be
00:05:42.319
fooled by that um it's like a small veneer that might look a little bit like Ruby but uh basically the internals
00:05:48.880
semantically are entirely different and my biggest complaint going between Ruby and elixir on a daily basis is I write
00:05:55.600
do in my Ruby code or I leave do off in my Elixir code and it's sucks other than
00:06:01.199
that it's uh it's pretty nice uh Elixir is an immutable language uh so we have
00:06:06.919
to change the way we write programs we can no longer um write objects that hide an abstract like mutable State we have
00:06:13.599
to uh write our programs in like a data transformation way and that's a very
00:06:19.120
difficult thing to get started with initially and hopefully we can kind of talk about that uh today it follows the
00:06:24.160
actor model of concurrency if you're familiar with that parentheses are optional just like Ruby so to callif
00:06:29.479
function as long as it doesn't introduce ambiguity it's going to be very similar to what you would do in Ruby and it has spawned a ton of debates just like in
00:06:36.599
Ruby already people hate that parentheses are optional but I love that they're
00:06:41.880
optional uh documentation is first class this is one of my favorite things you write your documentation in markdown so
00:06:47.840
you literally uh document your methods or your functions in markdown and then we can have access to them within I ex
00:06:54.199
so it's like if you had IRB up and you could just type a function and uh get the formatted markdown of that
00:06:59.599
documentation right in like a shell and it's amazing and we have coexistence with the
00:07:05.400
earling ecosystem which is huge so Elixir isn't trying to reinvent everything uh so we can call like uh an
00:07:13.199
Elixir function here uh we can call IOP puts it's like a ruby puts statement to print the standard out but if we want to
00:07:19.120
call earling we can call it um just like if you were like to chain a method off of a symol in Ruby so that colon IO is
00:07:26.199
referencing that means hey there's an earling module named I'm going to call the fight function on it uh so there's a
00:07:33.080
complete interoperability between earling and elixir and vice versa it's a little bit uglier syntax if you're
00:07:38.400
trying to call Elixir from earling you have to prefix it with an Elixir module um but calling it from earling from
00:07:45.199
elixer is super straightforward like I can call math. piy from the earling math module and I
00:07:51.440
get Pi question yeah why would you call
00:07:56.720
Elixir from earling if you so if I release a Elixir library that
00:08:03.919
does something awesome and an earling person wants to use it okay I guess pretty much for the same reason you would call earling from Elixir there's a
00:08:09.680
library out there that does what you want you can drop in your project and use
00:08:19.199
it awesome cool and uh before we hop into some uh
00:08:28.960
the first section here I want to talk a little bit about why I think Elixir is the future of my programming career as
00:08:34.880
much as I love Ruby um how many people do threading in their rails apps by a show
00:08:40.440
hands how many people do threading on MRI in the rails apps all right awesome at one person uh
00:08:47.360
so the concurrency story in Ruby in rails is really weak it can be done uh
00:08:52.640
but it's kind of like a uh Wild West and it doesn't work that well um for example we we do a lot of
00:09:00.320
like real time stuff when we build uh rails applications at work and we're
00:09:05.399
constantly having to shove stuff into a background job and then like pull the server if we're trying to hit a third party API because we can't keep a
00:09:11.240
connection open um in our rails process because it's going to clog the tubes basically so the way we get concurrency
00:09:17.720
in rails if we have like a quad core uh system we run like four processes of our rails app and that's the way we achieve
00:09:25.640
concurrency in Ruby just here
00:09:34.760
oops so as more and more cores get added to CPUs so there are like 50 core CPUs
00:09:40.120
on the horizon 100 core CPUs if 10 years from now we were celebrate rail's 20th birthday and we have 50 core CPUs that
00:09:46.720
are the norm my on my laptop I don't think we're going to all be standing up here saying well we just run 50 rails
00:09:52.680
processes to achieve concurrency so I think that's a problem and I think it's
00:09:57.800
inherent to rubies architecture um some people get by perfectly like that that's how we deploy
00:10:03.560
all of our rails apps and it works really well but it starts to fall down if you're trying to do anything highly concurrent if you're trying to trying to
00:10:10.399
do something um like parallelize some work it's almost impossible like we jump through all these hoops running like
00:10:16.000
sidekick or rescue workers to try to like coordinate them together to do some work together and that's because uh we
00:10:21.760
cannot properly do concurrency and Ruby in the ways we want to do it uh so getting into Elixir uh concurrency is
00:10:28.760
basically the heart of everything we do and it gets rid of threading uh because you can say well we'll just add really
00:10:34.040
proper threading in Ruby or we'll use J Ruby get proper threading uh that still isn't the best way to achieve
00:10:39.600
concurrency because you have to deal with like mutexes and locks you have shared mutable State it's really difficult to reason about and it's
00:10:44.800
really difficult to write programs around uh so writing in a functional way with a mutable State lets us write
00:10:50.079
programs uh that are safe and concurrent and it's really simple to reason about
00:10:55.440
and we'll see how message passing Works later and we use processes that aren't operating system processes but we can
00:11:00.519
run like a million of them on our machines so I can spin up a million uh Elixir processes and you couldn't spend
00:11:06.800
up a million threads on any operating system that I'm aware of and uh if anyone's familiar with like WhatsApp
00:11:12.680
that got up20 billion doll Fame recently uh they're running they were an earling app and they're running a million
00:11:19.040
concurrent connections per server to give you an idea of uh the language envy that I have coming from Ruby where like
00:11:25.639
you know we have like action controller live and rails but you go over 15 concurrent re crush you like destroy
00:11:31.279
your database pool of connections and um all these things give me um pause to
00:11:36.839
think about where we need to move as a rails Community to handle concurrency properly so who here is still working on
00:11:44.079
getting set up okay so uh I show hands who has
00:11:51.600
earling at least built and installed that's still working on getting set up so you're still building early no
00:11:58.519
it's you're good okay okay so I'm GNA get started um try
00:12:06.079
to pair with someone if they're working next to you um we're just this is pretty basic starting out um but hopefully by
00:12:11.880
the time you get into some real code examples you'll be able to type it in and be good to
00:12:27.880
go all right so uh Elixir has just a very small set of
00:12:33.920
types we have integer float atom uh when you hear adom you should think symbol in
00:12:39.480
Ruby it's almost synonymous uh with symbols we call them atoms in Elixir uh
00:12:45.480
we have a tupple a tupple is uh something that holds uh it's stored continuous continuously in memory you
00:12:51.560
can think of it almost like an array uh it's allocated continuously in memory and uh tupple comes from something that
00:12:58.199
stores like multiple items like quintuple multiple so it sounds a little odd but that's what tupple comes from
00:13:03.880
list is a link list and uh we went through a bit string before it's just a string of bits and a pit is a like
00:13:10.040
process ID so something you can almost think of them like threads but they're very lightweight and it's like elixir unit of concurrency we can run like a
00:13:16.360
million of them and from these small set of types we pretty much do all of our programming um there's some a few other
00:13:23.279
uh layers that Elixir Builds on top but uh we basically instead of writing objects that like hide State we write uh
00:13:31.440
functions to mutate some data structures so it's basically like data in data out from a very small set of types and you
00:13:37.920
end up constructing your programs around all these types uh so atoms are pretty self-explanatory uh just like Ruby you
00:13:45.079
open up IEX we can just say adom it's an atom there's some
00:13:52.800
build-in functions to type check so I can say is adom adom and it's true just
00:13:58.040
like Ruby uh and it's just like Ruby and if you have user provid an input and you want to call two atom on it you can fill
00:14:05.040
up the atom table there's only a set amount of atoms it's a massive number but it's just like in Ruby do you ever
00:14:10.440
call two sim on user provided input you're potentially at risk for memory over overflow because Ruby doesn't
00:14:15.519
garbage collect the symbol table same thing applies to Elixir so be careful when trying to take user input as an
00:14:21.480
atom or as a string and then cast as an atom is there um like a uh
00:14:29.399
I know in it looks when you control C there's all these options like respect what's going on can you like from there
00:14:36.560
can you like clear the ad table or something um I'm not sure I don't know that there's a command to do it there
00:14:42.720
might be um you can pass um runtime options when you run I ex that would make the um number of maximum number of
00:14:49.639
atoms larger if for some reason you required it okay uh I've never run into it in a real use case where I filled up
00:14:56.440
the table gotta um but same rules apply within Ruby just don't cast user input
00:15:01.560
to an atom unless you know what's going on saw that yeah that's actually
00:15:11.880
awesome and then uh tles are store continuously in memory uh we Define them between
00:15:17.519
brackets and tles can hold uh any term so any type we can uh store as a tle so
00:15:23.120
I can put a string inside say one 2 three three and that's a valid
00:15:30.319
tupple they can hold uh anything we want to shove in them that's built into
00:15:36.240
Elixir and uh you would use tupples when you have a fixed set of data so tupples don't really lend themselves well to be
00:15:43.199
appended to so if you had something like a three element tupple that you know is always three elements you use a tupple
00:15:48.880
it's very efficient very fast because it's stored continuously in memory and they're kind of like the most
00:15:55.120
basic data structure uh in Elixir and earling so you would use use them um as like return types uh especially once we
00:16:01.880
get into pattern matching tupples are used all over the place they're kind of like uh passed around and use as a way
00:16:07.720
to like decorate data we'll see that in a moment uh lists are link lists and lists
00:16:14.880
um basically are used everywhere to store any kind of collection and again they're very basic
00:16:22.240
uh but we build up our programs around some very basic data structures uh so we can create a list
00:16:30.920
1 2 3 4 it works and we use like a head tail denotation if anyone's familiar with uh
00:16:38.440
other functional languages uh they use this uh HT notation for like a head of a
00:16:43.480
list and a tail of a list and this is the way that we basically perform like recursive iteration
00:16:50.319
internally and here's our first little bit of pattern matching which is gives me language Envy uh every time I go back
00:16:56.759
to Ruby so I can say okay I have some head I use like that pipe character and say I have some tail of a list and I
00:17:04.000
want to store that as some or pattern match it against some list
00:17:09.400
right so it's almost like destruction assignment if you've ever heard of that term and if I check the variable head I
00:17:15.640
see that it's one and then tail is the remainder of that list and this is highly highly optimized by the virtual
00:17:22.520
machine and this is our first taste of pattern matching which we'll get into some Advanced examples uh so the earing
00:17:28.240
vers machine basically is like a pattern matching genius it lives to pattern match and pattern matching basically it
00:17:34.559
takes a thing on the left hand side and tries to match it against a thing on the right and you can basically uh use any
00:17:40.720
term any data type in Elixir and pattern match on its values head and tail special words there
00:17:48.080
or is it just something pip something it's just something pipe something it's actually a good question I was I was wor people might think that when I said the
00:17:54.559
HT yeah so we can cast any variable there and this goes beyond that so I can
00:18:00.520
say okay the first element of my list I expect it to be one second element should be two third is a
00:18:08.400
variable and then the rest is going to be the tail of the list that's totally
00:18:13.480
valid uh so third is now three rest is going to be the remainder of the list and this works for any data
00:18:20.559
structure so this is just a list we could have a tuple on the left- hand side and it would work once we get into maps and structs later uh it works even
00:18:28.400
at a more uh higher level which is super nice and it will blow up if it can't do
00:18:33.600
a match so let's add uh that's not going to work let's say our first element is not is not one it's going to blow up
00:18:41.120
it's really angry there's a match error and uh this is earling uh you can read that in red uh match ER is like a
00:18:48.159
nemesis for a lot of uh people getting into earling especially because their programs will just blow up um and the
00:18:55.559
error will be match eror no sap Trace so Elixir is trying to um get much
00:19:01.440
better air messaging handling than earling um but you see match air a lot
00:19:06.559
of times because that's the fundamental way to
00:19:12.000
uh I gotta be careful how I say this so we want to make our programs crash instead of rescue from exceptions which
00:19:17.960
we'll get into later uh so ideally if something doesn't match when we expect it to we literally want our programs to
00:19:23.679
crash from a match error and that will be supervised by another process and restarted or we can handle it in some other way uh so we write our programs
00:19:30.919
around pattern matching and if something doesn't match a pattern that we expect it blows up with a match air by Design
00:19:36.360
and we'll see how that works and we so we don't end up like an Ruby where like begin rescue rescue from this eror rescue from this error we very rarely uh
00:19:43.559
rescue from errors in Elixir because by Design um an error is an exceptional State and we have no idea why it happens
00:19:50.039
so trying to rescue from it from The earling Elixir philosophy uh isn't the right thing to do and we'll see that
00:19:55.919
this afternoon once we get into OTP
00:20:01.679
uh there's some helper methods like HD will give you the head of the list TL will give you the tail you don't want to
00:20:06.799
use the head tail pattern match example you can just call it directly with the HD and TL
00:20:13.840
method and elixir has a build-in uh some build-in modules to help us work with lists in any kind of uh collection uh so
00:20:21.640
enum is a built-in module and elixir that handles a polymorphic um concept of
00:20:26.880
a collection so we can itate over a list we can itate over uh a map and some
00:20:32.000
other built-in data types and you can write a protocol so we get into this afternoon that you can pass to enum and
00:20:38.559
this is where the pl morph resin comes in where I could write this afternoon we'll have like the uh concept of a
00:20:44.679
tweet and we'll be able to iterate over its messages by defining a enum protocol for
00:20:50.320
it and uh if you have IEX up I want you to play with the H helper function
00:20:55.360
because it's awesome I miss it in Ruby so H is a built-in helper function where I can say you know what um you know tab
00:21:02.559
confete your friend to so I'm going to type enum hit tab I get a bunch of options but if I want to know what enum at is I can just say h enum at and
00:21:10.679
there's that formatted um documentation because it was documented in markdown so Elixir
00:21:16.120
when it compiles IT stores all of the mark all the markdown documentation as metadata you can get access to that and
00:21:22.960
it's nicely color coded so constantly I do like you know I always say I do IRB driven development
00:21:28.880
um during my rails apps uh so I use a lot of I driven development uh it works the same way because I can come in I can
00:21:34.799
even get up my own code documentation like this so if I wrote my own module and I documented it I can say h give it
00:21:40.919
the module and function name and Bam I have documentation for it formatted directly from markdown and then you get
00:21:46.760
some nice examples for it um so for me this is a huge huge feature and especially as you're learning um just
00:21:52.520
like get in and explore so if I say h uh can I do HH gu I'm like meta oh my gosh
00:22:01.880
yeah HH works so pretty cool um so use H as your friend
00:22:10.360
uh and then Ena Matt will give you some niceties so we're going to go through some recursive examples with list later
00:22:17.120
just to give you to get you thinking recursively and then you'll probably never have to do that ever again because you'll use the enom module to do some
00:22:23.880
list operations instead of writing it uh in your own recursive Style
00:22:29.640
and a big type in Elixir is keyword list and this is basically syntactic sugar
00:22:35.120
over lists uh and they're almost synonymous with like a hash in Ruby um
00:22:40.320
but they're not hashes they're just stored as a lists when it's compiled uh so it's it's not meant for like true
00:22:46.080
constant uh lookup time like hashes are so it's for like small sets of keys and values but they're very cheap and very
00:22:53.840
uh easy to use and elixir internally when it compiles your source code in its abstract syntax tree uh it's using
00:23:01.400
keyword lists um to do some um really neat things which we'll we'll see later
00:23:07.200
so a keyword list is defined pretty similarly to a hash and Ruby so we Define it between brackets
00:23:13.480
because really it's just a list so I can say the types in Elixir sort as some variable and say one atom it's called an
00:23:19.440
atom so it's just the key value as you would expect and we'll say we have a
00:23:26.120
what are some other types tupple
00:23:33.000
so there's our keyword list then I can access them like a hash and Ruby give it
00:23:38.279
a key there's our value I gave it a key that doesn't exist goes me nil like
00:23:44.880
Ruby and the neat thing about what Elixir is doing with this internally I'll show you this is just syntactic
00:23:50.640
sugar I can say Okay a keyboard list internally is stored as just a list of Two element tuples the first element is
00:23:58.240
the key the second element is the value so I can say I have a list it's going to take a
00:24:06.200
tupple is that equal to the keyword
00:24:12.039
list oops missed the quote so you'll find yourself you if you
00:24:17.760
control C out twice it's going to quit I ex and then you lose your history uh so you can actually type IEX break you find
00:24:24.960
yourself in this scenario there we
00:24:31.000
go and I messed that up too I'm just going
00:24:37.279
qu really oh there we go okay so literally the thing on the left hand side is equal
00:24:44.120
to the thing on the right Elixir just provides us some syntactic sugar on top of list to do a nice set of uh key value
00:24:50.960
Pairs and we saw before in that first example you might remember we had a if statement so I say if true true I can
00:24:59.279
give it a do end block so I can say if true do it's
00:25:05.039
true find out oh my gosh it's true uh so everything between the do and the end and elixir is just literally syntactic
00:25:11.480
sugar for uh if is a macro which we'll get into later so if you're calling if
00:25:17.880
uh first element is an expression and then the second element between do an in liir convert Elixir converts that to
00:25:23.559
literally a keyword list as a second argument and you can leave off the uh
00:25:30.320
list uh brackets if it's the last argument like Ruby you can leave off the hash uh bracket or hash braces a similar
00:25:37.000
concept so this is synonymous with and so that works uh so everything
00:25:44.559
in Elixir is built up literally as like a do in Block as a single uh key keyword
00:25:50.799
list the key is due and the value is the block of code when we get into writing macros this becomes uh super handy
00:25:57.200
because we can we can inspect that and get like the directly of uh the code that we
00:26:06.760
want there's a keyword module that provides some niceties so I can ask like
00:26:12.120
give me the keys of uh some keyword list that I have and it's going to spit out the keys so Elixir has a small standard
00:26:20.279
library but um it provides you most of the building blocks that you need to write um most of your programs so it's
00:26:26.960
not as extensive and Ruby especially we're all familiar with like active support which like you forget like
00:26:32.320
What's Ruby and what's active support uh so you're not going to have quite the like you know array. 47 to get the 47th
00:26:39.279
element or the array. third um but you the standard Library actually is quite nice so um it's really well thought out
00:26:45.720
and uh I don't think I mentioned before uh who's aware of who Jose Bim is hopefully most people he wrote Elixir
00:26:52.480
meant to pluck him initially um he's prolific in the rails Community he was a part of rails core he wrote devis he
00:26:59.520
wrote simple form he wrote probably uh or he had a hand in probably half of the uh gyms that you use on a daily basis so
00:27:07.120
he put Elixir together and um he's made some really excellent choices and it shows in my opinion in the standard
00:27:13.120
library and in The Meta programming round elixir in pretty much all areas what's the magic
00:27:21.640
break I ex and then pound break should get you out let me find out actually I
00:27:27.360
was forg good so now I'm in like a bad state where it thinks I'm continuing an expression I should be able to hit
00:27:33.480
contrl C once I think it might be actually this no
00:27:41.440
e so I actually think that's uh so Elixir
00:27:47.440
I ex is built on top of the earling erl shell I'm pretty sure that's earling because we like a little better error
00:27:53.320
messages than eh but it's all right really
00:28:00.200
I have to look this up you're
00:28:14.360
saying like that so you're saying I did what
00:28:25.919
C oh I see you're
00:28:31.480
saying I this up basically um history is not in place
00:28:38.159
yet so if you quit out of your shell um it's really frustrating because like in Ruby I'll constantly you know hit quit
00:28:43.919
relaunch a shell and I'll have my history and uh Elixir we don't get that yet and that's built on part because
00:28:49.279
there's some it's been on top of the earling shell and there's some issues with trying to get history in place I
00:28:54.320
know that there are some pining poort requests but um I'm not aware of why they why we haven't quite gotten there
00:29:00.840
yet so you do a lot of copy pasting if you ever quit out of I ex uh variables are immutable um but
00:29:08.399
what a lot some people hate that do earling is that we can rebind variables to a new value some people call this
00:29:14.559
mutability but they would be wrong my opinion so if I Define a
00:29:20.440
uh variable uh named sum uh instead of saying Define variables uh the term that
00:29:26.039
we use is we bind variables to a value so I can say uh sum is 10 now I have
00:29:32.720
binded a thing named sum to the value 10 if you're coming from earling you would never ever in this scope be able to um
00:29:39.440
rebind some to a new value it would blow up with a an error because it earling is like single assignment principle if
00:29:45.720
you've heard of that um but in Elixir we can say okay now sum is 12 and some
00:29:50.760
people would say ah this is a mutable language you've just changed some's value Elixir is terrible a lot of people
00:29:56.360
on Twitter um that are coming from lling have have hated on this uh concept um
00:30:01.399
but all we've done here is elixir still abides by the single uh assignment principle but uh internally when this is
00:30:07.919
compiled it's saying okay we're going to take the thing that was named sum and we're just going to rebind it to a new value anyone that had a reference to
00:30:14.399
some prior to this some would still be 10 uh so we didn't actually mutate that variable that makes any sense is
00:30:20.600
everyone clear on that I think I can show that with an anonymous function if I said uh I can create a Anonymous
00:30:26.840
function we can see for the first time we'll say some
00:30:34.480
value that actually that could actually work too but then at the moment we added it it would actually be the value would
00:30:39.679
be stored there not the reference to the variable um so I can say I.P
00:30:49.640
puts some was so this is anonymous function we
00:30:56.399
Define it with FN Dash rocket and then we give an end and uh just like like
00:31:01.519
JavaScript and some other functional languages uh functions that close over variables so it's going to close over
00:31:06.760
the sum that was 12 so now I have sumbal as an anonymous function and if I want
00:31:12.559
to I'm going to change sum again and so okay sum is now 100 so if I invoke that Anonymous
00:31:18.360
function we see sum was 12 so we haven't mutated some when we said some equals
00:31:23.760
100 we just rebound that to a new value uh so this trips some people up coming from earling because they're so used to
00:31:29.960
defining like if if they ever come into a case where they want to uh change something you'll see like some one some
00:31:36.240
two some three in code a lot and this gets around that um and we can see that
00:31:41.480
we can invoke Anonymous functions uh with the dot notation which seems a little bit odd and uh some people really
00:31:49.000
don't like this uh but as you get further into this um I actually really like this so Anonymous functions are
00:31:55.799
invoked with it's called like do notation or the dot operator and the reason why we have this is because if we
00:32:01.200
didn't have if we want to invoke it some people want this to be changed to this coming from like a JavaScript background
00:32:08.519
a lot of functional languages uh this would ruin uh zero function aity in Elixir so if we ever wanted to call a
00:32:14.440
function off of a module in Elixir as I'll get into later that didn't have that didn't take any arguments we would
00:32:20.120
have to include the braces like here's one example self will give you the current process ID and that's a building
00:32:26.000
off the kernel um if we didn't have uh the dot notation on Anonymous functions
00:32:32.120
uh we would no longer call self we wouldd have to call Self like this which still works so the do notation resolves
00:32:37.639
that ambiguity on do we want to call a function or do we want to reference to self there I'm clear on that because
00:32:44.039
like self and like JavaScript for example if we had a function self would return us a reference to that function
00:32:49.600
but in Elixir zero aity is actually just going to invoke it so for anonymous functions we use a DOT operator uh to
00:32:55.880
actually explicitly invoke that function otherwise we just have a reference to
00:33:03.039
it and then pattern matching we saw a little bit before is actually doing variable binding so first rest equals
00:33:10.519
Alice Bob Ted list uh first and rest are going to be Bound To The Head and the tail of the list so we're actually doing
00:33:16.320
a variable binding within pattern matching as we saw earlier just through a rebinding
00:33:25.080
example uh so functions in Elixir are first class like you would expect in a functional language we can Define them
00:33:32.519
and pass them around just like any good functional language does
00:33:39.720
um see if this is worth actually going through yeah might as well do it so we
00:33:45.279
can define a Anonymous function named ad again we use FN notation and the
00:33:51.600
arguments are passed in so ad's going to take first number and a second number
00:33:56.960
all it's going to do is add them together return the
00:34:02.240
result pretty easy and just like in uh Ruby everything is an expression again so there's no return there's actually
00:34:09.200
Ruby has a return keyword Elixir has no concept of return so the last thing evaluated is a thing returned so we
00:34:16.079
don't return in Elixir we just write expressions so I can say okay we have
00:34:22.200
some subtract as well
00:34:27.839
and that's going to subtract the numbers so if I wanted to like perform
00:34:34.200
some calculation I could say okay I'm going to perform a calculation takes a first number a second number and then a
00:34:40.040
function as a third argument to invoke just to show you that we can pass these things
00:34:46.359
around so I like to you can hit enter and it will continue that expression so you don't have to like write it on one
00:34:51.399
line so we can say okay we want to explicitly invoke that function you passed to me with the dot operator and
00:34:58.280
we'll just pass in the first number and the second number and there's our perform calc
00:35:05.760
function so then we can see that functions our first class by saying okay
00:35:10.880
on a perform calculation say five and six and I want to pass that add function
00:35:16.560
that I defined above and it works so functions our first class um Anonymous
00:35:23.119
functions are actually used a lot less as far as passing them around and defining them explicitly like this uh we
00:35:28.880
use anonymous functions um as part of like enom modules and Performing mapping operations but most of our code is going
00:35:35.359
to live in modules that we'll get into um very shortly so you're not going to be using the dot notation quite as often
00:35:41.960
as you would think so if you hate it um it really isn't used all that often compared to calling functions on modules
00:35:48.240
which do not use the dot
00:35:54.839
notation and uh elixir has a shorthand function Syntax for uh some cases where
00:36:01.599
like writing the FN uh arguments is a little bit verbose so for example I have a enum map
00:36:09.680
operation so mapping over a set just like Ruby's uh uh array collect or array
00:36:17.119
map we can map over a list multiply uh the first or multiply each element by
00:36:23.720
two and we see if we get the correct result so this Amper sand syntax is basically
00:36:30.359
uh synonymous with saying okay I have some number and I want to multiply it by
00:36:37.599
two so these two uh top and bottom are synonymous so we use uh Ampersand like
00:36:43.400
create a shorthand function syntax then Ampersand one is going to say okay the first argument to this function do
00:36:49.280
something with it uh so this is nice and succinct for very very simple operations U but I caution everyone do not litter
00:36:55.680
your code with the Shand function syntax unless it's a very trivial transformation uh because it's one of
00:37:02.400
these things that uh I T I try to say uh always be have Clarity over brevity so
00:37:08.560
if you get into like AER one AER 2 and you're doing some transformation on that data someone reading through your code
00:37:13.960
later or your own self reading through your code later is to have no idea what's going on uh so it's nice to use
00:37:19.160
if we're just doing a simple operation otherwise use the expanded syntax is the rule that I try try to abide
00:37:25.319
by and uh you'll often hear people call the Amper sand then a function uh the
00:37:30.920
capture operator I've heard it called so we can like capture functions uh so some people uh say well
00:37:37.040
we if I have an a reference to an anonymous function that I have to invoke but on uh modules I don't use the dot
00:37:44.200
operator so if I want to do like kernel if I say like 5 + 2 really what that's
00:37:49.880
doing is calling the uh off the kernels uh imported plus
00:37:55.599
function so literally five 5 +
00:38:00.680
2 is actually doing this internally if I want to capture kernel plus as an
00:38:06.240
anonymous function I use I prefix it with an Amper sand so if I want to say okay uh add is
00:38:13.160
actually going to be a captured uh function off of this module I have to do
00:38:19.319
this so capture it by name and also aity so all functions in Elixir earling are
00:38:25.440
defined by their name Plus their aity so I have to give it slash2 here and now I
00:38:31.240
have captured earling and elixir uh plus operator and I had to specify the aity
00:38:36.520
because uh there are no uh uh all of your functions cannot have like any arbitrary number of uh arguments and uh
00:38:45.319
from Ruby I think half especially from rails half the time you can pass in a list half the time you can pass in like a Splat uh you kind of have to dish that
00:38:52.400
idea coming into Elixir because we are fixed by name plus are
00:38:57.440
um but what we lose in being able to pass like Splat arguments we gain in using pattern matching and writing our
00:39:02.960
code around pattern matching and we'll see once we Define modules how well that works out uh so you can stop thinking
00:39:08.680
about functions as just having a name you you have to start thinking about functions having a signature of name
00:39:13.839
plus aity plus guard statements as we'll get into
00:39:20.000
later two functions can have the same name in different are yes and you'll
00:39:25.079
exploit that um to great benefit as we'll see later we could Define a function we can almost you can almost
00:39:31.280
think of it as like overloading a function but really each function has its own unique signature and the virtual machine will use pattern matching to
00:39:36.839
figure out which one to invoke and then here's just a simple
00:39:42.839
example using the capture operator U this is this one's a little more explicit
00:39:48.760
that's store this as a new variable
00:39:54.960
first so if I have have some list then I want to filter over that
00:40:01.240
list so enum use tab complete to explore the enum module with the H helper there a bunch of building functions so I want
00:40:07.480
to filter a list and then filter is going to say give me a function um and if the function returns true it's going
00:40:13.839
to give you a bad a eror uh let's see what did it get mad about oh it's going
00:40:19.440
to pass the element in um so if the element was truthy it's going to give you everything back so if you just passed in the element everything's true
00:40:26.640
and elixir just like the only thing that's false in Elixir is nil and false um but we can say uh in earling we have
00:40:34.440
a built-in uh is number function so I can call it is number on that element
00:40:40.200
and it's going to fill through that list and I only get one and two back um but since that's such a trivial operation I
00:40:45.400
can use the capture operator and uh instead say Amper sand
00:40:50.560
and I don't have to use um parentheses if I don't want to here I can say capture that is number
00:40:57.119
and pass in the item and mad oh
00:41:05.359
misspelled so anytime I use the shorthand function syntax it will almost always be cases like this where it's
00:41:11.880
trivial and I have like a single um argument to the function so if you ever
00:41:16.920
find yourself like ersan one ersan 2and 3 that would work if your Anonymous function took three arguments um but for
00:41:23.160
me then your code starts getting SP spaghetti like to me so be a little bit
00:41:28.359
careful with that I have a warning you sparingly
00:41:35.119
oops so we went over captured functions and then we can pass captured
00:41:42.040
functions directly as like a second argument so like reduce and map always take a argument as a last operation to
00:41:48.760
perform some transformation so if I want to add or reduce one two three just like
00:41:54.160
reduce in Ruby I can pass in konel plus captured A2 and it's going to add them
00:42:00.280
together so you use capturing quite a bit if you ever want a reference to a function to invoke
00:42:08.640
later here's where we get into modules which we'll write a little bit of uh so modules and elixir are going to live
00:42:15.880
most of the code you write are going to be in modules so you're very rarely going to be defining your own Anonymous functions to perform some work we'll
00:42:22.280
pass Anonymous functions to some modules as arguments but very rarely will'll be defining like ad usually we'll Define a
00:42:28.599
module and then Define this is referred to as a named function so like Celsius to Fahrenheit in this example is going
00:42:35.200
to be a named function not to be confused with Anonymous functions and uh we can see uh we have like def module to
00:42:42.359
it's the way that we Define modules we get it a name which is camelcase and uh then we give it some
00:42:47.680
code between do and an end and just like on that if statement if you wanted to write a macro around this or get at the
00:42:54.440
internal representation that do all the way between do and end here so all of this really is syntactic sugar for a
00:43:01.559
keyword list of do and the value of all that code um so once we get into macros
00:43:07.480
I'll touch on a little bit this afternoon it's a little bit Advanced um but we can get at that um representation
00:43:13.160
of code very easily so everything Elixir is built up from some very uh simple building blocks and it carries out
00:43:19.040
throughout the language so you have like if do end def module do end uh it's very
00:43:24.880
uh similar all across most of its uh building blocks of the code that you write uh so we can just copy and paste
00:43:32.319
this directly into IEX and play with
00:43:37.359
it my phone a little bit so you see that it said okay give me
00:43:42.680
a tuple back um the name of the module weather and then like all this crazy stuff right so that's actually the bite
00:43:48.400
code so compiled this looker is a compiled language so you're literally looking at like the bite code of that
00:43:54.079
weather module if you're if you're curious and then we can call it so if I want to say
00:43:59.839
give me Celsius to Fahrenheit tab complete is your friend so if it's
00:44:07.760
31 or wait Celsius to Fahrenheit there we go 32 so uh we invoke this is very similar
00:44:14.599
to R we invoke named functions without the dot notation and this is how you would write most your code you would
00:44:20.079
write it on modules and invoke the functions very similar to like a class method in Ruby so this should look
00:44:25.520
pretty familiar here and then parentheses are optional as well so if I want to invoke it like this clear the
00:44:31.319
scroll back that'd be totally valid I get 32 uh but we Define functions with def
00:44:39.200
so if you're coming from like a uh closure use def like lot of lists use def um that's how we Define name
00:44:46.200
functions so we say def uh the function name and then arguments and then do end
00:44:52.559
again is syntactic sugar for a second argument of a keyword list uh so we have
00:44:58.520
two ways if you if you ever have a single line to like you can perform a tiny bit of work in uh you can literally
00:45:05.200
just write it like this and this is actually the preferred style if you have a very succinct function so if your
00:45:10.920
function fits on a small line it's doing uh something very simple say def High
00:45:16.319
comma do and then give it a value and again this is just syntactic sugar up
00:45:21.880
here for the do end so if you ever have a multi-line function you're going to want to use the D wind but if you have a
00:45:27.079
very short function that's a single line you can throw it in the uh single line syntax
00:45:37.720
here uh so constants will let me see if I actually I think I
00:45:43.200
do this in the next section we have a similar mechanism the
00:45:48.520
constants let's go
00:45:54.880
back we'll get to it okay a little bit
00:46:01.599
later but constants are actually we refer to them as like module attributes which are kind of synonymous but we
00:46:07.400
don't we're not quite there yet uh so let's hop into pattern matching a little bit we've
00:46:13.800
seen some examples of pattern matching um but just to show you a little bit extra of what's going on uh if we want a
00:46:21.200
pattern match on like a variable's value uh this trips people up sometimes so if I bind a to one and I want to actually
00:46:28.040
pattern match on A's value and not rebind it so if I want to say a is one
00:46:33.119
and uh B is one if I want to say does a match B we say like well we have an equal sign it's going to match the thing
00:46:39.079
on the left or the right if I did this it would actually rebind a but if I wanted to pattern match on
00:46:44.800
the value I'd use the like hat operator What referred to and it's going to match on it people from earling really don't
00:46:51.200
like this because they like single assignment so if you accidentally left off the the Hat operator you would end
00:46:57.760
up blowing away a and rebinding it to a
00:47:03.920
value so now we should be able to write our first program in a text
00:47:10.400
editor uh actually we'll go into control
00:47:15.680
control flow first that's so we saw if before pretty self-explanatory we have if else and we
00:47:23.000
have unless which is awesome but there is no unless else by Design so if you
00:47:28.520
have unless else in Ruby and you write it a lot you should probably
00:47:33.599
stop um so we have a con keyword so if you ever find yourself like doing if
00:47:38.800
else if else if else in Ruby uh Elixir can't do that you literally get one if
00:47:44.000
and you get one else there's no else if uh so what you would use instead is cond
00:47:49.200
and con takes a series of Boolean expressions and it's going to evaluate the first try clause so if I Define a
00:47:57.680
variable named temperature I can say cond and then just start some Clauses and the first one that's truthy it's
00:48:04.079
going to evaluate and return the result so we see that it was freezing um I
00:48:09.200
don't think I've actually ever used cond in any code for real U because I'll use case instead but cond is there um and
00:48:16.319
it's pretty handy um but most of your uh control flow is actually going to use case and um you're going to use very
00:48:23.839
little if statements in elixir very uh much fewer ifs than you would think
00:48:29.079
because we use pattern matching instead to do a lot of our control flow and that's where case comes in so case is
00:48:34.680
control flow based on pattern matching so we can give a case an expression and
00:48:39.920
then we can give it a bunch of Clauses instead of instead of to evaluate as like truthy it's going to actually pattern match on the thing on the left
00:48:46.599
and the first thing that act matches it's going to call the claws on the right so for this example here we can
00:48:52.520
again just copy and paste this into I ex I wanted to make make like a very simple parser quote unquote in Elixir that's
00:49:00.079
going to operate and do some Expressions I can store that Anonymous
00:49:05.400
function that calls case on some couple expression and I can pattern match on the operator and some values provided
00:49:12.400
and it's going to cases to go from top to bottom on each of these patterns and if it finds a match it's going to
00:49:17.760
evaluate the thing on the right hand side so I can say okay let's invoke calculate pass it a tle expression let's
00:49:25.160
say if we have we have parsed some user input and then we probably cast it to a
00:49:30.280
plus atom which we shouldn't have done I mentioned before let's pretend I use a string for this example so let's say we
00:49:36.000
par some user input from a calculator and we know that we have the operator plus and we have a couple
00:49:42.079
values we can call case on that expression which is a three element tle
00:49:47.520
first element is the operator and it's going to literally go from top to bottom here and try each of these Clauses out
00:49:53.680
pattern matching on each thing first one that matches it invokes the thing on the right hand side if we give it something
00:50:00.040
that doesn't match any of our Clauses like a Four Element tupple it's going to blow up with the case Clause error so you have to define something that
00:50:07.079
matches always uh so a lot of times you'll end up with like an underscore Das rocket which just says I don't care
00:50:12.559
what it is but I want something to match and you can do neat things like uh
00:50:17.880
short circuits so pattern matching isn't just like pattern matching and binding to variables this is a trivial example
00:50:23.440
but let's say if I had some expensive operation and I someone passed in a zero I know
00:50:29.400
that this is just going to be zero I don't want to perform any operation so just get to give you an idea of pattern matching it's not just like binding
00:50:35.640
variables we can say you give me a multiplication a number and then a zero
00:50:41.200
I'm going to say a short circuit and say well I know that's zero I mean this is kind of stupid but gives you an idea that we can pattern match on a provided
00:50:48.040
variable say num one and this example right here uh can be anything whatever it is if the second thing is zero that
00:50:54.440
you passed in it's going to match the clause and give us uh zero
00:50:59.960
back uh so you use case U pretty constantly if you find yourself doing a bunch of if eles it can almost I'd say
00:51:07.000
80% of the time um be done better with pattern matching when uh in this example if you had the other
00:51:13.640
multiply um num one num two if you have that before the zero was the zero would never yes that's a very good point so
00:51:21.240
once we get into modules almost all this rule almost always applies it's going to pattern match from top to bottom so if
00:51:26.559
we defined uh he's saying that if we defined uh this Clause with the multiplication above uh the num one and
00:51:33.400
zero we would never invoke that num one zero Clause even if you pass zero in so it doesn't like look through the
00:51:39.400
potential matches for like corre it goes top to bottom the first one that matches it's going to invoke and that's actually
00:51:45.240
really important once we get into pattern matching on function names because if you were like writing a recursive operation where at the end you
00:51:51.559
wanted it to stop but you def find it afterwards you would have like an infinite Loop we'll go through that yeah what's theity
00:51:57.920
of that calul function so aity here this would be a single aity function because
00:52:03.480
we're passing it a tuple okay but you don't have to Define that in when you
00:52:08.680
actually Define the function itself so like function here takes a single argument expression oh that is okay yeah
00:52:14.839
yeah I and then here we're just passing in a tle so a lot of times people get around arities by U passing in like a
00:52:21.520
list and the list can take any number of arguments but it's a little bit more
00:52:37.359
bbos right here uh if we use the Hat operator so uh we can actually see that
00:52:44.400
so if I uh here if I just said like VAR zero there or something um it would just
00:52:51.799
if it in if something matched that Clause it would invoke this thing on the right but VAR zero would be bound to
00:52:57.559
whatever value they passed in but how we defined VAR zero outside of the scope like up here and then we use that hat
00:53:05.319
operator far zero it would perform a match instead of a binding that makes sense so anytime in your case statements
00:53:11.920
you'll want to if you ever want to match on a variable's value use that hat notation that make
00:53:20.920
sense and then here's like the um issue with I don't want a case Clause here if
00:53:26.359
you give me something that I can't match against uh it's going to blow up and say like whoa I wasn't able to match anything crash so a lot of times we'll
00:53:33.480
just use like the underscore to say I don't care what it is and then it's going to invoke this Clause if if you
00:53:39.079
get it something that it can't parse we can say you know raise an error unable to parse the expression so this like
00:53:45.640
underscore notation is used quite often as like a catch all clause and that will
00:53:51.079
always be last because if we had this first at the top it would always raise unable to par yeah so could you use that underscore in
00:53:58.280
your like match cases and then do like your symbol plus comma underscore and then make that a function to just be
00:54:05.160
everything else that catches withes in between it Som yes so you're saying if we had like
00:54:10.680
a some expression maybe it took a plus and then if we passed it like seven and
00:54:17.319
like whatever else um you know sevens aren't allowed
00:54:22.720
I'm really bad at examples so your client gave you these requirements
00:54:28.559
as they normally do and uh otherwise I don't
00:54:35.599
know return wait so what so what are we trying to do then oh well in this
00:54:42.599
example it would if you did seven and then anything and then you did seven oh yeah you're totally right so let's just
00:54:47.880
do yeah that it would have never matched it would have uh the compiler would have taken it but we would it would have been
00:54:54.240
pointless right MH okay so yeah this is so this is totally valid if I call
00:55:08.559
calculate seven aren allowed so you'll actually you'll see that underbar and and it works in any match anywhere and
00:55:15.240
that's for cases where we can discard a variable and I use I use this constantly in my code where if I'm going especially
00:55:20.960
when you're writing macros if you have some like three element list and your API for some reason is always a three
00:55:26.280
element list and the last thing is some like expression that you want uh you'll very often uh see like it's called like
00:55:33.480
discarding that like we don't want to bind that to a variable and the compiler if we ever if we did that bind that to a
00:55:38.640
variable and then didn't use that variable we get a warning in our code it would work but then we all hate warnings
00:55:45.280
I get them constantly in my rails app for like some XML Library so you know rake routes spits out a compiler or a
00:55:52.599
runtime warning 16 off yeah so you N1
00:55:59.960
And1 can use underscore say N1 plus underscore or is it actually disc uh you actually could
00:56:07.319
use N1 plus underscore okay you probably wouldn't want to a Convention of saying I don't care about it's a it's a
00:56:12.440
convention for saying I don't care about this and it's a way to stop the compiler compiler will never complain about underscore like you didn't use
00:56:18.119
underscore you won't get a warning for that you could use it um if you find yourself doing that I wouldn't do it um but initially I thought that it did
00:56:25.200
literally discard it um but then in your code you actually can use it um if you wanted to be it's actually that's a good
00:56:31.240
question yeah if I wanted to say what's that yeah but if I wanted to say I have
00:56:36.960
some first uh second and the third thing is some uh value that I
00:56:43.200
want a common thing you'll see is using an underscore in front of the variable name
00:56:50.359
this is an idiom in Elixir uh if we Define this in one of our functions and did not use for first and second without
00:56:55.680
using the under bar in front of it the compiler would warn us saying you have an unused variable first second you didn't use them but if you wanted to
00:57:02.480
discard it but name it because it makes the code code more clear so if that was a better example than first or second
00:57:08.960
very often you'll see a discard but you'll name it just to make the code more clear yeah if you only use the
00:57:15.839
underscore in that line 37 as both the first and the second item
00:57:21.240
in the list there doesn't that force it to B the value for the first and second
00:57:27.280
yeah but we don't we don't ever reference the UND it works um but you
00:57:32.319
would never actually want to say what was the value of the thing I discarded well no but you what you were showing up there was open square bracket under
00:57:39.280
comma under comma Val could that and close Square could that actually match one two three yeah
00:57:47.440
so let's see let's actually see what happens I could eat my own words here so if I say okay that matches we expected
00:57:54.200
like what's the is this is this going to give me a value no it actually doesn't like that it's immediately garbage pled so I lied
00:58:00.720
okay I think this works though if I discard or if I say first here I thought
00:58:06.000
this was a discard as well which it is but I think I can actually reference underscore first yeah I can
00:58:15.760
so if you yeah so the compiler would warn if we uh in our function had a
00:58:21.160
first that we were binding but not actually using so you would prefix it with an underscore um it it is actually
00:58:27.119
binding that to a a value um but the compiler will stop warning you so you
00:58:32.240
can still reference it you if you ever find yourself referencing a prefix variable name um with an underscore
00:58:38.480
remove the prefix because it's just odd because it mean the intention is we're discarding this
00:58:49.240
yeah it's not treated differently it's a convention the compiler will warn you so it is treated a little bit differently
00:58:54.440
but we you can still reference it um I don't know if some of the internals optimize around it but you could uh we
00:58:59.960
just we have a variable underscore first that is bound no value but um the compiler would actually warn us
00:59:05.319
otherwise so the compiler treats it differently semantically I don't think it actually optimizes it out at
00:59:11.079
all so you're saying that a single underscore is treated differently than a variable name that begins with anore yes
00:59:17.520
single underscore literally is a discard okay variable that begins with an underscore you can think as a discard but if you wanted to reference that by
00:59:23.839
its name you could but you wouldn't want
00:59:29.000
to especially since later maybe they would optimize that in some way and if you had code referencing that I'd
00:59:34.960
probably consider it a little bit unsafe and here's where we get into guard Clauses which are awesome is
00:59:41.440
anyone familiar with the term like a guard expression in Ruby I use this term all the time so like the top of my Ruby
00:59:46.960
methods often instead of like an if else or like an if case and like write your
00:59:52.240
code in your method then an end you'll just have like a guard statement at the top um I think a lot of people use this
00:59:57.440
terminology in Ruby so like if I My Method receives something in Ruby that I
01:00:02.520
um if it doesn't satisfy some case like the user doesn't have access to perform some operation I can just say like
01:00:07.960
return unless is admin user um so there's like I refer to that term guard expression in Ruby and conceptually it
01:00:14.680
carries over into Elixir but it's a little bit more powerful here and um
01:00:19.760
it's highly optimized uh so in like a case statement I can give a guard expression by using wind so here's our
01:00:26.960
calculated expression again which if we try to divide two numbers in the prior implementation it would blow up with a divide by zero error so I can I can
01:00:34.440
define a case statement who also has a guard and I can say okay I have a
01:00:40.079
division operator number one number two when num two is not equal to zero then
01:00:45.520
go ahead and invoke the division uh so this would Define a um signature that
01:00:51.240
literally if you passed a zero as number to a uh clock would not exist that matches that and this is like super
01:00:57.079
highly optimized and um I use this all over the place in my Elixir code so if
01:01:02.200
we tried to call like Calculate 10 divid 0 we get a case Clause error that we
01:01:07.319
actually don't have a case defin matching 10 over z u but they're a little bit restricted
01:01:12.599
uh so we can't call like our own functions here so if I def finded a function that was doing some some of my
01:01:19.119
own defined functions it would actually blow up it's limited but it's highly optimized so in Ruby we have a guard
01:01:24.680
statement that calls any code anywhere um the actual guard terms in Elixir are
01:01:29.960
defined to a subset of operators and a subset of building functions but you can't call like user land
01:01:35.039
code I have a giant list here if you want to look um but they're pretty cool on name functions because like if I had
01:01:41.319
like a a bank system so if I want to Define like a credit function so you
01:01:47.839
have crediting and a balance and amount I can say like credit balance some amount when amount is greater than zero
01:01:53.079
and this would literally the function signature here would be A2 but the guard statement would um literally Define the
01:02:00.079
function only for when amount is greater than zero so this seems just like an if like return in Ruby but you have to
01:02:05.960
start thinking about this like this function credit has a signature that's all three uh name aity plus guard
01:02:12.160
statements that Define um the actual uh function that the virtual machine ends up
01:02:18.640
invoking and there's a huge list of functions that you can use um a lot of type te most type checking functions are
01:02:24.680
available in guards so I can say like if I was having a grading system you know de grade passing a letter when the
01:02:30.359
letter is in a or b they did well um let's see some more practical
01:02:39.240
examples yeah what does it mean that a function is not defined unless one of
01:02:44.480
the arguments presumably you're passing function like what it mean it's not
01:02:50.559
defined like the virtual machine when I invoke a uh function it's going to pattern match on the
01:02:56.200
function name andity in any guard statements okay so when you're invoking a function internally the virtual
01:03:02.079
machine is literally pattern matching on those things so the function is there it's just like oh this doesn't match the pattern so I'm I'm just saying
01:03:08.079
conceptually it's defined I'm trying to make you think of um in terms of pattern matching so when I ask the virtual
01:03:13.920
machine to do something it's literally going to take a module and try to pattern match on those things and if those don't match as far as it's
01:03:20.440
concerned that doesn't exist as far as code that should inv
01:03:26.039
so now we'll get into one of my favorite features of Elixir it's the pipeline operator is anyone familiar with uh
01:03:32.960
anyone do closure here it's similar to like a Threading macro en closure I think this is actually stolen directly
01:03:38.760
from closure's concept it's the first time I've seen this and it's amazing so a lot of times when you're writing
01:03:44.400
functional code things that I hate is uh you almost have to write code and read it backwards if you're familiar with any
01:03:49.960
lists in addition to the parentheses you end up having if you're trying to define a ser years of Transformations you have
01:03:55.640
to almost write it backwards because if we want to pipe or use the value of some
01:04:01.160
uh transformation and send it to the result of another function we end up having to write our steps from like the
01:04:06.359
center pass that in pass that to another function pass that to another function and it reads backwards from the actual
01:04:11.640
Transformations that you're performing so the pipeline operator exists in Elixir to pipe a value as the first
01:04:18.240
argument to a function and so here's a trivial example I have like IOP puts right
01:04:26.480
hello I can actually pipe this instead and say okay I want to pipe the string hello into
01:04:33.079
iuts so we use the pipe greater than and that will literally make transform that
01:04:38.480
into iuts first argument hello but the neat thing about this is you can have
01:04:44.000
still any number of arguments and pipe this uh value so if I have like a an enum map operation which takes a list in
01:04:50.960
a function I can have a uh a list and then I can pipe that into
01:04:57.839
enum map so enum map takes a list normally as a first argument and then a function as
01:05:03.720
a second well since it pipes that as a first my function becomes the first argument
01:05:10.799
here I can say I * 2 and it works and uh to me this is
01:05:18.839
seriously my favorite this and macros are my favorite featur of the language so if macros didn't exist or the pipeline didn't exist I don't know that
01:05:24.839
I'd be talking today so this is one of the things that really drew me in early on because this lets you describe your
01:05:30.119
programs as a series of Transformations so I'll get through probably my first real world use case here uh so let's say
01:05:37.240
uh someone comes down to you and they have a list of requirements for a program they want you to hit a third
01:05:43.000
party API so we have some like user token we want to hit the API from a with
01:05:49.119
a user ID get a token back authorized user token for maybe some like ooth API
01:05:54.400
then we want to make a Json request to an API with the authorized user token then we want to save all of those Json
01:06:01.039
results to a database so it's like a four-step operation if we wrote this without the
01:06:07.400
pipeline operator here's a ficti fictitious uh message service for example we want to like import some new
01:06:14.119
messages under the requirements I just described so we have import new messages maybe we have some ooth user token we
01:06:21.640
almost have to write this backwards and reading it it's not like we can like use indentation and this isn't too bad to
01:06:27.680
read but you can't grp this in your head or grock it right away at least I can't
01:06:32.839
so we almost have to read this backwards and like go outside in so we can say okay well the first thing they're doing is like okay take a user token here call
01:06:40.920
find user by token that's going to give us back some authorized user token that we can then fetch from the API maybe
01:06:48.760
some unread messages that's going to give us a Json result which we then want to parse to some messages in our program
01:06:55.880
and then we want to iterate over each of those messages and call save message right so what's that yeah so it's like
01:07:03.559
yeah I don't know it's like for me that takes way too long to reason about so that exact code exact function arity
01:07:10.440
with the pipeline operator becomes this where I can say okay and this is how I write almost all my code I can say we
01:07:16.079
start with a user token and we're going to actually transform that into some user and we get that result with an
01:07:23.039
authorized user fetch their un messages that's going to give us a Jason result part the Jason
01:07:29.440
message list pipe that to enam me which is a list of Jason uh or Jason array and
01:07:34.960
call save message uh so is everyone clear on that like literally this is the same same function signatures
01:07:45.839
here yeah so um yeah here you would need on everyone
01:07:51.920
and you can do you could put this at the you could pipe at the end of the line it's my convention to pipe um in this
01:07:57.920
manner some people will pipe at the end uh Elixir is so new yeah it looks go
01:08:05.319
ahead that's a good question so uh there's a lot of discussion around if like the third operation like uh trying
01:08:11.640
to make the fetch for example that failed what do we do uh some people would say well your program should crash
01:08:17.799
and it sounds funny but like one way you would handle this is this operation would be supervised by a super
01:08:24.640
which we'll touch on later and you would want this to crash and if this crashed we would then handle it at the supervision level which would then maybe
01:08:31.239
retry because maybe the API service was down so your supervisor could have logic that would say retry this um 10 times
01:08:38.279
over a minute period if that still fails and the supervisor would actually crash and then its supervisor would figure out
01:08:44.239
what to do um so that's one way but a lot of cases you're not in a lot of cases you're not going to want to
01:08:50.560
supervise everything so there's a lot of discussion around around um in Elixir
01:08:55.640
how we can best handle this so Elixir recently exposed a way to easily write
01:09:00.759
macros around this um which is we're going into a little bit this afternoon not this specific use case but there are
01:09:06.679
some mechanisms in language you could def find a macro to handle this error case um easily and um there's a lot of
01:09:12.480
discussion on the luir manin list about how can we actually do this in the language itself so some people are suggesting like a you would pipe into
01:09:18.880
like if okay and some other mechanisms um that's a good question um so hop on
01:09:24.239
The Elixir Lang uh liix Lang talk and liix Lang core Google mailing lists and
01:09:29.880
there's a ton of active discussion um and there's some different opinions so uh it's nice that Elixir is uh so young
01:09:35.600
we mentioned like conventions of the pipe operator where to place them uh it's so young that you can get in early and Define some of your own conventions
01:09:42.799
um we all use two space in notation hopefully so some things are set in place but um it's still up for opinion
01:09:49.359
so it's kind of a fun time to to be involved um but piping is literally one of my favorite features of
01:09:55.719
language and um I'll show you a tiny bit of real world
01:10:01.040
example just to say uh so I'm working on a web framework in
01:10:07.440
Elixir and I'll just hop into like a random uh module that I have we'll see
01:10:14.080
how many times I use the pipe operator so I'm not going to explain
01:10:19.239
this code but we can see like right away I'm piping so your program become a
01:10:24.440
series of data Transformations and the pipe operator literally exposes that so it like seems like such a simple thing
01:10:30.600
like if this didn't exist um it's the same code but it changes the way I think about programming for some reason I
01:10:36.520
don't know why so it's almost like you know I start in my programs I start with some string path I ensure that it has no
01:10:43.000
leading slash then I split it like it it literally just the fact that the pipe exists and flattens my transformation
01:10:49.679
layer out I start thinking about like I when I first wrote this method I wrote path down and I said like okay what I
01:10:55.840
what do I need to do with it well the first step of the transformation would be strip off a leading slash and split
01:11:01.040
it so like you start thinking about it as a series of Transformations um just by virtue of being able to flatten your
01:11:07.400
steps up like that no so it's actually really good so
01:11:13.719
there's a poll request that was just closed by Jose for people that wanted to be able to do that to say I want to pipe
01:11:20.239
to the second argument instead of the first or I want to pipe to the argument so there was actually one discussion on
01:11:25.760
the mailing list that was like I want to be able to say like regx dollar for like the end like basically like um Dave
01:11:32.840
Thomas if you're familiar with prag Dave he ended up finally chiming in as a
01:11:38.280
voice of reason saying like we've developed aor complete language um as a pipeline operator like people were like
01:11:44.520
it was literally was like well plus dollar like that would do something like
01:11:50.000
so most of the discussion and I'm with this uh I would actually prefer it just stays as a single um pipe like that and
01:11:57.480
always pipe to the first argument some people like this option to pipe to the second cuz a lot of earling libraries if
01:12:03.360
you're trying to do earling interop will pass the thing that Elixir passes the first argument is almost always the subject of the function so Elixir code
01:12:11.080
lends itself to always piping things to the next thing it's like a thing you're operating on is going to always be the
01:12:16.199
first argument when it lends itself very well to piping but earling doesn't earling just is a mix and mash it's kind
01:12:21.800
of like the I'm not going to pick on PHP like a PHP standard library is kind of like needle Hast stack hyack needle who
01:12:28.440
knows um so earling is kind of similar there was never a convention originally so a lot of people want to be able to do
01:12:34.760
the pipe uh greater than greater than for a lot of earling interop because otherwise if you wanted to pipe you have to write your own function that wraps
01:12:40.800
the earling function um but I'm of the opinion that we need to keep things simple because you get carried away like
01:12:46.159
with like what Pearl did and like you get two uh it's whole Clarity over brevity thing you focus on brevity so
01:12:52.199
much that we end up with this like turn complete language in like a pipeline operator so yeah it's
01:13:00.560
awesome we have next here all right so I'm a huge uh space
01:13:07.960
nerd so my our first real program real program is a rocket launch because
01:13:14.040
Rockets are awesome uh so if you have a text editor uh copy and paste this in because I'm going to show off a little
01:13:19.800
bit of IEX feature it's nice uh so we can define a module let's just
01:13:26.800
go ahead and uh paste this into your favorite text
01:13:44.199
editor uh so you if you name the file EXs Elixir files are named andex EXs
01:13:53.080
stands for like elixir script so all of your code that you're going to ship to production is almost always going to be
01:13:59.600
um an ex file ex are compiled to a beam bite code and EXs is um Elixir script
01:14:07.000
that you can run and it will compile it in memory and execute it but it won't spit out a bite code Beam file so if you
01:14:13.239
had something you want to do scripting wise uh you would do EXs so then you wouldn't end up with this bite code
01:14:18.639
compiled in your directory that you don't care about so for like simple one-off programs EXs is awesome so like
01:14:24.320
a lot of cases where you would just write like a simple Ruby script do some like sis admin related thing you would make an EXs because we don't care about
01:14:30.719
the compiled bite code we can just discard that after it runs so we can save this as Rocket
01:14:38.760
EXs and uh if we fire up IEX in the directory that you uh save that file I
01:14:45.440
got to quit out and see where I'm at here basic there we go fire if EX in that
01:14:52.679
directory and then you can oops if I type h and
01:14:57.920
look up uh C uh C is a helper function that takes a list of files or a single
01:15:03.679
file and it will compile and pull it into IEX so if we save that as Rocket EXs I
01:15:10.120
could say C rocket EXs and it compiled and actually
01:15:16.520
executed my program because I had a rocket start launch SIDS so I'll give people couple seconds to get that pulled
01:15:24.600
in so if you want to play with code without having to copy and paste the sourcing I ex as we've been doing all day you see to bring it in compile
01:15:34.679
it so then we have access to our rocket module we can call our start launch
01:15:40.080
sequence and we get a liftoff statement so we can actually walk
01:15:45.960
through that code a little bit can't read that or we need to make
01:15:51.400
that bigger good so we're going to do a little bit
01:15:56.679
of recursion here which is uh coming from Ruby we don't do much recursion at least I I
01:16:03.000
didn't so our rocket the goal of our rocket is to countdown from some yeah go
01:16:16.040
ahead what's the
01:16:21.360
year did you give it single quote or double quote around your double quote that's actually really
01:16:28.600
good I should have mentioned this before so uh single quote is a character list
01:16:33.880
so earling has a historically poor string handling support as far as like
01:16:39.600
Unicode support is concerned uh so earling strings are defined with single quotes so it kind of ends the debate
01:16:46.960
Elixir ends the debate of single quote versus double quote what do I do uh in Elixir it's almost always double quote
01:16:52.440
but you can still use single quote for earling interupt so that's going to be a uh string of characters so if I pipe
01:17:00.480
this to uh enum at zero give me the first uh element of this list I get
01:17:09.000
115 uh so what this is as a single quote it converts the uh single quoted string
01:17:15.960
into a list of asky integer values so a lot of earling libraries will use single
01:17:21.040
quotes but Elixir almost always uses double quotes which is a utf8 encoded binary string so pretty much always use
01:17:27.560
double quotes when you're writing Elixir code but if you're trying to go for earling interop you'll have to call uh
01:17:33.520
string. two car list which we don't really need to get into right now but if I want to convert
01:17:40.000
my name into a character list to get the single quote version I have to actually convert that and you'll get into that
01:17:46.000
when you're doing earling interop we can go to a car character list or from a character list but in Elixir we always
01:17:52.080
use uh double quote and that worked for you now with double quote cool yeah it was actually a great
01:17:57.679
question I'm glad you had what is the so banged in Ruby indicate M
01:18:06.600
Bang Yeah so bang in uh where did
01:18:14.719
I oh okay yeah so bang so bang and Ruby we kind of use it for two ways bang and
01:18:20.080
Ruby is either mutation or it can raise an error at least I've heard people use it um Elixir you never ever use a bang unless
01:18:27.360
you potentially raise an error is a convention and since there is no mutation I guess there's no other
01:18:32.520
interpretation of it so bang and elixir is saying I may raise an error and uh
01:18:37.800
there's a version of two car lists without the bang that returned me a this is called a Tagged tupple so a common
01:18:45.040
convention in Elixir and earling is to return a tle from a function and the first value a lot of times will
01:18:51.199
literally be okay saying like this was okay this worked and the value that I requested and then if it didn't work I'm
01:18:57.520
trying to think I'd have to paste in an emoji can I do that from the terminal command options oh my gosh it
01:19:06.440
worked okay so if I want to convert this to a character list um okay it shouldn't have worked
01:19:14.520
so Elixir has actually fantastic Emoji support and
01:19:21.480
uh I wish no no seriously I wish I could uh I gave a macro talk at earling
01:19:26.760
factory and uh I show how this is done at compile time it literally takes the entire uh known like utic code database
01:19:33.800
and compiles it to a bunch of pattern match functions uh so like there's a ton of functions dealing with Emojis because
01:19:39.679
they're just they're just Unicode code points so every emoji that exists Elixir can mutate and handle properly whereas
01:19:45.199
like Ruby if you tried to pass an emoji to a stream it freaks out so there's fantastic Emoji support which is just
01:19:51.600
great right um in fact like even in Ruby I'll give
01:19:57.440
you an example I use the I use this in my earling factory talk if I want to take
01:20:03.560
the string Jose oh man where's my uh option eight
01:20:11.440
option e oh my gosh option option e yes okay so if I want to
01:20:20.280
upcase Jose and Ruby it's like o doesn't quite work right the E is an upcase so I I wonder
01:20:27.440
if like Jose has such great Unicode support because his name has a Unico
01:20:32.880
character I don't think so but I use this to pick on Ruby a little bit because like this is so trivial we
01:20:37.960
should be able to upcase strings in Ruby 2.1 properly and that fails such a trivial thing and we test this out in
01:20:45.639
Elixir I pipe this to string upcase bam it converted that e to a cap
01:20:52.239
letter and um this looks so trivial but this is huge like go to any mainstream language
01:20:57.280
today almost all of them fail UPC casing uh that code point and elixir properly
01:21:02.480
maps all these things and does it in a very neat way that if we have time this afternoon I'll show you that it's taking
01:21:08.199
like a fat text file and then defining like thousands of functions off of it pattern matching on like the lowercase e
01:21:14.760
and then returning an uppercase version uh so our rocket module is uh
01:21:22.400
just has a few simple functions that does some recursion so we can see uh we're kind of tying together some
01:21:28.199
Concepts we have like a start lot sequence which is a public function the first time we're seeing defp uh defp is
01:21:35.760
a private function so we wouldn't be able to invoke that private function outside this module and uh it's my
01:21:41.880
convention to Define my public and private functions by each other based on where I call them some people throw them
01:21:48.159
like in Ruby a lot of people it's like you say private and you list all your private functions I mix in match based
01:21:53.520
on my needs uh so we have like a start launch sequence public function and we
01:21:59.040
get this uh default 10c argument here so this is a single uh aity start launch
01:22:05.760
sequence but I can call it with zero aity because I give it a default of 10 and the default uh notation is uh
01:22:13.560
backlash back slash which uh some people frown upon saying like what why is that
01:22:19.719
um and one reason is because our our equal operator like in Ruby we would write it as from equals 10 and this is a
01:22:26.719
pattern match and this is valid but we are pattern matching on from equal so if
01:22:32.239
I recompile this this is totally valid let's go
01:22:37.760
back go oh I'm trying to call here we go get
01:22:43.920
rid of that it's going to warn you that you're redefining the module that's normal so
01:22:50.040
if I want to call start LOD squits again it no longer has a default argument so it's going to blow up if I try to call
01:22:55.159
it but if I try to pass in like 20 there it blows up because it was performing a pattern match by passing 10
01:23:03.600
it works uh so equals is not assignment here it's a pattern match equals is
01:23:09.040
always a pattern match if it's a variable on the left hand side it will bind it to a value but if you pass in
01:23:14.239
from and it wasn't 10 it will perform a pattern match of the thing on the left thing on the right it would blow up with the mash eror so is patter matching like
01:23:21.600
that ever useful extremely useful like in in the parameters like that yeah oh yeah so
01:23:27.840
instead of writing um try to go through some examples instead of writing a lot of if cases in your functions we would
01:23:33.080
Define multiple here it doesn't make sense we could Define multiple start launch sequence functions each of them pattern
01:23:39.520
matching on a value and invoking that function based on the pattern match instead of like if this do this else do
01:23:45.320
this yeah does that do that from top to bottom okay yes you had like dep start
01:23:50.440
launch sequence zero it would just do lift off and then death start launch sequence from yeah exactly this actually
01:23:57.760
both your questions um work out perfectly with a countdown example so what our launch sequence does once we
01:24:03.719
get rid of the uh whatever variable they pass in is 10 I can call countdown and
01:24:09.840
countdown is defined twice so if we countdown in our current count is zero
01:24:15.360
we call blastoff otherwise it's going to be some seconds we don't care what it is
01:24:20.800
we print out what the current number of seconds are and then we recursively call countdown passing in seconds minus one
01:24:27.760
so in this example I'm not actually storing this as a value but if I was doing something with seconds I could say
01:24:33.159
seconds equals zero here and um that'd be totally valid so you use you bind
01:24:38.400
variables with pattern matching in arguments um all the time so instead of like you know in rubiko we might say
01:24:44.280
like well if seconds is greater than zero like a lot of like programming 101 recursion would say okay like what's our
01:24:51.719
the case where we need need to actually spit a value back then we call blast off um but we don't use if statements we
01:24:57.199
could um but the pragmatic approach is we're going to use pattern matching because your program reads almost as
01:25:02.360
like a series of specifications verse um using explicit like if control flow so instead of like all these branching
01:25:08.520
conditions you're program literally like from top to bottom this is a very simple example but from top to bottom immediately I know if I pass zero to
01:25:14.920
countdown I have totally different specification I'm blasting it off if I have countdown that's uh any number of
01:25:21.480
seconds then I some other uh Behavior Uh so has everyone grasp at least the recursion and pattern matching
01:25:27.119
in this example uh pretty simple but um very powerful and then we
01:25:39.400
yeah how do you decide so in my personal opinion if you
01:25:44.440
can pattern match almost always pattern match because the the conditional and the function and this I guess comes down
01:25:49.679
to style but for me um the virtual machine has been optimized for pattern matching for two decades and it lives is the
01:25:57.119
heart of like all the code that you write so instead of thinking about your programs as like conditional branching
01:26:03.280
um literally by defining them in pattern matching it changes the way at least I think about code so it comes down to style but if this was like a if else
01:26:09.920
case for me that would be harder to parse than reading through um some pattern match definitions but it it's
01:26:15.440
style but I would say um at least the code that I write has very few uh if logic branching because I'm using
01:26:21.280
pattern matching instead but it comes down to personal preference and then here we have a guard
01:26:28.320
statement so if I wanted to call start LOD sequence um I could say when from is greater than zero and when from is less
01:26:34.679
than 20 and that would literally Define a function that only responds to uh those cases so if we go back and try to
01:26:42.880
I got to recompile if I try to invoke this for like 24 it's going to blow up with a
01:26:48.800
function Clause error so literally as far as the virtual machine is concerned no no function exists to invoke start
01:26:54.360
laun sequence 24 and that's the way I want you to start thinking about functions is like they have their own uh
01:27:00.360
signature yeah is there a way to list out for a given function name andity in
01:27:07.280
a module what patterns will match uh I have to in what example like
01:27:14.480
well in this case you know there's a there's a condition that this definition that your cursor is on can only match
01:27:21.360
when from iser Z in Fr is less than 20 y so would there be a way to query the
01:27:27.040
system and say I want to know under what conditions there is a match for start launch sequence aity one oh I see um
01:27:35.239
it's a good question let's we can say I don't know if you can get that
01:27:42.199
granular there's some metadata to find on the module by Elixir it's like this
01:27:47.400
special underscore underscore info uh but we only get aity so okay um at
01:27:52.719
compile time if we wrote a macro we be able we would be able to get at that and look at what they were passing to win but at runtime there may be some trick
01:27:59.719
but I'm not wor of it okay I just I mean it obviously exists in the the BR machine yeah it has some logic to go but
01:28:06.960
uh that's beyond that's beyond my level but maybe there is that's homework you
01:28:12.280
find out let me
01:28:17.639
know a question yeah
01:28:34.560
yeah so um so you're saying like we have countdown twice here when I call countdown here like how does it know what what is it going to get a call so
01:28:41.239
in this case um so functions are defined by name and aity they both have zero or
01:28:46.600
they both have a one aity right they both take a single argument but the viral machine got a pattern match from
01:28:51.679
top to the bottom so when I call countdown right here if countdown was 10 it's going to say okay function pattern
01:28:58.840
match the name is countdown value is 10 okay that didn't match value here is 10
01:29:03.960
well it's just going to buy a variable so it's going to invoke that definition I pass zero it's going to pattern match
01:29:09.000
from top to bottom and then invoke zero so this is where pattern matching comes in where it's almost overloading uh but
01:29:14.639
not it's literally defining a function with a signature of name aity then we can have some guard Expressions does
01:29:20.159
that make sense yep so if I defined a countdown uh below like this since the
01:29:27.360
top one is more generic it would go forever so we can we can play with
01:29:36.960
this oh oops oops so that's one thing to keep in mind
01:29:42.760
you want to go from more specific to less specific also oh did it oh yeah yeah you're
01:29:49.880
actually right so it will warn that yeah if you ever see that you probably
01:29:55.960
want to take a look for that exact case yeah yeah the uh the compiler is going to warn you that uh you have an
01:30:02.400
ambiguous Clause yeah so I noticed that you you are just doing seconds minus one
01:30:07.600
you're not doing seconds likeus equals one so there's no mutable state in this is that right like yeah so Elixir put a
01:30:13.960
countdown on the stack like 10 times or something that's actually man you guys are like a perfect with questions
01:30:19.000
because I I'm forgetting to mention stuff yeah so if anyone familiar with tail call optimization this is tail call
01:30:24.679
optimized so as long as a function ends in another function call it's tail call optimized so there is no stack Overflow
01:30:32.239
cases so um it's going to T optimize that it's not going to build up all these things on the stack it's just going to T optimize it there you go yep
01:30:41.239
go ahead sorry one more um is the death be countdown open friend zero close friend
01:30:48.159
is would that be the same as saying death countdown of seconds when seconds equals zero y okay so you're saying uh I
01:30:57.040
could say and then uh
01:31:04.440
oops like this yes yeah that's uh it would be synonymous and the same as
01:31:10.000
doing seconds equal zero inside the parents so you're saying I could say
01:31:15.159
seconds equals Zer here yeah and then uh this should work it
01:31:21.320
wouldn't be are necessary because we don't need that value but yeah
01:31:30.239
so yeah yeah so it's like it's one of those cases where both the win guard and
01:31:36.080
the assignment is unnecessary we could write it more succinctly without but
01:31:41.520
yeah totally valid so when begins you can make something more specific um just by using a gar Clause so like you were
01:31:48.320
saying like if I had uh the function signature could look on nearly the same
01:31:53.440
like this but that's still more specific because of the Guard Clauses and original machine's fine with
01:32:00.000
that cool everyone good on this any questions ESP with a
01:32:10.840
recursion I have a question regarding and long it's not allowed to use a
01:32:17.920
function yeah so we couldn't uh let's say uh what's a good rocket term here so you're
01:32:23.760
saying if we were going to have like a
01:32:29.159
is about to explode and like we're really
01:32:35.320
pessimistic so yes always so we're saying if we're counting down and it's zero yeah you're saying if
01:32:42.840
we want to say is when about to explode oh is we can't do that um it will not
01:32:49.719
let us so it it should actually give you a help warning is that your question if we try to do something like this yeah um
01:32:55.440
so we're restricted
01:33:02.360
to yeah cannot invoke function cannot about to explode inside guard so it we'll pick that up and warn you um that
01:33:08.320
can't happen uh so this is where you would have to either write an if statement in your function or um often
01:33:15.600
times instead of ifs I will write another function that will then pass is about to explode the value of that to
01:33:21.920
countdown so then we could say is about to explode as a first argument and then we could pattern match
01:33:27.679
on that and say oops I could then discard it to be
01:33:35.040
explicit I then we can still get that pattern matching nicy without if else if else that makes sense um but no we're
01:33:41.159
limited to I have a list on uh the previous section I think it's it's exactly syon with earling we have all
01:33:47.880
those type check functions um we can't use like the andand or like oror operators it has to be the Boolean and
01:33:54.520
or and the reason why we're limited on guards is because it's really highly optimized so we can't do our own
01:34:00.040
function definitions because then it would literally have to invoke those functions and we'd kind of lose
01:34:06.400
performance but you could write a macro if you do this um so if you wanted to get really fancy you could write a macro
01:34:12.400
that literally would look like is when about to explode and you can compile that down to like an if and do something
01:34:18.800
crazy and it would look exactly like what we saw but um macros are amazing but then it's a
01:34:25.440
whole like with great power comes great responsibility
01:34:36.600
Clauses here's a I'm not going to type this in but we had like that case expression on Anonymous function before
01:34:42.960
uh it's kind of neat that Anonymous functions can take multiple function heads and pattern match on each value so this is almost like a case expression if
01:34:50.159
I had some like process input function that took like a command and then like the number of spaces that the player wanted to move I could say that process
01:34:57.480
input is equal to anomymous function FN but then I can give the function multiple function heads and it would
01:35:03.560
pattern match on each of these almost exactly like you would write a case expression and would evoke the first one
01:35:08.880
that matched so that's kind of neat so you could give like an Ena map pattern match on a bunch of function
01:35:14.800
Clauses and uh do something neat with that each of those is like a separate function body yes
01:35:22.360
correct so it would be like uh have that
01:35:28.440
still have an example of
01:35:36.840
this somewhere I don't know if this is going to be very clear but like I'm trying to
01:35:43.000
do some transformation that I can pass to Ena map here and then I'm doing uh some weird syntax doing some like binary
01:35:49.400
pattern matching on a map operation it's going to whatever one matches it's going to invoke the resulting map
01:35:57.080
operation um so I use this in real life you're not going to use it a ton but it's still pretty neat that it
01:36:03.800
exists can you like line 91 and Line2 I can't tell
01:36:09.679
that those aren't part of this like lines one and two of the same function as
01:36:14.800
to yeah I mean some cases I would probably recommend just piping that um
01:36:19.920
calling a function instead of a multiple function heads but Lally since I start FN right here at the top I have FN and
01:36:27.600
then I have end and then anything I put in between is almost like a case block where I have a dash rocket thing on the
01:36:34.280
left is the expression thing on the right is the function body is that
01:36:39.960
clear so that's pretty cool and then we can get into uh our
01:36:45.760
modules can Alias things import things and uh there's a require keyword as well
01:36:51.080
and and these let you do things uh pretty self-explanatory so if I have like a uh converter module and I want to
01:36:58.360
Alias an earling Library so earling library is always referenced by like adom so earling uh the math Library if I
01:37:04.800
want to Alias that as something more Elixir friendly like capital M math can define a converter and say Alias I have
01:37:10.920
this earling module of math I'm going to say Alias that as capital M math so then anywhere in my module I can then
01:37:17.480
reference it by capalm and then if I want to import functions from another module I can say Okay import from that
01:37:23.880
math Library uh if I leave off any second argument it's going to import all functions all public functions otherwise
01:37:30.440
I can say import okay only give me the pi function a zero so you can like
01:37:36.000
selectively import functions from module
01:37:42.040
all I think you have to you actually have to explicitly spell out the erity and uh you can do that so one
01:37:48.000
thing uh one reason why keyword lists exist is is because they let us Define uh multiple
01:37:54.599
keys of the same uh value of the same name and that's totally valid so keyword
01:38:01.000
lists um some people are like that why not use like Maps instead which Maps just Le in the language which are just
01:38:06.840
like Ruby hashes a little more performant um but keyword lists are still really nice because we can store multiple keys of the same key but then
01:38:14.440
we can have different values and it works out really handy for doing things like importing when we have a function
01:38:19.520
of the name Pi p takes a second argument but if it did we could say import Pi 0
01:38:24.639
Pi 1 and then we can reference it like math cosine here since we aliased it and then
01:38:31.639
Pi we can call directly because we've imported it so pretty simple but you'll constantly be aliasing and importing
01:38:37.320
things uh one thing that trips people up initially is elixir has no name spaces other than what you define yourself uh
01:38:44.440
so I'll show you rear World example I have a the framework I'm working on is called Phoenix it's an Elixir web
01:38:49.719
framework you examine uh any code in here you'll see like a ton
01:38:55.119
of uh aliases so like I have phoenix. router.
01:39:00.400
mapper that's just my own personal name space um so I don't have any name clashes but then I have to Alias any
01:39:06.159
other Phoenix router Nam space because it doesn't automatically like know that it's in a phoenix router um name space
01:39:12.920
if that makes sense so I have like uh Phoenix router errors is another module if I want to reference errors within my
01:39:19.800
Phoenix router mapper I have to actually Alias it first so there's no automatic uh name space awareness you actually
01:39:26.159
have to create aliases for that and this looks like a ton of aliases normally you don't get into this many but the Phoenix
01:39:31.679
router is doing like a ton of metaprogramming so it's a little bit complicated yeah how does that Alias
01:39:37.000
work you don't yes perfect because I would have forgot that uh so Alias by default if I
01:39:43.239
leave off uh any second argument this is synonymous with saying as path so if you
01:39:50.440
leave off second argument it's got to automatically assume the last dot whatever is the thing you want Alias
01:39:56.159
perfect question so it's actually kind of a nice guide tells these are the things yeah exactly it's actually um I
01:40:02.679
don't mind it but coming from uh Ruby a lot of people initi are like all this boiler plate just to use my um own
01:40:08.360
modules but it really in practice isn't too bad yeah go ahead um this reminds me
01:40:13.880
of Python's import and I'm just wondering you know just estimation from
01:40:19.880
somebody who's more experience like so how hard would it be to write a macro that takes like a name space and then
01:40:26.679
just lists off a bunch of things that you want to Alias from that namespace so you could write from Phoenix
01:40:32.880
router oh I wanted these three things Phoenix router use path resource context
01:40:40.080
scope context errors math um actually it would be trivial and um I've never
01:40:46.280
considered that but I think that would probably be a good language Edition because yeah why not like all these uh um three things should like be able to
01:40:53.320
take an array or something so yeah and the actual macro if we have time this afternoon um I touch on Macros um but
01:40:59.719
it's a whole another topic and very difficult if we have time um I'd love to explore this because it would be a very simple macro to do
01:41:10.560
that and uh just to give you an idea of Phoenix I just want to plug it a little
01:41:15.599
bit because we have a bunch of rails folks here this is a phoenix router and it might look very familiar to you
01:41:20.920
coming from rails I'm not trying to recreate rails entirely but um elixir does give us a
01:41:27.239
metaprogramming a macro system that lets us do like resources users do resources comments and we can then generate a
01:41:33.679
bunch of code at compile time that does a bunch of neat stuff so it's it's very
01:41:38.760
very
01:41:48.719
cool and here's I my next section is actually macros but this is not an exhaustive uh list I debated whether or
01:41:55.840
not introducing macros uh because it's a pretty Advanced topic um but I want to
01:42:01.000
get people a little bit uh give them a taste because macros are why I'm here today probably um I love met programming
01:42:07.320
in Ruby I love being able to define a router like we do in rails so if Elixir didn't have macros I guarantee I
01:42:12.960
wouldn't be staying here today so I want to give you guys a little taste uh so macros essentially are just code that
01:42:18.800
writes code if you've ever heard that terminology uh so let's pretend uh in
01:42:24.599
Elixir that the unless keyword didn't exist they just give us if and you say like ah I come from Ruby I have to have
01:42:31.040
an unless keyword and we can write that uh so we can define a module uh macers
01:42:36.920
have to be defined in modules which we can then import into any name space so I could Define a condition module and here
01:42:43.520
I named it l instead of like unless I could I could override Elixir unless but I could say like less to be like I don't
01:42:50.440
know unique so I can define a macro with dep macro and the most important concept
01:42:56.320
with macros is macros they look just like functions right like okay we have a couple arguments but macros uh get the
01:43:02.639
actual abstract syntax Tree in Elixir so instead of getting some like boan result as an expression they will literally get
01:43:08.639
the a that we can then manipulate in Elixir so I can get some condition
01:43:15.639
expression that someone gave me I can then generate my own as with quote do
01:43:20.760
some as manipulations and convert it into an if not expression is what we do here and uh let's play with that before
01:43:28.000
we jump into what that's actually doing so an Elixir quote is going to take an
01:43:33.239
expression and give you the actual Elixir as back so I can say what is 1+
01:43:38.560
one in Elixir actually so we're looking at the Elixir as so when you compile your code this is
01:43:44.880
the abstract syntax tree and the neat thing about Elixir is it's in all in
01:43:50.119
Elixir own terms so Elixir can be entirely represent your Elixir source code can be entirely represented in
01:43:56.280
Elixir own data structures and that makes it insanely powerful to write meta programming because we can get any code
01:44:03.280
representation and an Elixir own data structures we can then evaluate it a compile time do whatever we want with it
01:44:08.960
manipulate it generate some other code from it and uh it's not any like extra special syntax uh so like 1 plus one we
01:44:15.639
can see uh is a three element tle so uh it won't get too granular all of your
01:44:21.080
Elixir code everything you write comp compiles down to a three element tle in
01:44:26.199
the first element is the function name and then the second argum argument is
01:44:31.480
metadata so we can see like the context is Kernel and the last argument is the arguments to pass to the first argument
01:44:38.840
of a plus so if you're coming from like a list background like this blew my mind let's quote Elixir has a built-in div
01:44:45.000
keyword so I'm I divide four by two get two so if I quote that
01:44:52.239
you can quotee anything get the representation if we ignore this context here what we end up with is like
01:44:59.119
div some metad data and then 42 right um I did a tiny
01:45:06.760
bit of lisp in college but not much like this is basically what uh lispers write
01:45:11.880
right you replace the brackets with pins this would be essentially what Lis is doing uh so for me like that almost like
01:45:17.840
blew my mind once I realized that because Elixir is essentially giving us a uh syntax maner over this simple
01:45:26.400
structure but under the hood it's just all like a simple uh so like lispers
01:45:31.440
literally code almost the ASD directly but in Elixir we operate on top of that but we can still dump down jump down get
01:45:38.159
out that um abstract SX tree and manipulate it uh so if we want to quote like an if
01:45:44.040
expression we can see if I Define a macro it's going to get the as if we quoted a value and and then amro's job
01:45:51.360
is to take an as and return an as so immediately go into a quote because we
01:45:56.480
want to return as back to whoever called us and then we just write some Elixir
01:46:01.560
code because remember quot all Quote does is return an EST if I want to interpolate a value into the as I use
01:46:09.000
unquote and um if you're not familiar with like I think like the term like quote and unquote comes from uh I think
01:46:15.320
list closure does it too right yeah um initially this might seem unusual but the best way to think about quote
01:46:20.679
unquote is like string interpolation for code so if I have some expression um outside this a I'm generating if I want
01:46:27.520
to interpolate that into my quoted a I have to use unquote so it's almost like
01:46:32.719
if I had a variable in a string and I want to inject the value of that variable into the string um that's what unquote does for us so I say if not and
01:46:40.840
then I want to inject the value of as directly in that spot so I just say unquote expression and then any options
01:46:47.679
are just going to be the do end block so in elixir um I can say if whatever comma
01:46:53.560
do in and that that do in is going to be our options and we can just unquote it directly in place so literally that's
01:47:00.159
all that's required to write our own like unless macro so you could copy and
01:47:05.400
paste it in place to play with it I have and condition ma macro and the only caveat is you have to require it to
01:47:12.880
ensure that its macros are in scope here um in practice I don't think I've ever
01:47:18.599
written uh I've I've never used the require keyword in elixir in my own code because at compile time everything is
01:47:24.679
already um required and anytime you import a module it is required so I've never explicitly required one in my own
01:47:31.080
code but if you ever are playing with these things in IEX you need to require the module before we can actually invoke
01:47:37.000
it's list macro so I can say condition. list
01:47:42.840
uh 5 5
01:47:49.320
do and I get
01:47:55.560
nil yeah I should be able to import condition
01:48:03.800
then yeah so if I I can import modules directly into the scope here you
01:48:09.639
basically language yeah so what macros give you literally just like Ruby you
01:48:15.040
can make dsls and you can literally add things to the language and what josea said which is really neat the best way
01:48:20.960
to think about this is like program languages over time um fall out of favor because they become outdated and you you
01:48:27.840
basically you start pram languages are written and then they're they get they're not mutable enough to change
01:48:32.920
that um eventually something else Rises up to replace them but Elixir basically gives us all the main building blocks to
01:48:39.040
Define our own keywords in the language so if some new requirement comes up later in the future and you said like I
01:48:44.360
really wish that existed in Elixir like if you're trying to think in Ruby like I really wish the pipeline operator existed in Ruby you couldn't do it that
01:48:51.480
I've seen um but in Elixir the pipeline operator itself is just a macro it's like literally if we if we looked in the
01:48:56.880
Elixir source code we would have def macro left right do and it would
01:49:02.679
transform the left right thing into a um Reb backwards print expression uh so we
01:49:10.000
have access to all this power uh directly can you quote it yeah so the
01:49:16.960
only caveat is we can't define the pipeline operator is special that you couldn't just Define your own like you
01:49:23.199
know star star B operator um pipeline operator specifically is supported by
01:49:28.719
the compiler but if we wanted to say you're saying we want to quote like
01:49:34.679
uh hello maybe pipe it into iuts or
01:49:45.159
something so let's see if you can rep this so this is saying we just have a
01:49:50.599
function pipeline let try to
01:49:56.040
see didn't really format it very well can I in let me try to inspect that uh a
01:50:02.320
pro tip is like you know in Ruby if I I can get the previous value in IRB using the under bar in uh The Elixir shell I
01:50:09.400
can say vga1 I can go back the number of previous commands I
01:50:14.440
want so now I have the result of that so if I inspect that I inspect should
01:50:20.480
pretty print almost any data structure here we go yeah perfect so we
01:50:25.719
can see we get a three element tupple back three element tle is saying here's this function uh it's going to take list
01:50:33.040
of arguments first argument is low which is another three element tupple so like elixir itself um is
01:50:41.679
composed of three element tles like I said and it's basically un up with these stacking three element Tuple scenarios
01:50:47.639
um I don't know if we can Garner too much from this um but the a is pretty easy to reason about um if you get
01:50:54.639
really complex it becomes very difficult but at compile time you could write your own function to get at this and that's
01:51:01.440
what Elixir uh standard ex unit testing Library does there's a single assert
01:51:06.560
keyword so I can say like assert five greater than five and internally in Ruby
01:51:13.360
this would just say if this test failed um let's say if we wrote that in
01:51:18.440
our Ruby test it would say failure got false expected true or got true got
01:51:24.159
false expected true we we get no information from that in Ruby so we end up with things like assert equal and uh
01:51:31.480
it's not that bad but in Elixir the testing framework is just a single assert and if this we wrote this in
01:51:37.560
Elixir we would say test failure um we had five we expected five to be greater
01:51:42.920
than six it's able to actually at compile time U maintain that information and you just assert everything and uh it
01:51:49.360
it maintains uh all of that structure because at compile time it's going to convert this and say okay let's just
01:51:56.159
quote this because asserts a macro it's going to receive the ASD we quote that five greater than six what do we get we
01:52:03.320
get a very simple thing at that we can write Elixir code to say okay we have a three element Tuple the first element is
01:52:09.199
going to be the operator if it's greater than I'm going to run a function of the
01:52:14.280
uh assertion and if it fails I'm going to say print out we expected this thing
01:52:20.719
to be whatever this thing is greater than this thing right so if we want I
01:52:25.840
have a entire talk that we write our own a certain macro online um if you want to check it out literally I'll take you
01:52:31.920
from um no macro knowledge to writing a little testing DSL and um so hopefully it's that enough
01:52:38.960
to see how you can go about these things compile time we can get out a Elixir code in its own data structures then
01:52:44.239
write Elixir code to inspect that to generate Elixir code and um it's a whole
01:52:49.400
like the first Ru macros is don't write macros you've heard that joke and uh because people can get carried away with
01:52:55.639
these things like it's very it's like with great power comes great responsibility and um you end up generating your own language on top of
01:53:02.520
Elixir for me it's it's awesome but it it does have to be used with care like the assert case is a perfect case um
01:53:08.800
doing things like a routing layer like I'm doing I think is enough of a win um I'm actually trying to Advocate people
01:53:14.159
say write macros responsibly not don't write macros I think a lot of people have heard macros are evil so much that
01:53:19.880
that um they're often just overlooked um but you go home tonight definitely look into them and for me macros are kind of
01:53:27.599
like the future it's why I love the language or one of the main reasons so there's Alias import require
01:53:35.520
and that's pretty much modules so we compose modules to write almost all of our Elixir code uh we can import modules
01:53:41.920
directly in a function scope uh so here's a simple example I have I'm just going to call it
01:53:47.480
test um def run within this function I could say import
01:53:56.880
math I don't do this ever really in my code but this is totally valid so only within this function scope would math
01:54:03.639
exist and then I could say just return me pi * 2 I don't
01:54:09.880
know so now if I ran test out run I get Pi * 2 so import and Alias and require
01:54:16.800
actually all three are available at any uh any scope in functions or on
01:54:23.280
modules and it turns out they're all macros and I'll keep saying this everything in Elixir like death module
01:54:29.199
itself death module is a macro it generates some Elixir ASD uh death itself is a macro so if I
01:54:35.440
say HDE it's just def macro def in Elixir
01:54:40.960
source code so Elixir itself is built primarily with Elixir macros so if you really want to get into this read the
01:54:46.880
source code and then it will kind of blow your mind because you can write you could have written this if Elixir didn't
01:54:52.440
have a de keyword be terrible um but you could actually write all of what it's doing so it literally unlocks the uh
01:55:00.679
internal representation for you to write your own keywords in the language and for me that that makes it really special
01:55:05.760
coming from Ruby so there's macros it's a whole topic and uh I have a talk on it if you
01:55:12.760
want to watch that um but I don't have the whole day to go over them but they're
01:55:18.599
awesome um so is everyone here's where we're
01:55:25.320
going to get into some kind of like more Advanced Materials does anyone have any questions before we get into like processes and holding State and anything
01:55:32.840
else this is a really general question but how
01:55:38.000
much that's a great question because people ask this all the time um if you ask on Twitter some a lot of people will
01:55:44.280
tell you you have to earling first uh I started with Elixir primarily um with
01:55:49.920
Dave Thomas's programing L book went cover to cover and just dove into it
01:55:55.560
without any earling knowledge and that was sufficient to get going um eventually um you're going to have to
01:56:02.040
jump down into earling a tiny bit if you want to do any interop So eventually I basically while learning the intricacies
01:56:07.760
of lier and OTP that will get into otps like llings uh standard library for
01:56:13.280
building fault tolerant uh programs you're going to have to get down read earling uh documentation and be familiar
01:56:20.199
with semantics but they're very close to Elixir semantics so um I recommend people if you want to get into Elixir I
01:56:25.960
mean earling is fine earling is great um but just Dive Right into Elixir and eventually once you get past like that
01:56:32.760
beginner level you're going to have to dive down a little bit in documentation um but by that time you're exposed enough that you'll be be good to
01:56:42.280
go so we've talked about Elixir being uh immutable and uh being immutable makes
01:56:48.239
some things really difficult like what if we wanted to create anything what if we had like a
01:56:54.159
class that we just wanted to keep a count of something par program is going to be counting the number of requests
01:56:59.440
we've had per minute like where do we store that state we can't just in Ruby we would just instantiate something or
01:57:05.599
on the thread we would just increment a value every time something happened and that would be perfect but in Elixir we
01:57:11.480
everything is immutable so like how do we actually hold State and this is where uh processes come in and processes are
01:57:19.440
El's unit of concurrency open that real quick they live at the heart of almost
01:57:25.760
everything you do in Elixir so we spawn
01:57:30.800
processes and processes have U mailboxes so literally the ter mailbox is a
01:57:36.320
concept in earling and elixir and uh we can send a process a message and that
01:57:41.800
message can be selectively received and it's received in a mailbox so I could have I could be in my own process
01:57:48.079
someone sends me a message it's not to do anything if I want to check my mailbox I can hop into a receive Loop
01:57:53.400
say like hey is anything on my mailbox if it is I can handle it otherwise yeah is this a system level process or no
01:58:00.360
it's not a system level process uh it's a it's handled entirely by theal machine
01:58:05.960
and we can run like we could spend up and L like a million of them and um so don't think of them they're like incredibly lightweight I forget the I
01:58:12.679
forget what how much memory a process takes but it's tiny uh so you can they cheap I've heard the best way I've heard
01:58:18.800
it term is uh you never think in an objector language like um how many can I
01:58:24.760
what's the maximum number of objects I can create an object oring language you never like think that um same the same
01:58:30.159
thing you think about processes we spin up processes for everything and they're run concurrently and um we never really
01:58:36.280
have to be concerned about going over some Maximum process limit in day-to-day so they're cheap and we use them for
01:58:43.679
almost everything and that's how we achieve concurrency uh so we can spawn a process with spawn
01:58:49.920
and uh if we want to receive some messages we use a receive keyword uh so
01:58:55.360
go ahead and if you have IEX running uh with Spa a process so PID is a concept
01:59:00.719
you'll hear of like process ID so PID is going to be uh the result of spawning
01:59:06.159
some process we give it a function and this is just going to spawn a process and then within this process
01:59:13.199
we want to be able to send it messages so we're going to tell this process hey I'm going to send you some messages uh
01:59:18.719
receive some mesages from me so some kind of sender variable so some other
01:59:23.920
sender process is going to send this thing a message saying uh we'll say what
01:59:31.440
Ping we're going to Ping it so we're going to pattern match on a bunch of receive Clauses I'm only going to list one here I can say I
01:59:39.679
puts ping oops actually want to make this
01:59:46.159
multi-line font's huge So within this Clause I can say IOP puts
01:59:53.560
ping and then I can send send it another keyword back to the sender PID that sent
01:59:59.199
me a message I can send it a message pong so we're going to ping pong some
02:00:04.520
messages back and forth in that so now we have a process
02:00:10.239
that we've spawned it's out there and it's running the neat thing about process is this process ID is fully qualified so if
02:00:18.360
we have ra Wireless this afternoon uh you could I could pass this process ID to your laptop if we were
02:00:24.880
connected on a mesh and you'd be able to send it messages there's no it be it
02:00:30.199
would look identical to this so that process ID is fully qualified on any any network uh that's in a mesh which is
02:00:36.440
kind of cool and we'll see that this happening if that doesn't make sense yet so I can ask is the process alive yes so
02:00:41.840
this thing's out there it's waiting for messages so I'm going to send in a message from myself if you remember self
02:00:47.400
returns my own process PID so self is going to be the I ex sessions process ID
02:00:54.000
I can send a message to uh that PID I'm going to send it a TPP so here's how
02:01:00.320
like where tles come in as like a basic data structure I'm going to send it a tle saying well the first thing is for
02:01:05.440
me so here's a message from me I'm going to tell you ping and oh my gosh it got ping and
02:01:15.119
remember it sent me back a message so it got ping here and then it sent the sender pong but nothing happened with
02:01:21.960
pong right this is where mailboxes come in so processes in Elixir and
02:01:27.440
earling um if you want like guaranteed uh there there are two ways so if I
02:01:33.760
wanted to make sure a process was sent I have to check my own mailbox so if you're this kind of seems uh like an
02:01:39.199
extra step for a lot of people but the way this works is if we have code running out on a mesh I specifically have to check that a message was uh
02:01:46.320
received properly by checking my own mailbox is that ures that if that process died in the middle of me sending
02:01:51.599
in a message there's no way for me to know if it that actually got there unless it sent me a message back if that
02:01:56.719
makes sense so in order to check my own mailbox I can say from our own process
02:02:02.880
receive and then we pattern match I'm going to say I can receive any message I don't care what it is and I'm just going
02:02:08.520
to return it back to uh the console end and we can see we got the
02:02:14.960
message pong so there is a simple process
02:02:20.440
mailboxes and these if you do send again is it gonna output pong as well yeah so
02:02:26.880
that process actually let's see is it still alive
02:02:32.440
no so that process is gone and uh the reason that is is receive only executes
02:02:38.280
a single time so if we wanted this process to stay alive we would have needed to recurse on itself and do
02:02:44.360
another receive Loop otherwise it had no work to do so it died but if we sent 10 messages Mees to that process they would
02:02:50.960
all be in the mailbox waiting so they just ceue up in your mailbox you hop into a receive Loop it executes if you
02:02:56.560
want to go back and execute the next thing you just hop into another receive and we'll do that
02:03:02.920
next and uh processes can be linked uh we're going into this this afternoon with uh lir earling is all about
02:03:09.760
building fault Toler applications so instead of spawning a process I can link the process to my process where if uh
02:03:16.119
that process dies it's going to kill me with it so you can end up building up this hierarchy of processes and you want
02:03:21.719
to say if there's some failure I want that to Cascade up and kill everybody so if I had some API service and the API
02:03:28.000
was down and I was piping that to like an analytic service if both those dependent on each other you know having
02:03:33.639
the API service die the analytic service can't do anything I might want that to Spire out and kill everybody and then
02:03:39.639
try to restart it up by a supervisor and then like go down and restart everything uh so Show an example of that I can say
02:03:46.400
uh processes they go to a spawn link that takes a function spawn link is going to link uh that process to my
02:03:54.320
process and uh can say receive if you receive the message uh
02:03:59.520
boom I'm going to just raise boom which will kill the
02:04:06.760
process so I have some process and if I send it a message uh
02:04:14.000
boom ah I've killed it and I've killed myself but if you notice uh so this
02:04:19.040
error report is a earling error and um I actually our I session died and if you
02:04:25.679
notice we're still in our I session like why does it still work right we're still we're good to go it's because our ex
02:04:31.639
session is internally supervised by supervisor anytime it dies it gets restarted um so a little bit of process
02:04:38.880
supervision there uh so the concept of Let It crash is what you hear from the earling community and and the elixer
02:04:44.079
community and uh it goes instead of trying to like rescue from errors we just let our processes crash and then we
02:04:50.400
have any kind of uh failure and Recovery logic in a supervisor yeah and you do
02:04:55.599
you don't say like this particular type of excep is that because we don't we're yeah so Rays uh just like Ruby
02:05:02.400
take it can also take a runtime error there's some different errors that you could pass I can say runtime error new
02:05:12.679
here or forget the semantics of runtime error but yeah you can you actually you
02:05:18.360
can raise you can Define your own specific exceptions and then raise those and people can pattern match on that and
02:05:25.159
I won't get into that there is a rescue in Elixir so I can do a try rescue block
02:05:31.639
rescue from an error and then pattern match on the error type so if someone raised an eror that I wanted to pattern match and rescue for and do some extra
02:05:37.639
work that exists but um beyond the level of what we're going into but raise with
02:05:43.159
a string is just going to raise a runtime error like Ruby and uh if our me if our mailbox is
02:05:51.679
empty it basically is going to wait forever for a message so if I said uh
02:05:57.679
receive do no one's
02:06:02.880
broadcasting this thing is just going to block forever and wait which kind of sucks sometimes so this thing is just
02:06:09.320
until it receives a message it's should to basically just sit there and pull its mailbox uh so there's an after Clause um
02:06:15.920
that you can say wait a number of seconds so I can say receive some
02:06:24.000
message and then uh after 3 seconds you can say you know timeout
02:06:33.119
giving up or something just going to
02:06:39.880
wait yep it gave up uh so you can develop semantics around uh receiving
02:06:45.239
messages like if I was talking to an API or another process on the mesh so some
02:06:50.320
other node out there there might be some latency on the network I can say okay go try to do this thing so send a project
02:06:55.480
ping and then I can say immediately jump into receive Loop to get a response back
02:07:01.159
and then I can Implement some kind of logic saying well if it takes more than 3 seconds something terrible has probably happened to that node so I can
02:07:07.199
give up crash myself do some clean up or do whatever I need so that's what you would use after for and um just realize
02:07:14.719
that receive is going to be blocking Forever Until It receives a message sorry quick question on after is that
02:07:22.159
3,000 is that or that whatever whatever value can that be a variable like
02:07:27.360
something that you get from Big File yep okay thank you
02:07:40.199
actually hold State uh so we had to touch on processes first to hold State uh so let's build a counter let's say as
02:07:47.760
a trivial example we want to be able to create a counter module send in a message increment send in a message
02:07:53.280
decrement and be able to get the current value how do we do that in an immutable language so let's see how well live
02:08:00.480
coding works here let's edit create like a counter
02:08:06.400
EXs file so we can create a
02:08:11.679
counter module and we can say well we need to start some process to hold some
02:08:17.440
state so I can create start take some kind of initial
02:08:23.480
count maybe default it to zero what we're going to do immediately
02:08:29.480
is spawn a process and then we're going to say okay listen for some messages but we want to
02:08:36.199
pass in that initial count to our listen function so we want to spawn a process
02:08:41.559
close over that initial account and call listen so our listen function has some
02:08:47.320
current state of account whatever it currently is and what we do is we listen for messages so I can
02:08:54.440
say receive if I receive uh the
02:09:00.119
message Inc for increment what I need to do is my state
02:09:05.880
needs to change so what do I I say okay I'm going to recurse on myself on my
02:09:10.920
process with count plus one right
02:09:17.320
oops
02:09:22.559
oops and if this doesn't click it should click momentarily I receive decrement I
02:09:27.880
want to say okay listen on my count minus one then if some sender sends me
02:09:32.920
the message uh give me your value I want to send the sender back my
02:09:39.679
count and then again just recursive myself with my unchanged count I'm I'm done with my receive block
02:09:47.679
anytime I receive rece a message or anytime I jump in and receive I block Forever Until I receive a message
02:09:52.800
anytime that message comes in I then always recurse on myself with my current
02:09:59.440
state happens here uh it would die so one
02:10:04.599
option would be outside of our receive we could hop back into listen with some current
02:10:10.840
count count plus one and so if I say listen count plus one
02:10:17.960
here it's going to call listen and immediately hop into a receive which blocks for another message that make
02:10:24.159
sense so our listen always immediately hits a receive which will block until the end of time because we have no after
02:10:29.880
waiting on a message and if we throw this into
02:10:36.040
IEX we can say it compiled that's good so I can say I have some
02:10:42.599
process that's going to be uh counter. start and let's start it at maybe 100
02:10:50.000
so that guy's out there should be alive and should be listening so if I send it a message saying hey
02:10:58.000
increment hey increment again again again and if I want the value from it I
02:11:05.239
have to ask hey here's a message from myself uh
02:11:10.520
give me your value again nothing happens right because it sent me back a message I have
02:11:16.960
specifically check my mailbox and say okay let's hop into a receive
02:11:22.159
that thing should be just sitting in my mailbox I've already received it let's say I receive the value and I just want
02:11:29.400
to return it back to the Shell you see it's 105 so now we have uh
02:11:35.880
anyone everyone understand the uh recursion that we're doing here we're we spawn a process and that thing is out
02:11:41.280
there currently receiving and then recursing on itself till the end of time and that's how we hold State because
02:11:47.480
we're always drawing a function that passes our current state in and then does a recurse and a receive yeah I'm
02:11:53.840
sorry and maybe you've covered this and I just missed it about the mailbox but does the mailbox function is a que or does it filter for anything that matches
02:12:01.159
one of the rece matching Clauses in the receive and ignore anything that doesn't match so like there's a term I think I
02:12:07.960
used selective receive probably incorrectly I think there's a way deep in earling to you can get at the current
02:12:13.480
mailbox all the messages and look through them but in this case uh receive is going to execute as almost like a que
02:12:20.960
each time you receive a message just going to go through from top to bottom does anything match these Clauses otherwise nope okay go through the next
02:12:26.719
thing but there is a way we could actually iterate and inspect each value but normally you're going to jump into a
02:12:32.400
receive and then pattern match on whatever the top of the mailboxes me like first first
02:12:38.840
Ino first in P yeah so is everyone clear
02:12:43.880
on this this is uh you the caveat is we don't write too much code like this directly because this is where earling
02:12:49.000
comes in and there's conventions on top of this to not have to do this and um I
02:12:54.280
wanted to write a manual version first uh just to give you an idea of how state is held um it's all through processes so
02:13:01.320
this process could be holding something more than account but the idea is we have these things they're cheap we spin
02:13:06.840
them up they're almost their own actors out there and then we like query them with messages so it's all done with
02:13:11.920
message passing and then what you see typically is uh you would write a client like we call this a server
02:13:18.520
anyone heard a gen server I'm going to try to tie these Concepts together we can almost call our counter like a server we're going to send it messages
02:13:24.400
and we get messages back so we can write a client that queries our counter server sends it messages and we can make a nice
02:13:31.719
uh API on top of this I think I have an example written out
02:13:39.400
here um let's find
02:13:46.960
out
02:13:53.079
yeah so I've already done this so you don't have to watch me type so we can write like a counter. client module and
02:13:58.559
do like a nicer API so we wouldn't have to like jump into our own receives to check everything every time so I could
02:14:05.119
like wrap an API around this and say increment decrement that does my message sending so anytime you're sending a
02:14:11.199
message in your elure code you almost always want to abstract it because like the caller doesn't care the caller wants to perform an action and get a value
02:14:17.320
back so I can say increment decrement give it a process ID and that would just send a message do whatever it needs to
02:14:22.559
do to increment or decrement and then I can make a counter. client. valal get
02:14:27.679
the current value of that PID and that's going to send that process a message and then immediately jump into a receive you
02:14:33.719
get the value back and what this lets us do is just make a nice uh API on top of
02:14:39.159
all this stuff if I paste all that in I have a just start the counter server start
02:14:48.880
and then my client can then queer that server and say hey oops I didn't store the
02:14:56.719
pit so I have the process of my new counter server and I can say counter client uh
02:15:03.599
increment give it that process ID so I should end up with like what three so now I can say counter client.
02:15:11.960
value give me the value of that process I get three what was that Magic you just did there vus one yeah so vus one is
02:15:17.880
going to give you the value returned um one is give me the last thing1 would give me the thing 10 things ago so it's
02:15:24.599
just a nice way to get the last value to be correlate to starting I guess history
02:15:29.920
one up to whatever your step is okay I don't know what that means I
02:15:35.280
don't know why well so so okay is a common
02:15:42.280
returning the atom okay is very common in earling Elixir so it's not unusual to see okay I don't know why a positive
02:15:48.239
value I don't know what a positive value would have represented well it's probably the response to the prompt that
02:15:53.400
has the number in it like 20 the response to 20 was three so if you do V
02:15:58.480
of V sub 20 use negative values to look at the
02:16:03.639
expression values relative to the current one so you're saying positive is what well you see has a number in
02:16:13.760
it 20 now well of course
02:16:20.159
20 oh that's awesome cool yeah learn something new send me a PO request on uh
02:16:27.520
seriously on the like give me start documentation I don't even have V documented so if you want to send a p request this afternoon that'd be awesome
02:16:34.200
so minus one is the last value minus one would be yeah the previous value zero would be the current thing I don't think
02:16:39.320
it would well uh so that's uh holding State and then we would almost always abstract it so a lot of times once we
02:16:45.840
get into OTP you're not going to be doing this kind of stuff yourself but you will be sending messages using the
02:16:51.040
send and receive occasionally and you would almost always want to abstract that it's almost like you know the
02:16:56.080
internal details just like standard our you know objectoriented patterns that we write we always the caller doesn't care
02:17:02.200
what the message uh syntax is it just wants you to do some work and then uh we can register
02:17:08.360
processes under a name so if I wanted to uh say that that counter is going to be
02:17:13.400
named count I could then register that we should be do that here so I could say
02:17:19.000
process uh register give it a process ID and we're going to name it
02:17:24.400
counter so now we've registered that process and people can send a counter uh messages directly and I can ask uh where
02:17:31.960
is that process to see if it exists oops really oh I have to give it the name
02:17:40.920
du so if I wanted to then send it a message later I could say hey give me the thing named uh counter and it's
02:17:47.360
going to ruring that PID so it's a way to store uh messages or to store a process and we could do this globally on
02:17:53.320
a mesh again there's a global that's going to register the process on the current node but if we
02:17:58.760
had like 30 laptops connected all together right now I could globally register uh register name a process
02:18:06.281
which we'll actually do uh momentarily when we run the Twitter aggregator that
02:18:11.840
will say anyone can register a process globally on the mesh then you could look up my process ID of my laptop to send
02:18:18.080
messages to mesh would be uh we connected earling and elixir nodes
02:18:24.479
together then if I send that pit a message it could be running on your computer so message just much noes
02:18:29.880
connected which we're going to try to do right now um so do we still have internet anyone know it would be awesome
02:18:36.639
if we did okay so if we if you have I ex up and running uh CD into
02:18:43.800
the uh Advance or OTP directory where am I
02:18:50.559
at see OTP Source tweet
02:18:57.160
aggregator this is a uh OTP application OTP stands for open Telecom platform
02:19:02.719
which is a great name right so uh OTP started from Ericson as a telecom
02:19:08.200
Library U but it's maintained its name but you can think of it you can think of it as uh earling standard library for
02:19:15.000
conventions for writing distributed fault tolerant highly concurrent applications so it's a set of
02:19:20.240
conventions defined around that manual process U stakeholding that we just wrote and we went through spawn and
02:19:26.880
spawn link earlier so it's a set of conventions around it links processes and if they die you run them and uh
02:19:32.599
monitor them with supervisors so it's doing all these things it's almost like I've heard it termed the rails of
02:19:38.519
concurrency and that's the best way to think about it so there are these processes that we can monitor we can
02:19:44.440
link we can crash U it's a set of conventions around know everyone had 20 different ways to do it so finally
02:19:49.840
Ericson was like let's put a library together to set some San conventions around how most people write these things but it's called open Telecom
02:19:56.880
platform um which is trips people up initially uh so if you're within that directory uh and you have Internet run
02:20:03.760
mix depths. git and for you it'll probably do more than
02:20:10.800
that but hopefully that works for everyone mix uh the OTP Source tweet aggregator
02:20:20.000
so Elixir Express OTP Source tweet aggregator oh have you clone the repo I
02:20:26.120
think I may miss a step wait I I did clone the repo and it
02:20:32.399
just gives me runtime error undefine function
02:20:38.560
deps uh one second yeah mix so Elixir Express you
02:20:44.840
should be able to clone that and we're going to try to run we're going to run a Elixir application but run it across
02:20:51.160
everyone's computer at the same time what's that uh the
02:20:58.960
URL Chris mord Elixir Express clone that to your local
02:21:05.040
machine uh clone it just in like bash and clone it as just a get
02:21:11.319
repo and if you have it clone CD into the OTP Source tweet aggregator
02:21:16.439
directory
02:21:22.040
yeah so so you have this clo and you're you're in that directory U mix depths.
02:21:27.560
git should pull in the dependencies for this project not not an ex Pro that's
02:21:35.280
probably why I sorry probably everyone got the error so yeah outside of EX in
02:21:40.399
bash mixes a build tool that ships with Elixir you can almost think of it um like uh bundler and JY and rake combined
02:21:49.120
so it runs uh you can do like mix tasks similar to rake tasks in your project U mix is also like bundler where I can
02:21:55.319
fetch dependencies specified dependencies and I can say mixed steps. get that will fetch the dependencies and
02:22:01.240
a mix compil for projects so it's like a huge build tool and you can also say like mix new and it would create like a
02:22:07.800
project OTP hierarchy with like standard test directories it's almost like like
02:22:13.319
rails new um so it's a really awesome build tool that combines a lot of gry ideas into
02:22:19.520
one uh so do everyone at least have that cloned and who was able to run mix steps. get successfully well it's
02:22:25.800
running okay we'll see we we'll let it run for a second uh so what we should be able to
02:22:32.840
do if it finishes does anyone have it actually up and running like it's done mix mix steps.
02:22:39.080
gate is finished okay so if you go into the documentation online on the OTP
02:22:44.200
directory Source tweet aggregator there's a me and we're going to try to uh we're
02:22:50.479
going to see if the standard earling port is open and we're going to connect up our computers together and run this
02:22:56.200
program on a mesh uh so to give you an idea what it does I'll run it on my laptop first uh so I wrote this and I
02:23:03.200
wrote it against a single machine and just assumed that it should work on 30 plus and it did um so it was okay this
02:23:11.000
my first time writing like a distributor program when I put this together and I'll run it on my machine uh internally
02:23:16.359
so the goal the tweet aggregator is I have a projector that I want to send some tweets to and all of you guys are
02:23:23.319
going to actually pull Twitter for me make the request to Twitter and then when you get messages back for whatever
02:23:28.680
keyword that you want to search Twitter for you want to send a message to the projector node and display on the projector and uh I didn't want to have
02:23:36.640
all of you have my ooth credentials so I didn't want to have to distribute those so I have another node that I'm going to
02:23:43.040
call the gatekeeper that runs on my laptop that you can send a message saying hey give me Chris's Twitter ol
02:23:49.200
off credentials and it will send you a message back saying here they are so I don't actually have to distribute those to you manually on a thumb drive or copy
02:23:55.240
paste so there's three elements here the gatekeeper you're going to send messages to saying hey give me the O credentials
02:24:00.560
so I can make a Twitter authorized search and if I get any messages back for whatever keyword I want to search I
02:24:06.240
want to send that to the projector node that's displaying all the results so we're doing distributed programming and
02:24:13.040
I can run that all on a single computer to show you that it does work so I'm in my tweet aggregator
02:24:20.040
directory um I have some you're not going to run this I have an ignored EnV file that has my my Twitter credentials
02:24:27.240
that I want to source so I can make authorized requests and I'm going to uh
02:24:33.439
check my IP first for some reason you usually can use like host names but we haven't had good luck with it in the
02:24:38.680
past uh so I'll have to use uh my actual IP address fully qualified
02:24:45.720
name see here depending on how their Network's configured um we'll see if this
02:24:53.120
works okay so I'm going to start up in a IEX
02:25:00.040
node that runs on my uh mix dependencies but I'm going to give it my
02:25:06.359
fully qualified name so I'm going to call this node uh
02:25:12.680
gatekeeper at my IP address and uh cookie uh nodes run with
02:25:19.000
a cookie which really a password um so no one can connect without on this mesh
02:25:24.160
without the password which I name food here the only caveat is uh everyone needs to be good uh citizens here if
02:25:30.640
we're if we're connected together you could you could execute code on my laptop to do anything please
02:25:35.880
don't I will not be very happy um so don't do that but this is going to just
02:25:41.960
run a node on my laptop with the name gatekeeper and S miix is going to say hey run this as a mixed project so
02:25:48.680
instead of running just I it's almost like rails C rails console brings in all your project dependencies we're going to
02:25:53.920
run this tweet aggregator project with all its dependencies in IEX so now I'm in IEX like you would
02:26:00.960
expect but I have access to my tweet aggregator project uh namespace so I'm
02:26:06.000
going to start the uh gatekeeper is a module I've defined I'll go through the
02:26:11.359
code after we get this going uh gatekeeper has a become leader uh function
02:26:17.319
that basically is going to globally register a process named gatekeeper on the mesh saying hey I'm going to start a
02:26:23.800
p I'm going to create a PID but name this on the mesh uh gatekeeper so other people can look me
02:26:28.880
up so it returned yes that's what earling does and you globally register so I should be able to say Global where
02:26:36.279
is name gatekeeper what did I name it it's somewhere on the mesh I
02:26:42.760
guarantee it geeke keeper
02:26:51.760
oh gate underscore keeper so become leader is going to spawn a listen like we saw earlier I wrote this without OTP
02:26:59.680
um but we're going to say have I globally registered gatekeeper and I get a pit back okay that worked so now on my
02:27:08.120
I'm going to create a new uh bash tab but this could be on any computer this is what you're going to do if you get
02:27:13.840
this working and I'm going to start another node named aggregator you're not going to run the aggregator I'm going to
02:27:19.560
be the only aggregator and that's going to run the project dependencies but I'm going to
02:27:24.960
name it uh aggregator at my IP address so uh who has this code uh all
02:27:34.080
the dependency is working awesome so the goal of this is you're going to
02:27:41.840
run oops if you have the uh read me up you're going to run a command just like
02:27:48.160
this but instead of client one you're going to do like first initial last name at your IP address so your IP address
02:27:55.120
has to be correct uh your name could be anything but so so we don't get clashes do uh first initial last name if
02:28:03.120
config uh should give you your IP address if you if have config uh you
02:28:08.640
should be able to get your current Wi-Fi IP address depending on how their
02:28:15.880
uh networks config we may have to switch the port that earling is operating on I'm going to try to do the default um
02:28:21.399
but we had we had a distri we had this running at Panero one day over their Wi-Fi on Port 80 which is kind of cool
02:28:26.760
we had to change ports but it all worked so from my uh from my gatekeeper
02:28:34.800
that I uh started I'm going to try to connect to it so I can say node. connect
02:28:41.000
and I can give it a fully qualified name here so from my yeah could not find
02:28:46.200
Rebar it's a
02:28:52.200
problem it's just a networ only some people some people have successfully done it though right it's the network it's the
02:28:57.920
network okay um try fa
02:29:04.200
okay awesome oh my gosh someone already joined who just joined that's amazing
02:29:09.520
distributed programming so the cool thing is um on all your machines you just joined one of these nodes did you
02:29:15.120
join the aggregator or the GateKeeper
02:29:21.840
okay so do a node.
02:29:29.960
list yeah capital in node. list you should get me which is one node y okay so watch this so you've
02:29:36.720
joined me I've joined you I get just you and I've started this gatekeeper node which is just hanging out by itself
02:29:42.080
watch what happens when I say uh node connect here so I'm going to connect up from my aggregator which you're
02:29:47.960
connected to surround this in
02:29:54.800
quotes did you get a message saying that gatekeeper joined y yeah so do a node listing in so if you join a single
02:30:01.479
person on the mesh you join everyone so by joining a single person the mesh is distributed out so you're connected to
02:30:07.439
everybody now which is pretty awesome so there's no extra Fanfare of like trying to connect everyone together you connect
02:30:12.560
one person you're connected to everyone uh so now what's suppos sorry I didn't think
02:30:20.080
someone was going to connect so quick so uh you're you want to start a client node here so you're going to run uh ex
02:30:27.000
this whole command here you can copy and paste it but do instead of client one do first uh initial last name at your fully
02:30:34.120
qualified IP address with the cookie Fu and DS capital S
02:30:39.479
mix uh Ruby Central that's
02:30:45.439
probably did you just run mixed deps again yeah I
02:30:53.160
think that's just the Wi-Fi failing out and then you're going to node connect uh instead of aggregator
02:30:58.560
1271 it's going to have to be uh node connect aggregator at this IP address
02:31:04.760
here and we'll wait till a few people get on this is awesome I was worried that we wouldn't have
02:31:15.359
Wi-Fi when you run uh any of the I ex
02:31:20.840
commands huh computers cool so we uh so I have a node
02:31:28.000
monitor process that's actually just hooking into joint events that's going to print out to everyone's
02:31:34.640
console uh so now I want someone to send my gatekeeper a message so you should be
02:31:40.920
able to say uh oops in your shells you should be able to say tweet aggregator gatekeeper
02:31:48.880
do access token uh oh should be able get an access
02:31:55.040
token
02:32:00.240
here hold on that's a
02:32:07.720
problem it's my gatekeeper online
02:32:13.399
here sorry give me a second I'm confused on which tab I'm
02:32:26.960
in uh just try again some people have um had issues with that okay for some
02:32:32.920
reason my gatekeeper is not providing its access token I may not have sourced uh I got to quit
02:32:41.760
Out Source
02:32:48.439
what's that yeah yeah but you need the gatekeeper access tokens first uh I
02:32:53.600
don't I may not have connected him properly
02:33:00.160
no no we're not we're not even hitting it yet but we will and we will hit a rate limit uh pretty
02:33:09.560
quickly No it should be it should be fine um some
02:33:15.160
reason
02:33:29.000
uh no one no one has tried to become leader on the gatekeeper right okay don't do
02:33:37.160
that you may have had like a net split with a wi I only have one
02:33:45.160
person what it's probably the Wi-Fi being a
02:33:53.720
problematic yeah I should have rejoined let me try one more
02:34:00.800
time you should see gatekeeper join here
02:34:06.800
hopefully is a gatekeeper joined
02:34:12.160
anybody everyone left but me but you're still up and running yeah
02:34:17.800
yeah can you try to uh quit that spit reconnect you again yeah I think I try
02:34:24.319
to rerun there could be this wi-fi is probably falling over but hopefully we'll be able to get something at least
02:34:29.359
some messages going yeah just try to rerun no connect again on you should be able
02:34:37.560
to means I'm rejecting you for some reason
02:34:44.000
yeah okay new plan put out of your session and we're going to run on Port
02:34:50.000
80 it could be we're trying to run on the default aggregator Port it should be
02:34:56.000
uh EPMD uh Port 80 and then uh demon and this is basically going to tell the
02:35:02.040
earling uh to send messages over Port 80 instead of its default we run that from
02:35:07.920
the shell run that from the shell and it should just return you back to console Double Dash demon or single Das single
02:35:13.800
Dash we need to undo that No it should be fine um you if you were trying to play at home when you restart
02:35:20.200
it would be back on default Port but it's not going to hurt anything uh so now we should be running on 480 and
02:35:26.600
let's try to see what happens when we start back up all of our nodes uh the connection should be
02:35:32.920
identical to what you typed
02:35:44.960
before yeah so try to node got connect on the
02:35:50.600
aggregator again I'm going to connect to that real quick over
02:35:58.479
here did your IP change um let's find
02:36:07.600
out computer science yeah 138 66 83 is that is that
02:36:14.920
right science and stuff yes
02:36:21.240
um I mean I'm able to join myself but that's because uh it's on my own
02:36:28.359
laptop was just working um everyone's just getting false let's try rails comp XO Hall see
02:36:37.080
what happens we can leave it on Port 80 it should be
02:36:44.880
fine yeah it's going to change though so but the uh no couldn't connect to the
02:36:52.000
expo
02:37:00.560
hall uh maybe I have no internet but I should have an
02:37:05.640
IP and then quit out if you had those shells running you have to you had to restart them after the EPMD
02:37:12.520
command uh let's see
02:37:19.560
let's see what happens here with this IP
02:37:28.319
address so the new aggregator should
02:37:34.840
be uh this
02:37:41.399
guy are we on expo hall expo hall that's the only Wi-Fi access point I even see
02:37:47.000
right now uh Port 80 so like if you ran that
02:37:52.120
EPMD command it should return you to standard out and it should just be set
02:38:00.200
now are you running in or in your
02:38:05.800
shelf yeah sorry I
02:38:13.160
think sorry which what oh rails comp expo
02:38:21.600
hall that sucks so false it was working before
02:38:28.880
so um so the whole point of this is normally it just works so if you have a
02:38:35.479
reliable Network we'll try for a little bit longer you see if we can get it working the whole idea is I can globally
02:38:41.160
register a process gatekeeper or the aggregator and then when you say send PID boom or Fubar it literally will send
02:38:48.319
it to anyone on the mesh and there's no extra Fanfare there's no extra code to say hey call that machine over there
02:38:54.399
instead of my own laptop it's identical so the code you write to run on one machine you write to run on the entire
02:38:59.760
mesh broadc one who shares about it it's going to broadcast to a single process
02:39:06.040
ID um if you wanted to do something like that there's a build-in thing called process groups where I could say all
02:39:12.399
these processes could join a process group and any message sent to that process group group is sent to all processes like a pub sub type thing and
02:39:19.640
that's supported in the standard earling standard
02:39:28.319
Library no it's just for this to my I mean if you were doing like a if you
02:39:35.040
were trying to sample uh promiscuous mode on the ethernet you might get it any networking but it would only go to a
02:39:41.880
specific mailbox of a that node
02:39:47.920
yeah I think I'm going to blame the Wi-Fi we could try let's try rub Central one more time since it was working
02:39:53.359
momentarily even though we couldn't send any messages um let's try rub Central once and then uh I could walk through
02:40:00.279
the code but the the idea is normally you would just you would pull Twitter you would ask my laptop for its
02:40:05.800
credentials then you would pull Twitter get results and then send the aggregator a message to display on the console over
02:40:12.640
on the projector what your uh
02:40:20.680
it's a good
02:40:28.479
question I think it least me the same one find
02:40:36.080
out so it's that guy oh okay got back quick no let me
02:40:43.160
start with the gatekeeper up because that's that guy is needed for
02:40:51.920
everything started and I make sure you have to use
02:40:57.439
quotes So if you're if you're trying to connect doing a node connect make sure you give it to adom but use quotes on
02:41:03.040
the atom I want to make sure everyone's not accidentally forgetting that this is a good sign
02:41:13.800
though so when you say no connect you give it an adom but you give quotes after the atom so make sure you provide
02:41:26.680
that3 yeah I think so uh so quickly uh someone after I become
02:41:43.479
leader so I'm trying to become leader but it's hanging because it's your the global process registry is synchronized
02:41:50.120
across all nodes so the Wi-Fi is really horrible so did I become it's still
02:41:55.439
waiting so normally this is instant but saying globally registering a process
02:42:00.840
it's actually going to lock the mesh and ensure that only one person at one time can globally register a process and
02:42:06.359
that's handled automatically but stuff is freaking out right now I'm going to blame the Wi-Fi yeah I'm still trying to
02:42:13.960
become leader come on and uh NOP okay am I leader so
02:42:21.279
can someone say tweet aggregator gatekeeper access token yes if that works for you you've sent me a message
02:42:27.319
and there's my private Twitter access token but uh see if you can recreate this you should get a a random
02:42:36.359
string yes okay so Distributing programming okay so that's pretty cool
02:42:41.640
right you sent my laptop a message I'm running a node for just a gatekeeper it sent you back the access token pretty
02:42:47.080
cool so now you should be able to pull the Twitter API so say tweet aggregator
02:42:52.439
this is going to be really robust because I'm not aliasing it uh do
02:42:58.640
search do client pull and then give it an array of
02:43:05.120
streams like uh I'm going to search for Elixir and it's pulling Twitter and then
02:43:11.600
my aggregator is going every 10 seconds your node is going to pull twiter Twitter and send should send this
02:43:17.359
projector a message of the results we'll see what happens now so
02:43:23.520
let me bring that command back up tweet aggregator search. client. Poole and then give it an array a list of streams
02:43:29.840
it could be anything so search for something that you want to search on like Justin Bieber is what I use a lot for testing because he constantly had
02:43:36.200
new tweets so so every 10 seconds it's polling and
02:43:41.439
eventually it's going to exhaust my rate limit U but we should see
02:43:47.160
this is my aggregator right why am I not oh my aggregator needed to become leader
02:43:53.040
so you're pulling you're notifying me but no one became leader of the
02:43:59.800
aggregator the last step this works we should be getting uh messages here
02:44:05.840
on so normally this is it should be instant I think the Wi-Fi is so weak that
02:44:11.920
um it had it had to lock everyone's machines to make sure the process registry wasn't um overwritten by
02:44:17.800
anybody but like all this stuff is handled for you where you can globally register stuff on the mesh and you don't
02:44:23.080
have to worry about someone else trying also to become aggregator at the same time if you did uh your process would
02:44:28.279
actually die so say you were running this in some kind of production scenario
02:44:33.880
yeah what what kind of steps would you what tools would you use to try
02:44:39.600
and what's going on here because I mean it seems like okay well
02:44:46.080
some of these calls are coming back pretty slowly but is there any way to find out why and what's going
02:44:52.800
on yeah so there are tooling that I I don't have much experience with that but there's like a conqueror is a new tool
02:44:58.439
that came out recently oh my gosh it's working Scott somebody Ryan K okay
02:45:04.080
distributed programming so yeah there are tools for debugging these things I don't have experience with them um but
02:45:09.439
you it opens up a new set of problems of like the super programming if there was like a net split for example now you
02:45:15.399
have a mesh that like half of the people are connected to half the people and it's like who's alive and who's who's not alive so you have to handle these
02:45:21.960
unusual scenarios where normally you wouldn't have to handle them um but the coolest thing for this like I said um if
02:45:28.200
we have time I don't know what time it is we we could go through this code and I wrote this using the OTP framework
02:45:34.160
built into earling but writing Elixir code I wrote it on my laptop just sitting on my couch and I had heard that
02:45:40.240
like okay you can just globally distribute these things but I hadn't actually tried it so I wrote it against one machine I I ran new tabs to run new
02:45:47.160
nodes on my own laptop that worked and I was like well from what I've read this should just work on everyone's laptop
02:45:52.279
and now we're running however many no do lists work um there was no extra no
02:45:57.359
extra code is written how many let see we pipe that into enum count how many
02:46:02.439
people do we have connected so we have 21 people running this program on a mesh right now and literally it was the same
02:46:07.880
code to write write it on a single computer uh so that's like the dream I sell people we're getting some crashes
02:46:14.040
here um you may have hit the API rate limit so these are the earling error
02:46:19.160
messages which elix is trying to improve um and they're printed in earling own
02:46:24.359
terms which is a terrible idea so you get earling error messages in like a data structure instead of nicely pretty
02:46:31.160
printed um they yeah so Elixir um it already has a really nice uh err message
02:46:37.680
layer but like since we're hooking into OTP here uh they aren't we haven't yet wrapped OTP error messages so you still
02:46:43.520
get some earing error messages if you you you can um obtain a taste for earling error
02:46:50.160
messages and actually get meaningful data out of them um but for me it was very difficult getting stuff like this
02:46:56.399
at first so there is Meaningful error message data there it's just embedded in a data structure so I don't want to
02:47:02.760
knock this stuff too much um yeah
02:47:08.200
so that's still working is uh so that's OTP we can hop into some
02:47:15.359
of the code while this runs um but your basically your clients are just going to pull forever uh if someone wants to play
02:47:20.680
with this uh I'm going to kill the aggregator node you should see it Le
02:47:27.000
but you should still say connected to everyone else so aggregator is gone um someone I
02:47:34.279
say uh you on the end here D yeah you had good connection
02:47:39.560
earlier can you do a tweet aggregator aggregator becom leer aggregator
02:47:47.720
like tweet aggregator capital A aggregator beore
02:47:53.359
leer and you'll globally register yourself as the Tweet aggregator and you should actually start seeing everyone's
02:47:59.399
messages go to your laptop instead ofor agor yeah it's we should have just I should have had instructions to Alias
02:48:06.040
that we could have just typed alias in Shell in the Shell to not have to specifically do that but error already
02:48:12.279
started I quit no way might passw oh so you're I was like okay so
02:48:20.840
are you getting any messages um getting all those error reports okay so I think some of those may be either a failure to
02:48:28.960
fetch API issue are you getting any any actual tweets we may have hit the rate limit and I don't have any other
02:48:34.840
credentials to I think last time I did this I had a couple Twitter accounts I just like swapped out the gatekeeper to
02:48:40.680
use different credentials um but you're at least getting failure messages so the cool thing is like anyone could hop on
02:48:46.800
and uh like for this example you had your own Twitter API credentials you could Source those I could kill my
02:48:52.439
gatekeeper since I've maxed my API rate limit someone could then say hey I'm going to become the gatekeeper then you
02:48:58.160
could lease out your credentials and then all those clients every time they make a request they're just asking the
02:49:03.200
gatekeeper every single request give me your credentials so it would just work so it's the whole thing like the fault
02:49:09.040
tolerance this is not a great example but for like a beginner scenario we could have we could have each node say
02:49:15.000
if the gatekeeper or the aggregator for some reason becomes unavailable automatically just become the leader and you would globally register yourself as
02:49:21.319
that in earling OTP would actually uh the personal machine would ensure that the mesh only allowed one person to do
02:49:27.120
that so you could have a mechanism say hey become gatekeeper if the gatekeeper fails and like then you know fall
02:49:32.920
tolerance so as long as a gatekeeper is alive it would work you have the all the
02:49:38.160
nodes uh use like their own Twitter credentials like use uh yeah local you
02:49:43.239
could you could have each node use their own Twitter credentials um I didn't the easiest way was for me just to be able
02:49:49.319
to give those out but I didn't want to have everyone just like type them in so it actually worked out really well to make a node be the gatekeeper just to
02:49:55.840
kind of show off this like message passing stuff so if we pull the gatekeeper up um normally you would
02:50:01.040
write this is in what's called a gen server in otp's uh framework but I wrote
02:50:06.800
it in just a by manual uh just manual Elixir just to show off
02:50:12.920
that like how you would do it uh it's very similar to like a counter example but uh here's the documentation I never
02:50:19.520
went over that I can say at module Doc and then give it a string and this is
02:50:24.760
what if I said H tweet aggregator gatekeeper I would get that pretty printed marked down in the console so I
02:50:31.120
can provide module documentation and markdown get at that with the H Helper and
02:50:36.560
uh my aggregate or my gatekeeper is just like I say become leader to say hey the
02:50:42.160
Earline Global mod on the whole mesh register the gate keeper name and it's going to be this PID of a listener and
02:50:48.560
then listen is very similar to what we wrote for our like counter where we just
02:50:53.680
basically wait for some sender to ask us for an environment variable and we kind of protect it from you guys trying to uh
02:51:00.880
ask for like I don't know I had some like secret environment variable on my laptop it restricts it to who asked
02:51:06.399
about the constant earlier they are they still here not okay well you missed all
02:51:11.680
right so uh if I say at EnV ours here in my module uh this is called a module
02:51:17.640
attribute and module attributes it's like don't be fooled by the at sign it's not a ruby like a attribute accessor
02:51:25.319
it's almost like a constant so modu attributes almost synonymous with what we do with constants in Ruby but if I
02:51:31.040
Define some EnV vars it's just a list of uh atoms I can then reference that
02:51:36.279
anywhere in my code with just at EnV vars so it's a way that you would use constants uh in
02:51:41.920
Elixir and um I basically just recurse on listen uh forever and then anytime anyone asks for
02:51:48.920
like the access token oops I just expose this like client I have like the client
02:51:53.960
server written in a single module so if you ask for the access token um I basically call git which is just a
02:52:00.040
function that takes whatever environment variable you have and then this is like the send receive Loop that we saw earlier so ultimately when you say hey
02:52:07.359
gatekeeper give me your access token it's going to say okay send uh whoever the leader is which is going to be me in
02:52:14.000
this case the message whatever environment be you want and then you immediately hop in your receive Loop to receive whatever you expected back and I
02:52:21.200
don't have an after here and this is where I probably uh shouldn't write an after because it will block forever so
02:52:27.680
this is where we were talking about like fault tolerance uh you would do this in a different way if you were writing a
02:52:33.359
real system but for fa tance in this case I could literally say okay well after I try for 5 seconds to get uh that
02:52:41.200
value I'm gatekeeper's got to be gone so then literally I could say become
02:52:46.880
leader so there's fault tolerance so after 5 Seconds of trying to get an environment variable gatekeeper got to be gone I'm
02:52:53.520
going to call become leader and then I'll become the leader and then anyone else asked the gatekeeper for an access
02:52:58.760
token now is asking me which is pretty cool two two noes both try to become
02:53:04.120
leader at the same time so if you saw when I tried to become leader both times of the aggregator in the gate keeper it took forever it blocked my ex session
02:53:10.800
for like 10 seconds um so it will lock the whole mesh every 's machines and only allow a single person to globally
02:53:17.200
register that name okay I mean like for the fault tolerance yeah if so you have
02:53:23.279
you have 10 machines two of them at the same time or like one of them locks and is becoming leader but the other one
02:53:30.680
also hits the after yeah it just it just won't become leader it would try to
02:53:35.840
become leader and then uh I think whatever error message we got before like if I try to become the aggregator
02:53:41.840
it's going to die and say already registered let's see I have a
02:53:47.720
no okay so it should if you try to register it will crash or weer out okay
02:53:54.520
and it would crash your process or whatever you're in okay and hopefully your supervisor would restart you yeah it would it would ensure it would ensure
02:54:01.080
that that can um it would ensure consistency that makes sense you'd have
02:54:06.120
to rely on supervisors yeah so everything uh like your clients right now um this app is pretty big but all
02:54:13.160
your clients are currently super provid you saw those error messages popping up that was your client process polar dying
02:54:18.720
but it was restarted and it kept trying and that's because we have a uh where is it I go into
02:54:30.080
OTP so I have a search supervisor and a lot of this is kind of like mundane uh
02:54:36.000
earling OTP stuff which is like it's a there's whole books on it which you should read if you're really getting into this um but I can create a
02:54:42.760
supervisor for my search uh server that's going to basically pull a Twitter API and I can start a uh worker with the
02:54:51.279
term that they use saying I have this G server which is going to be a a thing that we can quer for values that
02:54:57.319
recurses on itself wrapped in like a uh convention and I can say if uh any of
02:55:04.040
those workers dies there's only a single one I want to uh like one for one there's all these different options one for one says if a worker dies I just
02:55:11.000
want to restart it but let's say if I had um a bunch of polers going if I had like an analytic service that hits a
02:55:17.399
bunch of different apis if one of those failed to hit Facebook and Twitter let's
02:55:22.439
say if one of them failed I want to restart all my workers for some reason that's a bad example but you could say
02:55:28.120
uh one for one you could say one for all and the supervisor would say if any of my things I'm supervising dies just kill
02:55:34.239
everybody and restart everybody so you can have different restart strategies so if you have like all these workers uh
02:55:39.920
depending on themselves and one dies you're going to say whoa okay let's just kill everybody start them because they all have to work in unison and um
02:55:46.960
there's like a ton of different options there's options to say if a worker dies try to restart it but wait 3 seconds and
02:55:54.399
then try to do that like 10 times and if that fails and then kill yourself and then your supervisor would then be
02:56:00.720
notified so you supervise supervisors and then that would that would go all the way up to the application supervisor
02:56:07.399
and if that guy died that's a problem um but you basically you develop your OTP applications as a hierarchy of
02:56:12.600
supervision trees and it's it's just really a unique way to think about programming and for me I I see it as uh
02:56:18.680
the future of the way I'm going to write programs it's a totally different way to think about distribut programming like
02:56:24.399
you know for our uh rails apps we we kind of like sew out maybe we make some rest apis or we can communicate over
02:56:31.000
like a redus bus or something um but there's we don't think about ever connecting multiple asss together in
02:56:37.520
this manner it's always like we have to put a wall between them because there's no convenient way to connect these
02:56:42.560
things um but for the OT TP land you develop different projects you can still like sew out like service oriented
02:56:48.120
architecture but you can have those things all connected on a network together calling uh just native Elixir
02:56:53.680
back and forth and you still develop clients like the the term client and server is still a concept but it's not
02:56:59.880
the way that we would think of them as rails developers it's the conceptual thing of I'm going to send this server a message and I'm going to get a response
02:57:06.000
back and it's all in Native Elixir code which for me is really interesting I see it as as the future of of programming my
02:57:14.080
opion so I think uh Ruby could learn a lot from this but I think we are limited by just the semantics of the language uh
02:57:21.319
so for me my goal is to eventually write Elixir professionally yeah um so
02:57:28.960
how like exting Andes back and is doing super efficient I
02:57:37.800
know between processes so I don't know the I don't know what it's using back and forth I'm assuming it's efficient so
02:57:44.319
like this the neat thing is all this was written around in um Telecom infrastructure initially so if you think
02:57:49.399
like back in 1986 is when they first developed this um and these all these sematics were in place like in the 80s
02:57:55.479
which is kind of crazy like if you go back like even today any mainstream language does not have these semantics
02:58:00.920
um so back then um stuff was a lot more expensive than it is today Hardware wise as far as doing anything computation
02:58:07.479
expensive so I'm assuming it's uh efficient but I don't know the semantics of like how it's doing it yeah I know
02:58:14.479
seems like we're through the demo I was going to how would you do like a IO or talk to a database with the Elixir like
02:58:21.720
if you wanted to pick up a process you know you're working in your rails app and you want to put something on the Queue or have Elixir work on you know
02:58:29.319
certain pieces of it integrate it with your existing yeah so uh Ecto is this may answer your question is anyone
02:58:35.960
familiar with link from uh net okay I've never used it so like link
02:58:42.920
is a uh database like access language buildin toet and uh Jose and a couple uh
02:58:50.200
another Eric um core maintainer of Elixir put together Ecto which is uh
02:58:55.960
basically using macros to write like a database access layer uh so you end up with things like uh I can say I can
02:59:02.920
create like a queriable I'm not going to go through all of this but I can Define like fields that my database maps to I
02:59:08.760
have a City Field it's going to be an integer or a temple O's integer and I can query in this like uh DSL so I can
02:59:15.720
say like from W in weather uh where the precipitation is greater than zero or so
02:59:21.239
I write in uh Elixir code a query and this is a macro that's going to actually
02:59:27.920
uh perform a query for me so it's almost like synonymous with like a link type scenario but literally this is just Elixir code and it's using a macro that
02:59:34.840
from is a macro to take in the of w and we where select W and um convert that
02:59:42.040
into a SQL query uh so this is one option that you would could hook into a database access layer internally they're
02:59:48.239
running a connection pool you may have been asking more granular maybe I mean that's fine I mean I don't know where
02:59:53.840
they you know how you set it up I mean this is this always feels like a an abstraction like
02:59:59.560
um active record but okay so I can show you off I I'll show this off a little bit so I I want to show Ecto first
03:00:06.120
because I see it as the future um but I put together Atlas which may look familiar to you it's a database access
03:00:13.960
ler possibly inspired by active record possibly uh so I can say uh def module
03:00:21.880
user now use is something we didn't go into it's a way to um invoke a macro on
03:00:27.319
Atlas model that does some code generation and then I get these uh macers like field uh so that I wrote
03:00:34.120
this as my first like fourway into meta programming so I can say like field ID integer email string and then some
03:00:41.920
familiar validations and um so I've shipped this this works but um I'm not running it in production and I've
03:00:48.760
started a web framework called Phoenix that um I want to replace my rails development with longterm uh that's my
03:00:55.399
main focus but I would love contributors on this um but you can do crazy things like you know I can say validates format
03:01:01.319
of email I can give it a regular expression just like we would expect in rails and um I can create Scopes so the
03:01:07.720
way you would call this with a pipeline operator is uh like this so I can say
03:01:14.080
you know user wear email whatever and that would return me some kind of query um state right so all of these Wares I
03:01:22.080
have a wear that is a single aity of a keyword list and all the ones I'm piping into I also Define a wear that takes a
03:01:28.319
first argument of the current scope so then I can create queries very similar to ra rails where instead of chaining
03:01:34.359
where I can say user email user example.com type that into user where state is n not null and then instead of
03:01:41.600
querying that off user um I'm using the repo concept like Ecto is and saying we could have multiple repositories in our
03:01:47.960
app that connect to different databases so I can query out um construct this
03:01:53.200
query and then I maybe have some um user repository over here that's connected to a user database that I have uh Define in
03:02:00.200
repo and then repo actually is going to perform the query that makes any sense uh so this is um my experimentation with
03:02:07.319
the databas access layer but um hopefully maybe to inspire you that um we can still do very uh rails like
03:02:14.279
things in elixir in very similar manners has support for similar databases yeah
03:02:19.600
so this is a e Ecto is uh just postest right now there's a play request for
03:02:24.920
MySQL but since Elixir um has had some bigger changes recently there's some work to get that in place um Atlas is
03:02:32.239
just post right now as well um but I'm using uh protocols which I forgot to
03:02:38.040
cover um protocols is the polymorphic layer um and you can also use behaviors which wouldn't get into behaviors are
03:02:44.080
almost like specifying an interface so I've made Atlas in a way that you could Define your own mySQL database driver
03:02:50.680
and plug it into Atlas you would only have to implement like 10 functions and as long as those connected to my SQL and could perform a query you could write a
03:02:57.560
my SQL access layer uh so both Ecto and atas um the goal would be to add
03:03:03.600
multiple database drivers but it's just just post Source right now unless you want to get your hands really
03:03:08.920
dirty and um so yeah so you can do awesome stuff like quers would be composable
03:03:14.200
so I can say like uh Define a scope as like where the site is admin and if they
03:03:19.359
you pass in an email to this user search I can then rebind that scope and keep building it out um so that's that's
03:03:26.960
Atlas and then uh I want to show off Phoenix for a second because this is my long longterm
03:03:34.040
goal is a uh web framework that gives me all the productivity of rails I don't
03:03:40.239
want to recreate rails um because a lot of the concepts don't necessarily map over to a functional language but I want
03:03:46.520
so the dream is a framework that makes me as productive as I am in rails with uh similar conventions but that I can
03:03:52.120
run on a distributed mesh of 50 computers um to really like conquer concurrency and be able to like sew out
03:03:58.560
my app as different um OTP applications but also running on the same mesh together uh so you can do cool stuff
03:04:05.840
like uh I can say you know get the pages page just like you would do in rails it's going to generate some route
03:04:11.399
helpers for me saying like as page here then in my controller I can say like redirect to a page path of that router
03:04:18.640
pass in a keyword list um so I'm trying to develop things uh that are kind of
03:04:24.239
inspired by rails but I'm not just trying to recreate rails I'm trying to um build on top use some like a lot of
03:04:30.040
people like to HTE on Rails especially from the Erland Community when they see stuff like this but uh rails got gets a ton right and it makes me happy to
03:04:37.239
program in so I think that we've had 10 years of innovation and 10 years of people going back and forth on these conventions so I think they should be
03:04:43.880
reused uh so I'm not trying to recreate rails but there's some undeniably good things and uh we should borrow them uh
03:04:51.479
so this is really young but uh it's progressing steadly I have a websocket layer on top as well uh so what started
03:04:58.600
me into Elixir originally was uh I got in anyone heard of the gym sync by chance real time
03:05:06.560
reals partials that I so I wrote sink a year ago maybe and uh I was trying to do
03:05:13.640
websockets in Ruby and eventually I was able to do it through Fay but I tried to get it in place through just vanilla
03:05:19.319
rails and like action controller live if anyone's familiar with action controler live and there's just like there's no
03:05:24.880
concurrency store when it comes to rails trying to open connections and keep them open uh so I H syn and it works really
03:05:30.880
well but it opened my eyes to like how are other languages doing this and then I heard of what WhatsApp at the time
03:05:36.239
running a million connections per server I was like that's pretty awesome I want to run a million connections per server
03:05:41.880
on my rails app um that's what I got interested into to Elixir and just to show off I have a pubsub layer in
03:05:49.720
Phoenix where like you have a oops it's on an issue
03:05:57.399
thread so like wouldn't it be awesome on your rails router you could just say we
03:06:02.680
have a router and then you have your routes I could say in Phoenix now channel give it a rooms Channel and then
03:06:09.680
I Define a channel in Phoenix to respond to some like pubsub messages so I can handle like joining from
03:06:15.359
different websocket connections and I can handle events if you're familiar with like socket iio and node it's very
03:06:20.720
similar I can handle event new message and I can broadcast to that socket all the uh all the listeners that same
03:06:27.560
message and then I have a javasript layer which is like this is a trivial
03:06:32.640
example I I'm requesting feedback this isn't merged to master yet it's very close but the code we've seen why I've
03:06:39.359
scow down is an entire chat app so there's a small JavaScript layer where I can say give me a new Phoenix
03:06:45.479
socket and then I can say hey socket join the channel rooms and then like a
03:06:50.640
topic Lobby and that topic could be like a user ID or anything to scope a uh like
03:06:56.160
pups up broadcast to and then I can say like Channel send so I can broadcast on that channel new message and I can also
03:07:03.760
listen for new messages and then run some kind of call back um so this is where I'm at with Phoenix currently and
03:07:09.800
it's uh it's super young and it's not uh it's not I'm not going to replace rails
03:07:15.200
immediately and I love rails so I don't think it's rails is obviated quite yet but I think that the building real
03:07:21.040
realtime applications and rails is not a fully written story yet I think that as a community we need to focus more on
03:07:26.560
providing mechanisms to do that and I think Elixir is also a great fit for for building out fault to like a bunch of uh
03:07:34.600
Cloud buzzwords so I think it's perfectly suited for like uh highly concurrent High fall uh distributed web
03:07:41.399
applications and hopefully I some that today um but if you want to play with anything now I don't know how I'm doing
03:07:48.239
TimeWise but I'm I'm welcome to answer any questions anything we haven't seen um we skipped protocols but they're in
03:07:53.680
the docs I think we went well beyond that with OTP but if anyone has any any
03:07:59.120
input or anything like like to see so in your mind where does fit
03:08:12.040
today yeah so my so there's a couple options and I'd love to have collaborators so my goal my secret to
03:08:18.680
get it in uh on like actual client work would be to write a uh sidekick
03:08:24.239
compatible uh worker processor as as something that would actually be a real world use case so we
03:08:30.200
had uh I worked on an app that was doing like social analytics hitting a bunch of different apis and uh we were doing it
03:08:36.479
all on Ruby not we didn't try like a vent machine or sell you weight out so we were running every time we wanted to make request for Twitter to Facebook
03:08:43.040
LinkedIn we would run a web request and we would block that worker but it basically got incredibly expensive like
03:08:49.080
on Heroku we would have to run massive amount of workers and it would be like um we would block other users so a bunch
03:08:55.319
of people hit the side at the same time we would max out our workers and someone may have to wait a minute until their
03:09:00.680
API request came through because we were blocking an entire rails process like 200 megas of memory just to wait on API
03:09:07.439
request uh so the idea to get it in place into production soon my goal is this year would be able to write a
03:09:13.920
sidekick compatible worker because we use sidekick and it's awesome you probably make it work with rescue as well because Sidekick is rescue
03:09:19.640
compatible but the goal is maybe we could um do a perform async on sidekick onto a um queue that a an Elixir uh
03:09:28.359
process would be watching Elixir process could pick that up do some work make the API requests it's almost like data in
03:09:33.680
data out the ra app can maybe provide the credentials down to the Elixir app all the data it needed to perform API
03:09:39.160
requests it makes the API requests incredibly efficiently because we can run processes and spin up a million of
03:09:45.399
them you couldn't run a million API requests but then when you were done with the data on The Elixir side you
03:09:50.840
would in a job back on the rails Q side and it would pick it up like any other regular worker does that make any sense
03:09:56.640
so there I have some ideas that some like you know it's I have a ton of fun coding in Elixir so it's not just the um
03:10:04.560
infatuation I think there are some clear use cases that I've hit in the real world that it would be a perfect use case for to like sideline against all
03:10:11.760
the awesome real stuff G us gives us so I think like it would be years before I would be able to replace my rails
03:10:16.840
development um but I think in the meantime there's some clear winds um doing like anything websocket related
03:10:22.600
like that's why I have websockets in Phoenix so quick like there's no view layer currently so I hit websockets first before the view layer because I
03:10:29.880
have a project coming up that's going to be doing some like real time updates some like
03:10:35.080
uh user has like a feed of activity we want to be able to update that in real time so we're coding the project in
03:10:41.560
rails but if I get Phoenix in place stable enough um we're going to have offload that Pub sub to Phoenix so You'
03:10:48.399
create a phoenix channel that ran alongside your rails app you would write your JavaScript doing like Fenix channel. new and all the authorization
03:10:55.160
on The Elixir side the idea of
03:11:08.239
distrib yeah that's what I got into and there's been
03:11:14.520
this
03:11:21.359
ises yeah those are my thoughts so I yeah I I work on Rails fulltime so I'm
03:11:26.600
thinking constantly about how to get this into production um in a responsible way in a way that makes sense and I
03:11:31.880
think offloading um Pub sub anything any like really heavily blocking IO would make sense and um have you started
03:11:40.319
the not yet so it's like a it's like between a uh web framework a active
03:11:45.560
record replacement yeah I haven't quite found the time but that's what um that's
03:11:52.080
what I'd like to do so it's on my on my bucket list y you talked about zero
03:11:59.399
downlo y yeah so I don't have um actual
03:12:06.040
professional experience with that but the way that works is you each module has a version and that version can be
03:12:13.239
you would do a release of your uh software and you would have a call back in the module to say uh there was a code
03:12:19.520
change and if the version change you could say what was your current state on like a gen server so if like our our
03:12:25.000
counter example is a trivial example but if we want to update that counter that process is running and we have to kill
03:12:31.319
that process to restart and run the new module code so like how do we do that with our current state so you would do a release with a new module version and
03:12:38.160
then you would write a function a code change function that said here's the current state then maybe that counter
03:12:43.760
now is going to be a toule of the current count plus the number of requests that have come in totally and
03:12:49.359
you could actually take the current state and transition the existing state to the new state required by the code
03:12:54.680
change and then it would restart that process with a new state with the new code that makes sense I don't have a ton
03:13:01.120
of experience with that and there's a I would caution people um code reloading
03:13:06.359
is awesome and I sell that as like that's why Elixir is great and earling is great um but for a lot of Real World Systems unless you truly truly need hot
03:13:12.880
code swapping um a lot of times it's way better to just um you know like on our
03:13:18.080
rail apps we'll do like a unicorn um deploy where we wait till the process
03:13:23.239
gracefully dies then we there's no like reals spin up time it'll wait till rail spins up completely before Ser new
03:13:28.399
request so there's no latency in pushing out code I almost always recommend that as the first step because the problem
03:13:34.720
with hot code swapping is unless you have a system that truly should never fail um you still have to write code
03:13:41.239
around what if like a noo down what if there's a net split you still have failure scenarios where hot code
03:13:46.279
swapping still isn't going to save you you still have to write code against um stuff crashing and having to be completely restarted anyway someone
03:13:51.720
trips over a power cord in the data center how do we handle that so you still have failure scenarios where um
03:13:58.160
hot code swapping um isn't going to save you so if you have failure scenarios that's handling code going down you
03:14:03.920
might want to use that for disgraceful restarts vers all the complexity of hot
03:14:09.319
code swapping but it's still awesome so if you want to look into it it's very
03:14:15.200
cool question what's the Tes experience like it seems like I wasting before like
03:14:20.520
seems like this eliminates
03:14:27.560
scen yeah so like having having no like shared mutable state is awesome and um
03:14:33.399
just to there's testing tools built into mix so in this my Phoenix project mix test is going to look in the test
03:14:39.840
directory and run all the tests in your projects and it's super fast um if we
03:14:44.960
open that
03:14:50.640
Up's see if I go
03:14:56.160
into so testing it's almost very similar to uh uh Ruby's test unit so I have a test
03:15:03.840
macro I can give it a description then a do in block of code and then everything becomes everything is just an assert
03:15:10.359
because we're able to get at the representation of code um I guess I'm trying so as far as like less things to test for um I found that
03:15:19.319
like inter oping libraries is incredibly easy because there's no nothing's being mutated it's like someone there's a web
03:15:24.760
framework called Dynamo that Jose started um but has since hand that off to someone else um and someone there's a
03:15:30.439
view layer in Dynamo web framework and someone was like can we get this into Phoenix said like that'd be great but
03:15:36.040
like I can't imagine we haven't looked we haven't tried to do any interop with this framework it's probably going to be impossible and there was a poort request
03:15:42.120
that even evening of like massive code that they just copied and pasted and it just worked I haven't accepted it but um
03:15:49.640
because you have these cases like functional programming becomes like data in data out I so I feel like um I've
03:15:55.520
only been doing this for a year compared to object orientation but there's less uh it feels like there's less
03:16:00.680
dependencies because there's less to um clobber and not be aware of so like the debugging becomes how is my data being
03:16:07.199
transformed incorrectly verse what's the state in these 100 different objects um
03:16:12.680
so I feel I I feel like things are easier to test and easier to debug but um I don't know if that is just because
03:16:19.279
of functional programming or if Elixir provides us some kind of extra benefit but yeah the testing is very uh just
03:16:25.800
asserts which is kind of cool and you get nice error
03:16:39.080
messages yep so check out Phoenix so I have a couple resources if you want to
03:16:45.399
get into this um there's l.org has a new getting started section that just shipped like
03:16:51.199
last week two weeks ago which is is really good uh free node Elixir Lang IRC
03:16:56.319
I live in there constantly I always tell people I'm worried about being too active um so I'm always willing to help
03:17:01.680
there's actually a lot of helpful folks in there Jose hangs out in there and he'll answer your questions uh so that's
03:17:07.160
IRC is perfect um don't be afraid to ask beginner questions like the language is so new that everyone's a beginner
03:17:12.720
and we can all learn from each other so hop on there that's probably the best single best resource is just IRC watching the discussions asking your own
03:17:19.199
questions uh github.com Phoenix framework is where Phoenix lives I'd love ideas um trying to discover some
03:17:26.279
new ideas and bring some awesome Innovation from rails into Phoenix where it makes sense so if you have any input
03:17:32.000
on that um hop in on the issues list I'm kind of using it as like an active discussion there issues with like RFC
03:17:37.520
request for comment and I'd love to have collaborators contributors I'm Chris
03:17:43.000
record on Twitter and uh it's my email if you need to reach me I'm always willing to help out and uh I'll probably
03:17:49.239
be hanging around a little bit afterwards if you want to see any other code examples but uh the prag prag book
03:17:55.359
I don't think I have that listed there P that back up% oh is it wonder if they planed that
03:18:03.319
really yeah so the pragprog book by Dave Thomas is where I started and it's it's excellent um it's like a it's a
03:18:09.880
condensed version so like he wrote the pickaxe book anyone has a pickaxe book um so it's not a uh it's not built as
03:18:15.720
like a complete exhaustive Elixir book but it's enough to get in get your feet wet it introduces OTP a little bit and
03:18:22.720
we'll talk about like enough to get you started into not knowing earling and then I finished the book with enough
03:18:28.319
knowledge to be able to find out whatever I needed so like you'll come you'll come in and if there's some earling documentation you need to get
03:18:33.960
into you'll be at least be able to be um proficient in reading it like how to do things yeah cool I think that's I have
03:19:07.439
lot