 My name is James. I work at Gaslight with a great group of individuals. We spend most of our days writing Ruby and Rails applications. I've been spending increasingly more and more time in JavaScript. You could read into that whatever you want. So I've been looking for a new language to pick up and I had been looking for a functional language to learn for a while, had been trying to learn Closure for whatever reason and just never really quite stuck. But then I was introduced to Elixir at a local SINSI functional programming group and was pretty immediately drawn in. Initially at first I'll admit was the syntax. I had a very similar journey to what Richard was talking about earlier where the syntax kind of drawn me in and I ended up staying for the semantics. So I've been having a ton of fun programming in Elixir and it's really helped me to think about my programs differently and to break up problems into smaller processes using pipelines and pattern matching to just really model my programs more closely to my data which I've really loved. And the first time I connected to a distributed mesh I felt like a wizard. I mean this is amazing. The fact that I can have my code running on multiple machines and that the syntax still maintains its expressiveness with so much power and I was just absolutely blown away and so of course what I wanted to do immediately is tell all my coworkers like any geek who's passionate and I just wanted everybody to know so immediately I just started talking about nothing but Elixir and I always kept getting something similar to this back. I'd love to check out Elixir but I don't really have a problem that's big enough or that Elixir is well suited for and I thought man that's a bummer. I'm really excited. Why isn't everybody else as excited as I am? And what it turned out they were really trying to say is I don't want to use a cannon to kill a mosquito and that's a valid point I suppose except for I don't really feel like that's all that Elixir offers. See I realized when I was trying to sell Elixir to my friends I would use words that we all use to describe Elixir in Erlang functional, massively concurrent, distributed, fault tolerant, web scale, whatever that means. And that's pretty intimidating and if you were to try to think about you know what could I come up with that needs all of that. It's kind of difficult. There was a talk at Erlang factory about composing a functional community by Katie, I can't remember her last name right now, Miller. It was absolutely great and she made a great point that functional programming kind of has this reputation of being unapproachable that the really smart people are doing it and we use these big words like massively concurrent and monad whatever that is. So I've been trying to think of a different way to sell Elixir the way that I know Elixir and why I like it which is it offers me a different way to think about and solve problems no matter what size they are and it's very similar with Dave's mantra so maybe we're onto something here but really pattern matching, pipes, message passing, immutability, these things make me happy because it allows me to write my code very similar to the way my data is. And sure all of the power is still there. We still have massive concurrency and distributedness so by all means nuke it from orbit. It's the only way to be sure. So I wanted to talk about writing command line applications with Elixir and why and part of the reason why is to really show that you don't have to have some massive applications, some large website that needs to scale in order to have fun with Elixir and to enjoy it. Also the other reason why is because I feel like Elixir has some great libraries for doing this. The Stener library is fantastic and really is one of the better ones I've ever worked with. Also command line applications are kind of cool. I mean this is what everybody's desktop looks like when they're doing programming. If you want to have fun download this GIF and put it on your laptop full screen and just sit at a coffee shop for a while and see what reactions you get. You may or may not get kicked out. Anyway, but like I was saying, Elixir has a great standard library. This is actually the Cincinnati Public Library. I'm from Cincinnati and it unfortunately got tore down in the 60s I think. It was absolutely gorgeous but we have a great standard library that supports a lot of great functionality right out of the box and I've been really impressed with that. When I first was learning Elixir I immediately went out and grabbed Dave's book and devoured it and I was really filled with the same kind of excitement I had when I was learning Ruby. It just felt right. When I first learned Ruby my first introduction was Wise Point Guide which if you haven't read it I highly suggest it's a very strange time but you'll walk away feeling like I think I learned a language. But when I read programming Elixir I walked away thinking I can think in this language. I think I know how I would solve problems in this language and then I started doing that. If I had a small scripting problem I would immediately go hmm, how would I solve this in Elixir? What would this look like? I started writing small command line Elixir apps and increasingly found myself using Elixir in anger and that's really how you know you know a language is when you reach for it in anger. One of the first things you come across in Elixir is Mix and Mix is fantastic. I wish I had had Mix when I started doing Ruby or something like it. This was back in 2007 when Ruby gyms had just started catching on. The fact that we get all this functionality from day one, I feel like it's the early days of Ruby and the level of excitement but I feel like it's not the early days of Ruby in that we are standing on the shoulders of Ruby and other great languages. We have tools like Mix that is a dependency manager. We have a good package manager in Hex. We have the ability to write one-off tasks that's very simple and just a ton of functionality. So the dependency management with Hex now is fantastic. I've made use of it and thank you to everybody involved in that. So getting your dependencies, compiling them, updating them, locking and unlocking, I really like the fact that you can unlock a specific or all dependencies so that you can then upgrade. The other feature that's really nice is if you have a mix of Hex dependencies and Git dependencies and there's a shared dependency in between those, you can declare the shared dependency and override it to the version you want, unlike in Bundler where you just end up getting in a loop. So the way you declare your dependencies, I'm not going to go too far into this because it's already been stated. You just add them to your depth private function and you can declare those as a Hex package like the one right there or as a Git dependency and any tag, specific tag you want to include. And the other thing that I've used, especially with small little applications like command line applications where you might have multiple tasks to do something as an umbrella project, and the nice thing is you can collect up your applications and do things with them like run one task across all of them, say to clean up log files or you could also run all of the tests for the applications. And then if you have broken your app up in a modular function, you can declare any application dependency order that you have. So umbrella projects are pretty cool and it's something I hadn't seen in other languages that I really liked. Writing mix tasks, this was pretty cool how easy this was. You just include the mix task behavior and you supply a run function and do what you need to do. So a little bit of IO, some colored output, and then mix just knows about your task so you can say mix the name of my module and it will run your task. So very similar to rake, you can write these very short tasks and maybe you don't need a command line application. You can just do everything you need to do in a mix task, which has been really cool. But if you do want to write a command line application, you're going to want to bundle it up so that you can run it on the command line like you would any other executable. So mix escript build is how you build an escript, which is a zipped up version of your application and you can actually bundle along Elixir with that and the only system requirement is Erlang at that point. So what you need to do to do that is declare a main module inside of your project and in the escript key. And so I've declared a private method here. I set the main module to my project command line module and then what you need to do is supply a command line module, which is really pretty easy. All you need to declare is a main function and then do what you need to do, which leads into another really awesome standard library module, which is option parser. I think Elixir is one of the first languages, Python might supply one, but one of the first languages I've used where an option parser is supplied and that's been really awesome. So you can parse args, supply switches. So here we're supplying a help switch and we alias that to h, just in case somebody wants to use it shorter and otherwise then we pattern match on that. So this is another instance of pattern matching being really powerful in our code reading really nice and being very similar to the data. So we declared two process functions that we pattern match on. If it's help, we're going to display a helpful message and exit, otherwise we're just going to display a helpful greeting. And so to package that up, we run escript build that compiles our project, generates a escript and then we can run it on the command line like we would any other binary. And that is really as simple as it gets. So I've really enjoyed that. The other thing that was really nice coming from Ruby is basic IO and Elixir is pretty much exactly what you would expect. In order to put out something to the standard out, you just clear IO.puts and you get your standard out. If you want to get, gets. The interesting thing though is where Erlang comes in is that by default puts is going to the group leader process. You can actually send IO to multiple processes which is helpful if you need to read or write files across processes. There's great testing built in baked into Elixir and coming from a Ruby background also I was a big testing advocate. And testing command line applications, there's a really helpful module called capture IO that allows you to assert on any IO that's done inside the function and then make an assertion outside of it. And that's been pretty helpful for testing my command line apps. The other cool thing is IO ANSI supplies a lot of escape sequence support. So if you need to clear the screen, send the cursor home, change the colors to green or bright and want to make something that looked like that slide earlier, you can do that. So, it's pretty helpful. Files and paths. Again, this is very similar to Ruby with its file library except for there's a caveat. If you want to be able to use any of the IO module on files, you need to pass it the UTF 8 option and then all of IO is available that way. Otherwise you're stuck with using Ben read or Ben write on the file module. The other thing that was really nice is path wild card. So in my case, I'll show you later is I want to do write something that watched a group of files and path wild card was super helpful for that. The other nice capability that Elixir has that comes from Erlang is being able to interop with other processes. And that's done through Erlang's ports. And the way that works is Erlang spawns an internal process that binds to the input output of the external process and then passes it along to whatever process spawned it. And the basic usage of it is pretty simple. To open a port, you just declare port open and then say that you want to spawn a process. There's also a spawn link, if you want to link it. Pass it the command that you want to use or executable. A couple helpful options is binding standard error to standard out and you also want to record the exit status in case the process exits. So in this example, we're going to open up a port and then when we receive a message from the port that looks like data with a key of data and a path, we're going to put out the current working directory. And then when we receive an exit status message, we're going to let the user know that we exited. So that's a really simple use of port. You can also work interactively with ports, which is something I've been playing with. You can do some pretty cool stuff. So I wrote a really quick library for interacting with a game called Rogue. So start up a IEX ripple and bump the font, clear the screen. It probably needs to be a little bigger. Sure. Is that better? A little more? All right. So I wrote a library for interacting with the game Rogue, which is an old console ASCII-based RPG. So we're going to call Rogue start. That's an args and we get a PID and a port back. The PID is the PID for the port that we're going to communicate with. I have a function called Rogue show, which needs args. And we get a message back from the external process Rogue with the current state. And if you've never played a Rogue like before, the at symbol is your character. The plus symbols are doors and your objective is to survive and go as low in the dungeon as you can. So like I said, you can interact with not just spawn processes. So we're going to send the Rogue command. And because for some reason Rogue likes our Vim users, we're going to send an H to go left. And then call Rogue show so we get the message back. And we can see that our guy moved left. This is really cool. We are sending messages and receiving messages from an external process. And that's just really cool. So I've been playing with that. My goal is eventually to write an AI process to interact with Rogue and play through. Turns out that's actually pretty difficult to do. So that's real quick ports. Also something you may, some external processes do not exit properly when you tell them to close. And I happen to know that Rogue is one of those. So we're going to kill all Rogues. So Elixir has a great interoperability story with ports. And there is some limitations. One of the things that port has trouble doing is if you want to read all of a file to the end of the file, it has problems doing that. So there's a great library by Alexi true droid on Twitter and GitHub, I believe. And it's called porcelain. And it wraps a Elixir interface around the existing port library and also provides the ability to get past the end of file issue. He actually uses go to do that. So you can use Erlang, Elixir and go all at once. So the other really awesome thing, and this gets back to the early slide of being able to have concurrency and scalability, is that once you write a command line app that actually needs to scale up, there's great abstractions for doing very simple tasks that you want to be asynchronous. And that's with tasks and agents. And tasks are, as someone mentioned earlier, a, I think it was Josh, similar to futures in another language, with the caveat that they're only going to return to the process they called them. So, the here we're declaring a greet function with an argument of name and we're putting out name. And we're going to pass that to a task that we want to call asynchronously. And let's say, we're going to greet ElixirConf and friends. And then here, you're seeing we're putting out good afternoon and then mapping those tasks and calling a wait to get back the output. And so, we'll see in order, good afternoon, hello ElixirConf, hello friends. So tasks are a really nice simple abstraction for just spawning functions off and receiving the output back. The other thing that's really nice that I've used in my apps is agents. So agents are just a really simple abstraction around storing state. And really, under the covers, the thing I like is that they're just a gen server. So, to start an agent, you start and link it, pass it the initial value that you want to have. In this case, it's just an empty hash dict. And then you can, you get a PID back and then you can update your agent. So here we're passing a function that will have the agent's current state as an argument. And then we're putting into its current state a tuple of foo and bar. And then we can get that back. So agents run in a separate process. So if you have lots of little processes that just need to read from a global state, agents are really nice for that. So the command line application that I wanted to write is I had a project where we had a lot of coffee script files and a lot of markdown files. And we were using a JavaScript library to compile all of those. But it was single threaded. And so it was pretty slow. So I thought, you know, it would be really interesting to see how I would do that with Elixir. So I wrote a really simple library that will watch for, watch a path. Everybody see that okay? Okay. So we'll pass it a glob that is a path wild card. And then we're going to start an agent to keep track of the status of the files that we want to watch. So the agent is really simple, like I showed earlier. We start up an agent. It has a set the initial state that maps over all the files in the path wild card. And then uses an internal module in mix to get the last modified date of the file. So there's all kinds of hidden gems inside of mix. I recommend diving into the source. You'll find that maybe what you're trying to do makes already does. Same way with xdoc. So we're going to set the initial state of all the files. And then we're going to watch those files. And all that does is check for changes and checks to see if the last modified, if there's any modified files that have changed. And then if there is, it's going to perform a task in this case, we're going to map over all the files and spawn off a task to compile the coffee script files in this case and then concatenate them into one application.js file. So the coffee script compile, and I found out after doing this there's a much simpler way to do this without using ports, but it's just spawning a port to the coffee script command and compiling it and getting the compiled coffee script out as standard out. And then bringing that back in to the application and concatenating it. So I'll show real quick. I have a file or a folder rather with 60 or 70 so coffee script files. And I've packaged this up into a e-script. And then I'm going to run. I'm going to have it watch the test directory for any coffee script files. And then down here I am going to edit one of those. Looks like I need to move that over a little bit so you can see. There we go. And to the right here I have htop running so I can see that all my cores are going to get utilized. So in this case we're going to edit the file save it. Yes. I'm sure. And we'll see all eight processors were used. Our coffee script files were compiled. And pretty short time. So this was just a really quick example of something I was able to do to solve a problem. And that's how I've been using Elixir is to find small problems that I would normally reach for languages like Python or Ruby to solve and at work and solve those problems with Elixir because like I said the language is really expressive. It is really powerful and has a great standard library for doing this kind of stuff. So I encourage you not to be afraid to use Elixir as a vector, you know, command line apps and scripting as a vector to get Elixir into where you work. I've had a lot of success with that and I know a lot of other people I've talked to have as well. And also to just generally experiment and do fun stuff. I really enjoyed Augie I think did a synthesizer or was that Josh? Josh did a synthesizer in Elixir. You should check that out. Super cool. But yeah, have fun, solve problems both big and small, and think differently about your software. And that's all I have. Thank you. Have you found a good documentation for what the allowed options in mix.exx are because the docs are kind of lacking and mostly I've learned about by seeing other people's apps use a certain keyword and then like oh I can do that I didn't know that. So the docs at least the most recent version seem to be better but I know because the version of Elixir has been changing very rapidly lately a lot of those keywords have changed so it wouldn't surprise me maybe if some of them were out of date. But I have tried to dig into the source and see what's available to you. But if you find a key that's not documented please submit a pull request. Okay. And then just two comments on questions. Ruby has OPT-Pars and it's called option parser. I've never ran it. Yeah, confusingly the library is called OPT-Pars all one word lowercase. So most people don't find it because the required library is not the class name. And also are you using Homoculus the last thing you demoed like in production a lot? It's mostly development environment. Okay. Because I'd recommend looking into using the most OS's now have file system change libraries. FS watch is one I'm looking at to replace what I'm doing because I'm really just pulling FS watch I've thought about spawning that off as a process and then just having it pass me a message when a file is changed. There's also at the Erlang level a thing called NIFS which is loading a C library into the Erlang VM. You might want to look into that might not spawn an OS process it might work better. But I think it can screw with the Erlang VM if it crashes. Okay. Another thing I didn't mention is there's another library that is much more mature than this for watching files and performing tasks called Rotor. And that's written in the lookser. I'd recommend checking that out if you want to do that. Rotor. It's by hash nuke on GitHub. Yeah, shortly after I had started working on this I was on IRC and he was like you should check this out. And it's much further along than my implementation and actually implement some of Gulp's API. Do you know if you're able to feed in special keys to that standard N like if I wanted to control plus something or plus something do you know can you do that? So you should be able to with escape sequences. Yes. So if you wanted to interact with save them and send an escape then you can do that. Any more questions? All right. Thank you. Thank you.