List

Workshop - All Aboard The Elixir Express!

Workshop - All Aboard The Elixir Express!

by Chris McCord

In the workshop titled "All Aboard The Elixir Express!" presented by Chris McCord at RailsConf 2014, attendees are introduced to the essentials of the Elixir programming language. Emphasizing Elixir's advantages, McCord compares it to Erlang, highlighting its concurrency and fault-tolerance features. The workshop is structured as a guided tour through Elixir, starting with the fundamental concepts and gradually moving to more advanced topics, including:

  • Erlang's Background: McCord explains Erlang's development for telecom systems, focusing on its design for distributed, concurrent, and fault-tolerant systems.

  • Elixir’s Relationship to Erlang: Elixir is introduced as a modern language that runs on the Erlang VM, incorporating Erlang's strengths while adding features like metaprogramming, ease of use, and rapid deployment, contrasting its syntax with Ruby.

  • Language Features: Key features of Elixir are introduced, including immutability, the actor model of concurrency, and pattern matching. There is discussion on constructs such as tuples, lists, and terms.

  • Concurrency Model: McCord discusses how Elixir’s approach to concurrency is superior to that of Ruby. He explains how Elixir processes are lightweight and how message passing effectively eliminates shared mutable state, allowing developers to write safer concurrent applications.

  • Process Management and Supervision: The concept of processes in Elixir is explored in detail, including how they can be supervised to handle failures gracefully. McCord demonstrates how to send messages between processes and manage state effectively.

  • Use Cases and Real-World Applications: Throughout the presentation, McCord illustrates the practical implications of using Elixir over Ruby for certain applications, particularly those that require high concurrency and fault tolerance. He shares his experiences with Elixir while discussing a Twitter aggregator project that demonstrates these concepts.

The workshop concludes with a discussion of the advantages of adopting Elixir for future programming endeavors, particularly for those familiar with Rails and looking to explore concurrent and highly reliable software development.

Elixir provides the joy and productivity of Ruby with the concurrency and fault-tolerance of Erlang. Together, we'll take a guided tour through the language, going from the very basics to macros and distributed programming. Along the way, we'll see how Elixir embraces concurrency and how we can construct self-healing programs that restart automatically on failure. Attendees should leave with a great head-start into Elixir, some minor language envy, and a strong desire to continue exploration.

Help us caption & translate this video!

http://amara.org/v/FGZr/

RailsConf 2014

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