 Seriously, thank you. Thank you all for coming. Specifically, I'm going to talk about writing Elixir in Elixir. It's a meta-programming talk. Cool. So fact is, and actually some of you got a preview of this in Lauren's talk just a bit ago, a large portion of the Elixir programming language is actually implemented in the Elixir programming language. And that is super interesting. It's super meta, right? Whenever we make bold statements like that, the first thing that comes to my mind, you're curious people, it probably comes to your mind, too, is how much, right? That's great, Jay, ha-ha, it's a lot. But how much is a lot, right? I've got an answer for you. It depends. Doesn't it always? So what does it depend on? We need to figure out how we define Elixir, right? We could just take the code base and look at it, but there's a lot of other things in the code base that maybe isn't the language, the tests in particular. So here's how I defined it for an example. Take the basics of the language, the structural elements of the language, and add in standard library. The idea is basically anything that you're going to touch and play with when you write an Elixir program, we're gonna call that Elixir. So I did some highly scientific analysis using the linguist tool provided by GitHub, came up with 78%. Wow, it's a number. 78% of Elixir is written in Elixir. Pretty interesting. I actually got this number by basically deleting everything that wasn't the Elixir source implemented in Erlang and then the standard library, which is written in Elixir. You might compare that to similar values if you look at Ruby. So I came up with 44%. It's like, oh cool, another number. That number's smaller. I must like Elixir better. That's impressive, but I don't know. Numbers, they're sort of inherently faulty. Ruby is MRI, at least, is implemented in C. C is noisy. There's a lot more characters. You're gonna use more code, so it depends on how these tools work to come up with those numbers. And it's sort of the same story in Elixir, right? The portions of Elixir that are written in Erlang, or in Erlang in Erlang maybe is more noisy in some way than Elixir. So I don't know. The numbers aren't terribly impressive to me. What is really impressive to me is when you write Elixir, you use all of these different constructs and pieces, and almost every single one of them that we interact with is implemented in terms of Elixir. Examples, if, it's a macro. I think a lot of people are familiar with this. The if control flow operator that we use, maybe we use it less than Elixir because we have pattern matching, but it's a thing. It's implemented as a macro in Elixir. So you can go look up the source code in Elixir to see how if is implemented. Pretty interesting. The same thing for def. So function definitions, module definitions, macro definitions, all these things are implemented with a macro called def something, or just def, and def itself is a macro that's used to define these things. And even operators like the pipe operator is implemented in Elixir as a macro. And a lot of the operators in Elixir are implemented as macros. So it's really neat to think about how much of the language that we interact with is actually implemented in terms of Elixir itself. It makes it really easy for us to learn about the language because we can go read the source code and instead of having to know C or know Erlang or whatever it's gonna be to read the implementation of the language, we just know Elixir, which is what we're writing. So we probably know Elixir already. So how does this happen? Metaprogramming, wow. Yeah, metaprogramming in Elixir kind of just boils down to code generation, which is sort of simple. It's not all that complicated. In other languages like Ruby, we get into a lot more complicated subjects like runtime, message dispatch and stuff. In Elixir, we're generating code. We're writing a bunch of code for you so that you don't have to write it when you write your programs. So let's pause for a second. Let me introduce myself. My name is Jay Hayes. You can find me on the internet, set I am very, I am inside your computer, just go to that and it's me. I come from northwest Alabama, the Shoals and turns out we bottle the stuff there. So this is the, yeah, the big factory where Elixir is produced. That's an old logo, but yeah, pretty cool. Fun fact, Alabama. Woo, I work for Big Nerd Ranch. Actually work remotely. I'm a full-time remote employee for Big Nerd Ranch. It's in Atlanta. We do development, so we'll build programs for you. As a consulting company, you come, we'll develop first-class solutions to your problems. We also teach. We'll come to your company and teach on-site as well as we have open enrollment classes where you can come to us and we'll learn for a week together off in the woods somewhere and it's not scary at all. And then finally, we write books. Pretty well-known programming books. It's been really fun interacting with people throughout this week and finding out that you learn how to do maybe iOS development or something from our programming books. We just released a front-end programming book which is really, really good. You should check it out. So when I found out that I was speaking at ElixirConf, I told my wife. I was really excited because I haven't done a lot of speaking and I consider it an honor to be here. So I went to her and I was like, honey, honey, this is fantastic. I'm speaking at ElixirConf and she responded much less enthusiastic. Oh, that's nice. Where is it? I'm like, come on. So she kind of settled me down a little bit. I was like, it's in Orlando. And then she perked up like, oh wait, that's where Disney is. Can we go to Disney while we're there? And I was like, well, at least she's excited. Yeah, actually it's at Disney. So we can totally go. And she's like, oh my gosh, you're speaking at Disney? I'm like, well, I mean, sure. Yeah, if that's what you want to think. Yeah, that sounds great. And she interrupts me, gets on the phone with her friend. Yeah, yeah, he's speaking at Disney. We're going to Disney and I've already lost her. So here we are at Disney and she's really excited. Her and our eight month old son, Liam, came down for the trip. We had a lot of fun. One of the things that I didn't necessarily expect is Liam was absolutely enthralled with the Disney princesses. Like he would be fussy and wiggly in line and then he would see a princess and she's like, wow, she's beautiful. And so he got a little closer to them than, maybe I would have liked an eight month old. Anyway, metaprogramming, right? So a lot of people think metaprogramming is a really, really scary thing. I don't know, in Elixir, that is sort of dispelled a bit. The metaprogramming model in Elixir, it makes it somewhat simpler. You know, I referenced Ruby and there's a lot of different styles of metaprogramming there. Maybe it's simplified a little bit in Elixir. You'll be the judge after you see this. So to talk about metaprogramming, let's talk about what it really is. It's just programming, right? And what's programming? Programming is performing some work on some data. Well, what's data? I like defining things, cool. Data is quantities that we perform operations on. So when we're metaprogramming, we're performing operations on data just like when we're programming regularly, yeah? So let's look at a really simple program. Four plus two. Most of us understand what that means. Where's the data? The data is the integers in the plus operation, four and two. So we could rearrange this. Looks more like a function. We have the plus function now with the arguments four and two. Still doing the same thing. The data's still there. And it turns out this is really exactly how the plus operator is defined in Elixir. They just give us some syntactic sugar so that we don't have to write it. As a function call, we can use that infix notation. So in metaprogramming, the program itself is the data. That's the definition of metaprogramming. Instead of us operating on basic data types, actually operating on a program as data, doing something with it, maybe transforming it in some way or generating a new program. And really the main mechanism for doing this in Elixir is macros. Here's the thing. Macros are everywhere in your Elixir code. And the reason that you may not know that is really good macros are pretty much invisible. You don't even realize you're using them. They feel like an extension of the language. And oftentimes they're used to extend the language. So here's an example. This is a test, a test written in EX unit. Probably looks somewhat familiar. So let's find the macros. Literally every single line of code in this file is a macro. Def module is a macro. Use is a macro. Test is a macro. Assert is a macro. So the question comes up, where's the program, right? Well, for def module, the data that you're performing some operation on is everything after def module. This is actually the arguments to the def module macro. For use, it's the module ex unit case. For test, it's the description and the definition of the test. And then finally for assert, it's some statement that we're asserting truthiness about. So macros kind of do this. They take an expression. That expression is piped through the body of the macro, the definition of it. And then they produce some new expression. It's code generation, right? Let's define expression. Let's make sure we're all on the same page. An expression is what we're gonna call quoted elixir code. The general form for quoted elixir code is this. And we'll get to a little more details about it. But in general, it's a three element tuple. The first element is the function that that particular piece of code uses. And the last element is the argument list. So with this combining these together, you can produce an abstract syntax tree. Many of you I'm sure are familiar with the idea of abstract syntax trees. They're very common structures used in many languages. In a visual form, they might look like this. The cool thing about syntax trees is they capture precedents within them. So in order to execute this syntax tree, you have to first determine what the result of the subtraction operation is, and then use that result with addition. So it sort of supersedes the traditional order of operations because there's precedents built into it. If we walk the tree, then we produce something like this. And this is like prefix notation, which maybe some of you are familiar with it. We'd often don't have to worry about it. But in this case, of course, the functions are the operators and the arguments are the data. If we throw in parentheses, it looks a little more familiar. At least we understand the precedents there. The two and the three subtraction must happen before it's added to one. But rearranged in infix notation, this is something we're a little more familiar with. So that's abstract syntax trees. The thing is, macros and elixir, the arguments to the macros are implicitly quoted. So those quoted expressions are produced implicitly for whatever arguments you provide to the macro. Let's see an example. So say we have a module named expression that implements a function or a macro in this case, matchA. And what it does is it returns true or false based on whether the argument, the expression given to that macro is a match operation. So you'll notice that the top, that's not a match, that's greater than, so it returns false. And the second one, it is a match, so it returns true. Now, some of you might think, hey, there's an error there, right? The atom law does not equal the atom what? That doesn't match, so you would get a match error. The answer is no, that's not an error because that expression is never evaluated. We're just looking at the syntax tree that that expression produces from the macro and determining whether it's a match or not. We don't care what the matched values are. So how would we implement this macro? We might do it like this. So we can use pattern matching on the arguments to that macro to determine whether the function used in that expression is a match operation or not. So if it is, we can pattern match it, it's true. And if it's not, if it's anything else, we don't really care what it is. Well, then it's not a match, so we get back false, right? So again, using it looks like this, but the neat thing about Elixir is an important detail about how macros work is macros are evaluated at compile time. So when your programs are compiled, every macro becomes the expression that it produces. So the macros that we define produce the literal booleans true or false, depending on what expression was given to it. So at compile time, as far as the VM is concerned, it's looking at literal values, false and literal values true. So the next thing about macros is they must return a quoted expression. So remember, macros just accept expressions as arguments and produce expressions as results. They're just generating code. They're producing something from something, right? So we need to return a quoted expression. Here's a macro. It is a macro that produces an expression that's a bad match. It's the same bad match we saw used in the previous example. But here we've hand coded the literal AST for the atom law, matching the atom what. Now, it's hard to read that, I would say. It's kind of hard to glance at that and realize that that's an AST for a bad match. So Elixir provides this quote macro that produces those syntax trees from some Elixir code so that we don't have to write those by hand. As you can imagine, if it got any more complex than that, the syntax tree that we would have to write by hand would be really difficult to produce. So I'll talk a little bit more about the quote macro in a moment, but in general you can make this a little more readable by using it here. But the point is, if we were to use bad match anywhere in our program, we would get a match error at the point that it was referenced. And that's because when your program is compiled, that call to the bad match macro becomes literally this expression, which is a bad match. It will fail, it will raise a match error. So let's talk about quote. I've been promising some discussion of that for a few minutes now. In review, and giving you a little more information, the quote macro produces three element tuples. They're composed together to make arbitrarily complex expressions of Elixir code. The first element is a function that's being called by that expression. The second element is some metadata. So metadata is things like maybe the module that that function's defined on, maybe other modules that need to be imported in order to, for code that's referenced within it, things like that. Oftentimes we're not too worried about the metadata, but it's useful to know what's there. And then the last element is of course an argument list. It's the list of arguments that are being provided to that function when it's called. It also may be additional quoted expressions nested within. That's how the precedence is expressed. So here's that same bad match, right? That's the one that we saw in a couple slides back as a quoted expression. The function is of course the match operator and the arguments are lull and what as atoms. And that's produced by using quote. So we know this, we've seen this. So the thing about quote, this was really hard for me to grasp. So I'm hoping, I'm hoping that I do a good job here and I can convey this and it will be clear to everyone. Quote is, you can kind of think about it like strings. And that seems weird because it's not strings so don't think too much into that. But the point is in other languages, sometimes we put programs in quotes, right? In Ruby for example, you might have a program that's in quotes, it's a string, you're storing your program in a string and then you for evaluation later, right? So that's kind of what we're doing in Elixir. We're putting our program in quotes, we're quoting it to produce an expression to be evaluated later. So this example is actually just the one line version, some Elixir syntactic sugar lets us write it in multi-line if we wanna drop the parentheses and do that. It's the same thing. But that's kind of what we're doing with the quote macro in Elixir. So quote just returns an abstract syntax tree of the expression that's being quoted and it can be arbitrarily complex and as you can imagine the expressions that are produced become quite complex. We take a simple example like this, we have two minus three and we quote that, then we get an expression that looks like this and this is maybe what you expect from what you've seen so far. The neat thing is if we fade out some of that Elixir data syntax, you kinda see the infix notation buried in there. So the infix notation for that expression is right there in the Elixir code. If we were to quote a more complex Elixir program, then we get a decidedly more complex abstract syntax tree but it's still neat. That infix notation is still embedded in there. It's sort of inherently part of the data structure that Elixir uses to express programs as Elixir data. So what's the point of quote? In my opinion it makes it easier to grok these complex syntax trees that you're dealing with when producing metaprograms when you're producing the expressions for macros and stuff. It's a lot easier to see on the top that we're producing a syntax tree for a couple math operations than it is on the bottom. On the bottom it's like, I don't know, the numbers and like a smiley face that's eyes are above its mustache. I don't know, it's something weird. Before we stop talking about quotes I do wanna mention that there are a number of values in Elixir that are considered literals, meaning that when you quote them, they just return themselves. They kind of act as terminal values for like the recursive nature of quoting. If you quote an expression, it's gonna quote all the nested calls all the way down until it eventually gets to some fundamentals that it can't unquote, they're just the same thing. So these values just return themselves. Things like strings, atoms, numbers, both integers and floating point numbers, lists of anything that returns itself. And in particular, I found this interesting, the two element tuple is also a literal that returns itself and the reason for it, I confirmed it with Jose, so you can quote me on this, ha. It's because it's a support structure for keywordless in Elixir. So they want keywordless to also be a literal that when quoted returns itself. So in order to pull that off, the two element tuple in particular is one that returns itself when quoted. Interestingly, other sized tuples actually return the quoted three element tuple with a function and arguments and stuff, so you can see that you can play with it. Cool, let's talk about unquote. So quoting expressions is great. You can produce syntax trees for Elixir code, but what if we wanna like inject values into those trees as they're being produced? That's what unquote's for. So when you use unquote, what you're doing is you're injecting a value into a quoted expression. Now, remember how I said quote is kinda like strings? Like, don't think about it too much, but it's kinda like strings? Well, unquote's kinda like string interpolation. And it's actually, I think in the documentation, it makes a reference to this and when I read it, I was like what, what, that doesn't make sense. And it does, it just takes a second. So again, I hope I'm able to communicate this in a way that does it justice. So let's talk about string interpolation. String interpolation is injecting a value into a quoted string. So if we have an example, the string su, we bind it to the variable name with the match operator, then we, in the next line, we produce a new string called high name. Now, we wouldn't expect the value stored in name to be inserted into our string in this example, right? Because name is quoted, it's in quotes. It's part of the quote. It's not making reference to anything outside. It's being quoted. So in order to do that, we use string interpolation. That's fun. And the way I like to think about string interpolation is we open the quotes to say, hey, Elixir, we're starting to quote a thing. And we start typing, hi, and then we say, oh wait, temporarily pause the mechanism for quoting and let me reference something outside this quote for a moment. And we say, go get name or add two numbers together or do anything. Anything outside the context of this quoting until I close that unquoting, or until I tell it, you may resume quoting, essentially. And we do that with string interpolation to access things outside the string. And so as you would expect, the string that's produced now says hi, sue, taking into account the name that's in scope there. So with unquote, we do the exact same thing with expressions. We're injecting a value into a quoted expression. So let's say we have the number 42. It's a good number. We bind it to the variable name and we then produce a new quoted expression that adds one to that variable num. I said name a moment ago, forgive me. So num. Now, the syntax highlighting doesn't really do us any favors here. It kind of looks like we're referencing the variable but we're not. What we're doing is saying, produce me a quoted expression for the elixir code adding one to a variable num. And that's exactly what it produces. You can see in the output code, we get the plus operator with the arguments one and then some variable num. But that's not what we wanted. What we're wanting is to produce the expression for one added to the value stored in the variable num outside of the quote. And to do that, we use unquote. It temporarily pauses the quoting mechanism of elixir, says go find me something outside of this quote, evaluate it and inject it into the expression and that's what it does. It produces the quoted expression one plus whatever value was stored in num and that thing could be more complex than that. It may not just be a variable, it may be another quoted expression, right? So you can kind of see how, hopefully, how unquote is a lot like string interpolation. Okay, I have now armed us all with the insane power needed to produce a macro. So let's implement one that maybe we're pretty familiar with. I was wanting, when I was working on this talk, I was wanting to come up with something crazy and like just have a lot of fun and I thought, you know what? Why don't we just stick with something we know? Maybe some of you even know how to implement the if macro in elixir. But I feel like it's a concept that we kind of all have a good grasp on. It's fairly well understood. For those that don't understand or need a refresher, here it is. So we can say if we give it a condition that needs to be a truthy value or it doesn't need to be, it could be a truthy value. When it is, it evaluates, or it executes a true case that's given to it. So it would say pass if it was a truthy value. Otherwise it's a falsely value and it would say fail. So there's a lot of syntactic sugar that is happening here. So we could rearrange that and realize, oh, actually, if is just a function. It's a macro in this case, but a macro is just a function. And it might look something like this. And if we take away a little more of the sugar, you'll realize that it's just a function that takes two arguments. The first argument is the condition. And the second argument is a keyword list that captures the true case and the false case. So the condition is the first argument and the second argument is the cases. Let's talk about truthiness and falseness. It's just in case you're not aware of that. So in elixir, the if macro kind of captures that idea. Without if, we would be stuck writing maybe complex case statements or something to determine if something is not literally true, but kind of like true or kind of like false. So the if macro sort of encapsulates that idea for us. So falsely in elixir is the literal false or nil. So it's kind of nice not to have to check for false or is it nil? We just say if, right, or unless. Truthy is anything else. So it's a lot like Ruby in that way. If you're familiar with Ruby, true is anything but false and nil. And elixir is the same way. So with that, we can imagine writing a case statement that our if macro would act a lot like. The condition would be the condition of the case statement. And then the cases would be the two things that execute. If the value that comes out of the condition is false or nil, then it's the false case. Otherwise, it's the truth case. So that's really all we need to write the macro. And I'm sorry, there's a lot of code on the slide, but we'll step through it. It's relatively simple. We start off with the first argument to if being the condition. And the second argument is that keyword list where we get the true case and the false case. And then we build the expression for a case statement. We unquote the condition. So we inject that condition into the case statement. And we inject the cases into the case statement that are executed for either true or false. And so the result of using this macro is we would actually use it like this. It would look just like we saw earlier where you have those conditions and cases in there. When your program is compiled, it would literally produce a case statement. But we don't have to write this. And it's very nice that we don't have to remember to define falsiness for our cases in this particular case. The macro does that for us. It sort of encapsulates that responsibility. And so there, again, are the case and the condition in that case statement. So, one question that comes up pretty frequently and it's an important one to answer and I certainly don't have all the answers but I've got some guidelines that I've been thinking about is when should we use macros? I'm gonna shamelessly steal my first point from the Elixir Meta-Programming book which you should all read because it's really, really good. And that's just don't. Just don't use macros because they're really complicated. Especially if you're using them when you shouldn't and that's the point. If you can write a regular function to do what you're wanting to do, write a regular function. So here's a bad example. We define a macro add and in order to add two numbers together we produce the quoted expression for adding those two numbers together. Now in order to understand this you have to know okay A and B are going to be quoted because that happens implicitly in a macro and then we're producing a new expression for adding those two things to get whatever. Just do this, do that, right? That's much simpler to understand. So the point is those implementations like that are just a lot more direct and there's no reason to add indirection to your code if you don't have to. You're also much less prone to making errors. Dealing with quoted expressions can be really complicated and so if you don't have to do it, don't do it. So you should be excited about macros, they're really useful but that doesn't mean you use them everywhere, that's the point. Another one that I stumbled upon that I thought was pretty interesting was constants and this is kind of a duh to me now but I honestly did not think about it before this talk. So macros become the code that they produce at compile time so it's a really nice way to be able to name a thing and reference it by name but when it's compiled and executed you don't have any overhead for function calls. That's great, that just makes sense to me. So I thought that's a good use case. DSLs are another use case. I'm gonna go ahead and steal this example from the Elixir Meta-Programming book as well. So Chris talks about how you could produce a DSL for generating HTML code. So this is valid Elixir syntax but you could write a collection of macros, a family of macros that when used together like this would produce the expected HTML code and Phoenix also establishes DSLs. That's a pretty common thing with macros. Like in Phoenix the routes file is a big DSL for generating function heads for each route to be matched. So macros can also be really good for hiding details. This one's interesting. So take this example. You may be familiar with the EX unit library. So in EX unit a lot of stuff happens when you define a test and you probably don't care. I don't care what happens. I just want my tests to run and get out of my way because I'm trying to figure out how to write a program and I'm already writing tests and trying to convince people that that's a good thing. So what's actually happening here? I won't go into all the details but a lot. So when you define, when you call tests, the test macro, when you use that in EX unit, it actually defines a function that's named the same thing as your description and then it adds that function to an accumulating module attribute that's being built up throughout the definition of all your tests and then eventually all the tests are defined and it shuffles that up so that you get some random order to them and runs your tests and that's really interesting that you just don't have to worry about it. We don't have to care that that happens. So macros can be a really good way of sort of guarding your users from that complexity that they just don't need to know about. So macros are also used to reduce boilerplate and that's kind of the same thing as the last thing but I had a really funny example so I wanted to share it with you. Language extension, that's kind of fundamental, right? Everything I've talked about is talking about language extension, ifs and unlesses and Chris implements while in his book and that's really cool. So consider this. We have def module, the module's law what defines a function law returns an atom what and that thing too fancy here but you decide, you know what, metaprogramming is too much magic. I don't want it, I don't want to deal with macros. I want to do it all by hand. I'll say, okay, you like pain, that's cool. Just go ahead and jot this down real quick. You're gonna have to figure out what the quoted expression is for defining that function but that's fine. You can compile, paste this into your IEX and I promise you it will produce a law what module that you can use. One problem though, the Dunder ENV thing there, that's not a variable, I'm sorry, that's a macro. So we can't actually use that because you said you didn't want macros so you can just write this down real quick. Just take a quick note, stick that in your E. It works great, I promise. Literally that is how you define, if you were to expand all the macros, that's what you would get for defining that module. So I tweeted a couple weeks ago it's like 50 characters to define that module but if we don't use macros, we would be typing, it's close to 2,600 characters there so that's pretty cool. And all that's of course because really good macros are invisible and you should write really good macros. So I blogged about this. I've actually heard a lot of people been very nice about the blog. They said that they've read about it. Hopefully you enjoyed the talk and got something out of it as well. You can find me on the internet at IamBerry. I have swag and stuff up here if you want some big nerd ranch swag. You can look like this. But anybody have any questions or anything? We've got plenty of time, I kept it short. Oh, nice, good, good. Hi, well I've used macros before. I've struggled to figure out what they represent in elixir code, like that compiled form in the like kind of Lispy expression, they can get that. Actually can I wanna see what would that look like had I written it in elixir? Does that make sense? Like debugging the macro to what that expands to that can't be difficult. Oh yeah, there's a really great blog post out there. If I'm understanding your question correctly, I believe what you're asking is, sometimes I'm curious, what is being produced by this macro? What's the code? So there's a couple options. Yeah, if I wanted to know what that case looked like. It's like if I just explored it doesn't say case. Yes, yes, okay, so a couple of things. One, check out the macro module. There's an expand function, maybe a macro, who knows, everything's a macro, right? It's defined on the macro module. If you use that with a macro, it will expand one depth into your call and produce the next syntax tree. So that's a good one. But there's another one if you want it to recursively expand all the macros, which is how I got that ridiculous mess on the screen. There's a blog post, I'm so sorry, I don't know who it's written by. He's probably here, hey, if you're here, sorry. But he writes about macro expansion and he has a little tool called MEX, M-E-X stands for macro expansion. And you can just type MEX and then give it a block and inside that call a macro and it will just print to the screen the fully expanded form of that. It's a really great tool for debugging, like just that kind of stuff. No, no, no, it's not, the syntax tree. So, okay, another thing. Macro, on the macro module, there's a two string function. So if you give the two string function a syntax tree, it will show you what the elixir code is for that, yeah. So the macro module, there's a lot of good stuff there. There's also good stuff on the code module. So there's on the code module, there's an eval quoted function that will actually execute the quoted form of the elixir stuff as code, like write it whenever you call it. Yeah. So the abstract syntax tree in elixir is very lispy, schemy. Is that true in Erlang as well? Yeah. I don't know Erlang. I don't even know if Erlang has macros. Somebody told me earlier that it didn't and I was surprised, but oh wait, there's everybody knows this. Oh, okay, okay. So this gentleman says Erlang macros are like string macro, or C macros are just string substitution, but we've got another one here. Oh, this is an Erlang guy, I just saw him. So Erlang macros are like C macros, but there's another feature called parse transforms that act more like elixir macros, but they're much more complicated and painful use. Gotcha, okay. Yeah, elixir. Any more? Yeah, here's one. So going back to your metaphor about quoting expressions as like quoting a string. Right. I think the thing that you talked the least about in that analogy is like in Ruby, you could take that string and run it through eval and actually like generate something and you sort of hinted at being able to do something like that in elixir. So like take an AST and then like, I don't know, export it somewhere else so that someone can then evaluate it and run it. Could you talk maybe a little bit more about that? Yeah, so I understand the question correctly. You're asking if I have an AST that I've stored somewhere, how can I eval that? Like I would eval a Ruby programming a string. So on the code module, there is a function eval quoted and it does exactly that. The second argument to that function is the binding. So that's the sort of the scope, sort of the same terminology in Ruby we have for Ruby binding. So you need to tell it like what variables are, here are the values for the variables referenced in that quoted expression and you could pass your current binding and say just use my scope, right? Does that make sense? Cool, anybody else? Oh, go ahead, what? Yeah, I think you could do that dynamically. I don't know what the use case would be. So the point or the question I guess is could you do all that stuff dynamically? I don't see why not. I haven't necessarily seen it but it seems feasible. There's also an apply function in elixir where you can dynamically make function calls at run time and so that's another kind of dynamic thing. As a matter of fact, that's what X unit uses to execute the test. So it's building up a list of test names when the tests are defined and at the end when all the tests are defined it just goes through that list and applies each of those function names to whatever the module is to execute that test. Yeah, back here? Yeah, you mentioned that when you use quote the macros are compiled. So when you use unquote to kind of break up and make a little more dynamic does that mean it's done at run time instead or is it kind of done in like pieces? Is some of it pre-compiled and some of it's run time? I'm not sure I understand the question. When you're using quote for a macro that gets compiled before run time, right? It gets compiled or it's, yeah, it's compiled, yes. It's compiled, so if you're using unquote does that still pre-compile the pieces that it can and then leave that unquoted part for run time? No, so when you call unquote whatever, so unquote it may be a macro but that expression that you give to unquote is evaluated at the call time and produces something to insert into the syntax tree. So it's not like you have a piece of code that it waits to evaluate until run time. It is evaluated at compile time also. And you would not give unquote a quoted form of an expression. You would give it an actual Ruby expression that it does its thing with, if that makes sense. Here we go, hey, Michael. Hey, good talk. Thank you. When I've been trying to wrap my head around macros I ran into something in a macro module called macro.escape and I have not been able to wrap my head around that. I was hoping you had looked at it and could explain what the heck it's for. Could you, do you have any point of reference for me? I mean, if you don't know right off top of your head then whatever, we can just play with it later. But like, if anyone knows then please. Because I've stared at this and it's made me cry. It's like, it almost sounds like either quoting or unquoting. I can't get my head in the matrix enough to figure out which way it goes right now. But it takes an expression and then seems to escape it. So looking, I think of quotes the way you think of like with string interpolation. It's kind of like putting escapes on something in a string but I can't figure out when it would get used. So I just didn't know if anyone wanted to. We should play with it because I don't know off the top of my head. Anybody else? Oh wait, we got one over here. Maybe a question, maybe an answer, who knows? Man, Ernie is gonna be so fit after this. I mean, he's pretty ripped right now, but just wait. So this may not be true, but what I found is that macro escape means the aliases of your variables are different at that compile time location. So when you escape it says, well wait until I unescape this variable for you to look into the aliases and find out what the variable actually is. Okay, yeah, we're gonna figure this out. I know we can. Anybody else? Here we go. Another Michael. If you could just maybe do it from this side to this side so I can get my cardio in. I just have a question about compiled code size. If you write a ton of macros into your code, is that gonna explode the size of your compiled code? And if so, what are some strategies where you can still use macros, but maybe reduce that? So that's a really good question. And Jose has some good direction on this. There's some libraries that I've seen where macros are so-called not used correctly. So one use of macros is you could dynamically define functions on things. But if those functions don't depend on something like special, like if they're not doing something special when you define them, there's really no reason not to just call them in another place. So the reason that this is an answer to your question is if you had a macro that defined a function, the add function, let's say that we looked at, on every module that used that macro, well then that add function is going to be re-implemented all over the place, every time that macro is used. And that's useless, right? You could just store the implementation of add in one place and reference it. And if you really didn't wanna reference the module that it's defined on, just import it into your module so that you don't have to do that. So it'll become, I don't know what the right term is, but it's like it's available, it's in scope or something. Does that help? So the answer is yes. You could definitely bulk up, but I would say that you're not using macros right if you did that. I don't know if this is beyond the scope of your talk or not, but I'm curious, could you maybe talk a little bit about macrohygiene? Oh yeah, yeah, so macrohygiene is basically the idea that, well, the way that I understand it is you should kinda be able to see whatever you're talking about around your macro. So if there's a variable that's available when the macro is called, then the expression that's being evaluated in the macro should not know about that variable. Like things should not come out of nowhere. But I think you're right, it's a little beyond this because I don't have a great ready-to-go answer for it. The reason that it's a thing is to keep people from a lot of pain because you don't want variables and data to just appear out of nowhere. But there are certain cases, and there are ways to get around the hygiene that the var bang I think is the function that does that. And that's actually, you should go read, definitely read the Elixir Meta-Programming book because Chris talks about, he has a really good example for when you have to sort of violate the hygienic nature of macros in order to define that HTML example actually. Because the HTML example, if you think about it, you're sort of building up nested strings throughout it. And so if that one macro hasn't finished, and how will you know to close it when the other macro is executed, and it actually is passing along like a string that it's building up over time or by not using hygiene in the macro. Another, cool, thanks. Anybody else? Ernie, is one more good run. Cool, oh wait, yes. Thank you for the good talk. Thank you. I have a question about, is there any document, what is a macro or what is not a macro in Elixir to see? What is and what isn't a macro in the language? Actually, it's sort of, it's fairly clean cut. I wouldn't say there's a document, but if you are just thinking about the sort of fundamentals of the language, like what's defined in kernel, basically everything defined in kernel is somebody's gonna tell me I'm wrong about this, I can feel it already. I'm pretty sure everything defined in kernel is functions and everything defined in special forms is macros. I don't think anything defined in kernel is a macro. You don't know. All right, anybody else? But check out the kernel modules because there's a lot of interesting stuff there. There are macros. Yeah, I realized after I said that the thing about special forms is there's no implementation in special forms. Special forms is the things that are implemented in Erlang. So I was probably completely wrong about that. Y'all got me. The documentation, yeah, and that's why we have def macro, so you can tell right there. Oh, yeah, and the documentation always splits up the macros and functions too, so. Yeah, documentation. Sorry, that's totally, that's totally split there. It's not true. Gotcha. All right, anybody else? Cool, thank you so much.