Adventures in Metaprogramming: Macros versus Shapeless by Dave Gurnell

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone and I can't really see from up here welcome to my talk my name is Dave Jenelle I'm here to talk to you about something very exciting because programming is pretty exciting right yeah the meta programming is exciting exciting but first I have a small aside oh this is where this happens again my last time I did this my clicker failed so I might have to go behind a brief announcement do then e1 know what I'm going to talk about there here okay so my company underscore we're a consultant team we're also training company we write a lot of books you can tell which one we hired a designer to design the cover of and our cheers yeah I'll get it back anyway look this is just a very quick announcement to say as of about yesterday all of our books are no longer cost money so you can go to our website and get any one of our books for free there's the website and we wrote the blog posts about why we did it so there you go there's the publicity stunt and now let's get on with the talk so it's this one going to work this one's not working either then decided I need to turn to switch them yes I do there we go brilliant okay back to the schedule program so we're talking about meta programming what is what is meta programming well we can think of it as this idea of writing programs that write programs but a scholar developers we can also think about it as teaching the compiler to write code for us giving it rules to write code for us and this is really good this is something we can use for a lot of purposes at least two of those purposes are the ones I'm going to talk about today are making nice DSL for our libraries and for getting rid of boilerplate from our code but the reason I'm giving a talk about meta programming is that it can also be quite difficult to get right so there's various different approaches to mesh programming in Scala they're suitable for different tasks and if we choose the wrong approach wrong tasks we can spend more time getting things to work than we otherwise would so we're going to talk about two things we're going to talk about macros and shapeless and we're going to cover topics like which of these should we choose for any given problem how can we make that approach work well with our code so how can we integrate it neatly into our code how should we get started what sort of what how should we design our code and we're going to see all of this through the medium of a couple of examples apologize and being slightly sketchy because the slides in front of me is actually showing me what's on the screen and not the preview of my next slide so I'm slightly faced by that I'll see if I can ignore it I'm going to be quite high level in this talk I'm not going to I'm going to show you Koba I'm not going to walk through it as I would normally do with the talk all of the code is here on this github so if you have a laptop and you want to look through it now you can do that or you can look afterwards and I'll point you to many learning resources at the end of the session so I've got two case classes case classes use cases examples case studies there there we go case studies for you and we're going to look at both case studies from the point of view of macros and the point of view of shapeless and the first case study is the simplest I could think of to give us a warm-up which is just building values constructing values given types so here is our case study we have a simple case class something very regularly all right all right in our code and we want to be able to create values of it but we are lazy I'm lazy I hope you're a lady too we want to build a kata class without actually okay points not working without actually specifying all the parameters of the constructor and it you know we can do this by making default values on the arguments that's all fine but we weren't going to do it with some fancy programming techniques to justify our scholar salaries so we're going to write some macros or check this code to do it so we can write create and give it a type and it's going to build a very exact type so let's start off by looking about how looking at how we might do this with a macro caveat I'm talking about Scala reflect macros I'm not cool enough to know about Netta yes so we can be looking at the old version all the macros are fairly short that's actually one of the kind of points and of this talk and I assume are easy to port but if there's only a scholar meta people around they can comment on that towards the end so we're going to write code like this and what a macro does is it rewrites our code for us it expands it into something more useful and the way we do that is by defining our create function as a macro like this so we call create it has a type parameter a and we're returning a value of type a but the implementation in terms of the macro is a piece of code that runs inside the compiler so rather than thinking about types we're going to think about the metadata the compiler is holding about those types so in this case you see we have this thing called a week type tag which is part of the macro API and it's basically an interface to say what is this type a what's its name what methods it has got all of these kind of questions and then whether returning a value of type a we're going to return a tree and a tree is an abstract syntax tree so we're actually building a piece of code to construct an A so broadly speaking we do B first of all we try to find an apply method in our implementation we try to find an apply method for our type and then we have to look at all the parameters to that apply method and find out what values to insert what expressions to insert at each position and then this Q thing at the end is quasi quote is constructing a piece of Scala code and that's what we return ok great it's dead silence I assume we're all I get are we ok yeah it's better right cool ok so these are the steps are going to go through like I said I'm going to show you the code I'm going to show you how it works so we start with our macro our the UPU code user writes and then we look up that type that's a thing inside the the macro API from that we look up a thing called a symbol a symbol represents a definition so in this case it'll be like class ice-cream and that will give us all sorts information what constructors look like what feels it like and what the companion object looks like so he goes to the symbol for the companion object and then when we've done that we look at all the message for the companion object we pick a method called apply this is literally the level of sophistication that we're operating on we look to the string apply in the method name and from there we figure out all the parameter types and when we've done that we generate expressions for each parameter type and we are done sounds simple right this is the code that does it it's about 40 lines for people who are judging by weight so 40 lines worth of value delivered and that part of the top there is the bit that I just showed you the three lines but expanded out we have a helper method to look for an apply apply method so you can see there we're saying find a member that's a method in is public and has the right return type and all of that and then we have a thing at the end this helper method here is helping us fill in the parameter types so what that's doing this is the only bit of code I want to focus on is it is taking a type of one of those parameters and saying what expression should I fill in and this is the simplest possible implementation I could think of if it's a string I've get return an empty string this expression representing an empty string if it's in return zero and if it's a billion I'll return false and if there's anything else well you know we only designed this to work with three types sorry I'm going to raise a compilation error okay that gives us working code we can take an ice-cream which has a string and infinite billion in it and we can build our constructor cool however there's a bunch of problems with it can anyone think of a problem with this piece of code shout out don't be shy second it is not extensible to new types it only knows about three types and we can extend it right we can extend to double and long and all these other types but we can never extend it to all the types of the user knows about so it's it's not extendable and that's like a fatal flaw right anyone who wants to construct values is going to want to strap values that contain things of their own types so what we need to do here is we need to actually think twice that initial implementation is naive let's go back and look at how we can do this macro again and make it extendable so right think about it users going to type create a we're going to have to look up that type a we're going to have to go through all the parameter types and whatever type of parameters we have we need to somehow look up some code based on the type that we can use to generate the the expression we need right now what programming pattern does that sound like that sounds like a type pass with an appropriate whoo yes absolutely so we're going to use a type class to support our macro so this is an interesting thing right here I'm talking about better programming I'm talking about fancy things a type class is a relatively uncertain teasing well it's pretty cool actually it's actually very cool but it's not strictly speaking a stuff we're talking about here and yes it's essential so I'm going to build this type class I've called it pure which is just the same name as this method we get in cats to do it it's just a type class that takes a type parameter a and has a method to return an A and then I can start building instances of the type class those are my 3 test instances the three types I care about and I can summon an inch of those instances string into Billy and using this helper method called implicitly so anywhere in my code I could say get me a pure of string implicitly pure a string and the compiler will go and look for anything tagged implicit this in scope and it will return it to me so we can use that with our macro with our helper method the one that summons the values for the parameters and we can just reimplemented like this so we're still looking for the parameter type we're returning an expression but the expression that we are returning is making use of the type class and I've got these weird like routes Khalid pre-death things in here macros in Scala reflects our unhygenic and so any variable name you use the user could come along and hijack it and turn it to something else probably by accident not maliciously so I'm globally a referencing all the types here basically this is this piece of code right so I can say okay finally a cure for my parameter whatever type of parameter I have and call its value method and that will give me an expression that gives me a validator that type so now when I write create ice cream I get something that looks like this not the sort of code we want to write by hand but who cares right it's a macro that's writing the code for us and from there we have a working solution so now use a customizable it can handle any parameter type we throw it or the user froze of it because if they want to have a parameter of type Java util date for example they just go and implement an instance of pure tagatose implicit and we're good but this approach is brittle it's brittle in the numerous ways I don't know if you sort of you if you've written any macros before you're probably looking at this flow chart that I built and thinking well there's a whole bunch of steps in here that can break what if I call pure and I don't provide a class a type that is a class I could provide you know an abstract type or or something something weird is one of these it's got many different types of types it could be something that's another class and maybe we can't look up this symbol what if the symbol doesn't have a companion object what if the companion object doesn't have an apply method what if you've got to imply methods there's all these weird sort of things that we have to take into account in our own code they're all solvable and a valid solution is to just go well look the lonely works case classes you've got to have one apply method blah blah blah blah right so is anyone use play here that macro with the jason macro the json dot format macro who's had the error where you've got to apply methods on your class and it won't work anymore right so the macro just doesn't cope with this it could cope with this it could use it heuristic to choose which one but that is sort of applying bias you know that the designers bias to it so it quite rightfully I think sales okay so what and as macro writers these are all tedious things that our users will throw back at us because of them working in particular situation so we'll look at the shapeless implementation of this now and the point here is just to show that in this implementation we are looking at things in a lack of high level of abstraction so we don't have to think about as many things so the way the shapeless stuff will work we're still going to use our pure type class but we're going to repurpose it to actually solve the whole problem here so we are going to implement a new instance of pure for any data type so any data type a I can summon a value of type a so rather than dealing with a single parameter to a constructor it will just deal with the whole thing and you might say well why didn't you do that with the macro and the answer is I didn't think about it but anyway we got there now and the way it does it this is you know I talked about in all the tools I've given him out shakers I always talk about one aspect of shapeless which is tight fast derivation so specifically solving this problem and and and I'm focusing my discussion to just this part of shakers again but the way this is going to work is shapeless we'll give us a piece of magical machinery called a generic generic is a tight class where we give it a data type and it will map that onto another data type so we say here's ice cream can you give me the structure of ice cream or can you map this onto another data type which we can process generically and shape us we'll say yes I can I can give you this thing it is an H list but more importantly it is showing us it's a recursively defined type it's showing us what the constituent parts of ice-cream are what sort of order they appear in and how many there are and because this type has structure we can analyze it we can pull its pieces and we can write instances of cure to cope with each part independently so we write a pure for ice-cream the way our algorithm would work is we use the generic to turn that into this generic representation string cons in conclusion foundational and then we say okay well how am I going to generate a value of this well I can generate a value of string I've already written that rule I've got a pure a string and then maybe I look at the tail of the H list well how do I do that I've used my value since I look at the tail of that I use my value boolean and I can easily generate a value of an empty H list and all of these components together recursively call one another and we can then get all the way back up to our ice cream and the codes looks something like this this kind of code is I'm not going to go into the details I have actually copies the shape this book here to give out at the end if you if you find this code difficult to pass but basically the idea is we have a rule I wonder if I've done this yeah I have a rule for mth lists we have a rule to say given a rule for the tail of my H list and a rule for the head how do I combine them together and I say have a rule that says given a rule for an ageless how do i generate a rule for something that maps onto that age list thus the problem is solved so this will work for all case classes out of the box it's subject to some constraints right so there are certain data types like regular classes with some vague constraints that it won't work for but the key thing is we haven't had to worry about finding apply methods of doing all this this low-level stuff we've written 16 lines of code including crazy line wrapping probably more like six lines seven lines of code if we were to actually write those method headers but then I would need sixteen by ten slides rather than know whatever 16 by 5 wide wide screen I can't do ratios okay so what have we done we got we got better code out of using shapeless in the instance and the reason we got better code is because I'll back up the reason we got better code is because the solution we're writing is operating on a high level of abstraction is saying rather than saying what class have you got what methods is that got who is there this method is it got parameters and going through lists we're simply saying what are the components that make up this class let's solve for those components and shapeless is is doing this sort of the underlying processing okay so so in this instance I think shape such a place is a is Aneta solution there are a couple of things we can say negatively about I'm using words it's bad when you're doing a talking culling of words there's some negative things we could maybe say criticisms that people might raise against this approach what about error messages what about compiled times I'll just go into them error messages well really when we're writing shapeless code we're dealing with implicit in fact actually when we are writing the macro code we were dealing with implicit error message for implicit are I couldn't find the implicit they don't give you any information about the problem whatsoever so that's that's a tricky a tricky problem and we have to solve by sort of working through all the steps that our shapeless solution will be doing instead of trying to mediate stefan seeing is that getting error message and so on apparently there are better error messages about implicit sin dot e so I have heard from Martin in a corridor between talks at some point maybe someone can can enlighten us on that at the end the other thing is compile times and compile times are not as big a problem as you might think until they are imagine what the H lists are this looks like it's pretty big data now imagine that the very last field is a type that we don't know how to don't have an instance of pure for so when we are solving this problem recursively we're going to look at this H list we're going to run all the way down to the ends fail on that last field you can imagine there's a lot of intermediate processing is that in general if we can't find a solution the the shapeless code will look at all these hundreds of possibilities and then say I can't find a solution so we can be subject to that problem worse still we can have recursive data structures where you know if you think this has got 26 different fields in it this thing has got three by three by three different possibilities that it can expand into so the solution with that is to use intermediate implicit definitions so those are we can say in this instance first of all let's work out how to solve this problem for inner then we say I've got a solution they used a single cached implicit which allows us to say solve this and then the solution to this is stored it in a pure then when I'm solving for middle because I'm dealing with instances the search space is collapsed so we can get much more efficient compile times over that okay oh and there's also we mustn't forget the the stuff that Mars has been working on the type level compiler which is working its way into the scarlet I forget there's some stuff is happening it's going to get faster lot faster because the optimizations basically can sense this use case is pattern and sort of reorder the order in which the compiler does things okay so this is in my opinion or a structural solution is possibly the wrong way of saying this you get a better solution from shapers here because we're thinking at a higher level abstraction we have fewer cases to worry about - okay cool good all right but the other thing to note is that most of our solution is just it's nothing to do with shape that's all what sort of nothing to escape to some macros it's a type class and by writing the type class to begin with we inform both solutions okay I'm going to skip this part okay sweets right I got another case study this one is a slightly different type of thing we're going to be jumping over to data validations anyone have any questions about the first case study no good right we can we can keep going another case study here this is to do a validation I have a little library I'm working on it's like a toy library called checklists which does exactly this so if this interests you go check out checklist and the idea here is that we're doing runtime validation so we got our ice cream again the data type of ice cream gives us a whole bunch of information about that tells us what types of fields are but it doesn't tell us other useful things like it doesn't tell us that the number of cherries on an ice cream must be zero or greater and we can solve that with various clever libraries like refined or we can do like a simple solution which is just do some runtime validation so what checklist allows you to do is to build a function essentially you can pass an ice cream into it it tells you what's wrong with it so this is this is a nice DSL logical syntax and we're saying you know check this filled with this rule check the name filled with a non empty string rule check cherries filled with this greater than equal and zero rule pretty cool what's even cooler is when you get back error messages it'll tell you where things went wrong so again this is inspired by the play JSON library right when you when Jason validation fails it tells you where all the a validation errors happen and the key thing here is the names of the fields that we report in our data in our error messages at the end are based upon the names of the fields that we are analyzing how can we achieve that better programming so let's look at this with macros so the way we do it with a macro is we implement our field methods as a macro and then we look at what the person's written here cherries and we turn it into a string and also use it as an accessor method so and and that the key to understanding this I'll just walk you through how the library is designed to show you how this works the key to understanding this is that every part of this rule is another rule it's all rules all the way down so this gte zero is also a rule so what we can do GT zero on its own is a rule you can apply it to an integer so you can say you know you say apply this rule to minus one it will say minus 1 must be greater than or equal to zero it has the rules failed what we can also do then is we can apply combinators to the rule to get up to what we need it to be when we're dealing with a live screen so we can say prefix this rule with this path so you'll notice with actually when the original rule gives me an error message it says nil at the end there the path is empty that says the whole piece of data is wrong you say prefixes of cherries it says ok well it's not the hole it is we're now reporting the same error message what we're saying this field cherries is wrong then we can use this fancy name method contra map which is like that being backwards to say this rule is now not a rule that checks an int it's a rule it checks something else in this case an ice cream and what we're going to do when we run the rule is we're going to call this function cherries and then run the original rule on it okay so now we can supply a whole line scream and we check just that one field and when we check the field the result comes out with the right method name so what we're going to do is we're going to create an expansion that looks like this when we say our original original rule we're instead saying here are two possible rules I want to add them together and is a particularly undemocratic so I want to take the name rule and the cherries rule and apply them both and collect all the error messages so how do we do this so I mean the key thing here I guess is that each one of these fields macros is expanding into one of the rules here so we're going to write field as a macro and you know the method itself takes in a function and another rule and returns a rule and the macro looks like this you see def field macro third line down there takes in a tree taking an expression that user has supplied and another expression and returns an expression and this is actually the complete implementation all we do is we look at the function expression we Pat match on it you can see it with basically saying are you a function that returns a field on some value C they see the structure we have an argument list and object name on the right hand side if you are then I want to extract the name part which is an identifier and I want to turn it into a string by calling two string and I want to turn that into a string literal expression by sticking it in a quasi quote and if it's anything else sale and then we expand into this thing at the ends here we say rules what prefix names or Contra Matt func we know that part and then this C dot prefix part is to just say well when we are expanding the sealed macro we are in like a method call position so I need you to bolt this method cool if an method onto what we already had and that's it that's the whole thing for those who accounting that is also 16 lines of code and I think that's pretty pretty straightforward pretty easy to understand right I mean we talked about scholar Affleck going away and Scarlet Letter coming in I'm feel quite happy putting this macro in my code right now and then rewriting it when scholar reflect doesn't work anymore that's short enough and light enough that it's not a maintenance problem so we've now got this expansion okay analysis I like this I think this is easy I hope I hope you agree with me it is pretty straightforward macro and the reason it's short and the reason it's simple is first of all the problem we're solving is quite straightforward but also it is a syntactic problem we are just putting a very very thin layer of DSL over a library we've already written so by writing the library by just doing functional programming we have solved that problem and then we're doing now is offering convenience to the user so that's that's a real key point I want to provide if you write your library library correctly first or you think about cleaning functional design then this stuff is easy to add on top let's look at the shapeless solution you might be surprised to hear that you can solve this with shapeless it doesn't feel like a pasty problem given the last example I gave the way we do this is we use a thing called a labelled generic so just as generic will give you this data structure representing the types of all the fields in your case class the label generic will tell you here all types and here are all the names of the fields how long I got by the way another another 15 pretty like a load of time here are the names the field so you see this this field type thing is kind of crazy right it's a type but it has a symbol in it which is a bit weird so what that is and that obviously the symbol is telling us what the name of the field is but it is actually a type is to think what a literal type who total literal types before so it's a few people and a lot of people who haven't that's fair enough right this is a fairly new thing these are things that have existed or singleton types and literal types have sort of existed in the Scala compiler but we haven't been able to write them until very very recently so they sort of an underlying mechanism but now we can actually write them in code like scarlet 211 9 and I forget all the numbers but but recent versions of the Scala compiler and so if you see you can take a the simple name and you can put it in a variable of sight symbol that's fine you can also put it in a variable of type name so name there is the type of that particular symbol it's a sub type of symbol we don't normally use these types because they're not very useful as soon as we change the symbol or we take that number 42 and we add one to it it's no longer a type 42 becomes an int so normally not that useful but in this type with this case they're really useful because we can key off of these types when we're searching for implicit so we can search for not just an implicit for a string we can search search for an implicit the string and look up what the name is and then resolve and results and code turn the name into a value at runtime Bobby so what the way we express our rules if we're going to do a shapeless is we actually rather than use accessor methods we write just symbol literals in our code and we use a thing called from shape it's called a witness which will calculate what the type of that symbol literal would be and this is the code I don't just blur your eyes don't look at it in detail but we can see somewhere at the top there's the word witness and that is this thing where it's going it's going to be an implicit conversion there we write a symbol then shape this calculates what the singleton type for that would be what the literal type words that form that would be and then we start using that in all our recursive search for implicit so back to 40 lines of code again it's funny these two examples I have the same lines of code in opposite orders that's 40 lines of code again so it is it is possible to do this in shapeless I think the solution that has a much cleaner implementation as a macro and that's that's because of the nature of the problem so this is the first thing you should think about when trying to when trying to solve probably mess of programming it's what type of problem you trying to solve okay I'm very nearly wrapping up so take-homes this is the deep take-home point macros good for syntactic staff shapeless good source of structural or like type based inferring types from other types of learning solution some other types kind of stuff so that's your first choice points the other thing though a really key take-home point here that in both cases most of the solution that we've been dealing with most of the code that we're dealing with is about designing a library first so make some algebraic data types do some structural recursion make some type classes all these good functional practices that solves your problem this is just a thin layer on top so so this is what I have been calling the quotable slide metaprogramming is kind of at least for these these cases it's convenience right we solved from first and then we make life easier for the developer on top of that and I don't know if I don't know if I'm comfortable enough to say that that is the way you should think about it for all problems ever but it's certainly the way that I think about it for problems where I try to use this stuff in my code so we have a couple of minutes I want to just point you to some useful topics useful further reading on the macro side I fixed your name now so I wrote timers known as primer Wix shout-out to Wix who employed Tomer I did talk about macros time into stiphu to talk about using macros to validation which is great really on topic for this they're both great also crisp virtual meta programming talk he gave this at scholar Matsuri this is actually a London Scala user group video it has a slightly higher resolution slide set on it that's all good good good resources for anything that macros shapeless you can get a copy of my book if you want one and you don't have one you can grab them from the front afterwards there's the talk version of the book is that middle link that's a 20-minute talk where we go through a type class in detail from beginning to end and then if you want to hear somebody who really uses shapeless in real libraries that real people use as opposed to my toy library's Santa holidays workshop from scholar exchange a couple years ago is really great but I've said that like most of this most of this stuff I've been talking about it's like just just write nice clean functional code what is clean functional code if you're interested if you're sort of setting use function programming and you sort of want to know what people keep talking about in in terms of what is clean pure functional code these are like the least complicated introductory talks I could point you to so my colleague Knoll goes through this is the main principles that we use in our training courses which are also one of the books that we've now open sourced and then this if you want to see the evolution of checklist from just an idea through to the library I've given a couple of talks about that so thank you very much I'm required to say please rate all sessions on the scale of a zap but yes no thank you and does anyone have any questions they're just so thank you so I'm about the letter example that you provided them what has been our compiled times the schaeffler solution are the microcredit solution well has better start compile time so the examples we sort well examples are given to the second example the macros faster is a very very simple problem for a macro to solve for the first example it depends on how you do things so the thing that's slow is not shapeless but the thing that's slow is implicit resolution right finding implicit so when you're using implicit so you miss it's solving things of the implicit as a search problem and the complexity the problem depends on the complexity of the search space so if you sort of provides the biggest data structure in the world and ask tapeless to divide it into all its constituent parts and solve something with visits then that could be very very slow and I'm talking you know maybe you have a hundred feel a couple of hundred fields in your algebraic data typing your steal traits and your case classes so that's a tricky problem solve and again the way to solve it is don't deal with the whole thing in one go break it down if you're if you have something with a couple hundred fields in it the likelihood is you have intermediate types you solve for those types so I'm dodging the question slightly but the the answer is it depends on how your macros are implemented it depends on how your shape is code to implement it and there are if you think about the search space that you're creating with implicit that's the way to get around this kind of stuff so make sense yep can I make a small to love question maybe then sure yeah so I'm regarding the future what do you think will get the better performance and improvement macros are like emphases resolution well I think maybe I'll duck that question and pass it to the man with the beard so the answer that question is that the work that I've been doing on inductive intercept but Dave mentioned in this talk is I think I think the the right solution to this problem what it the way it works it looks the kind of inductive patterns that the Dave's Illustrated very very nicely in his example and if you like souls it directly rather than using the fully general intercept search mechanism that's that that's used to cover all cases it has a a a particular solution strategy for inductions which would have the same compile time performance as if you were to code it up by hand as a macro essentially there you go and that's what's the sort of the what the the thing that I messed up on that Mouse sorry and it can keep the mic Romar's respect what's the where are we with that and what's the what can people expect in terms of so it's a pull request against Scala 211 and 212 and it's not merged yet III had to badger Adrian at some point over the next day or two about that and there is one missing piece which means that it's not at the moment a completely seamless solution which is which is the use of lazy which you appeared in your slides but it didn't dimension it so lays lazy is an important feature of this because it's one of the things which allows implicit resolutions which technically speaking should diverge as far as the Scala compiler to converge in these kinds of inductive cases where we know that that's the right thing to do that uses this bit of magic machinery in shape is called lazy I am in the process of translating that into an interpretation of what by name implicit arguments would be in Scala that's actually something that Martin picked up and has already implemented in beaten me to it in terms of enhancing it Dottie is also do me a big favor actually writing a sit for it so I don't I don't have to do that which is nice so to get the full benefits of what I've been promising in terms of induction inductive implicit heuristics it needs both the stuff I've already done plus this but that's that's pretty straightforward and I'm expecting to have that in the next in the next time double scholar released quite soon so yeah watch a tight level scholar near you any other questions for anyone yeah we've got one here on the right did you have your handout on the front or anyone have already see very well hi so you skipped a part of your presentation and I saw it mentioned Mac wire so I was wondering what you were going to talk about that so that's very simple and so neck wire is anyone use Mac wire here yeah loads of people cool cool right okay so Mike wire is a dependency injection library and it's let's just tell you what let's do mak hyeo mak hyeo mak wire that quite mad choir wait for it wait for it mmm esters compile times mac wire so Mac wire yeah it's a dependency injection library it's implemented using macros so if you have some database and some web routing and you have a service which needs a database on the web routing rather than write that by hand you can use okay all right I want to stay on the slide please you can use this wire macro so you can see that wire macro expands into this larger call now the wire macro is a macro it's implemented using macros it looks like a really simple macro to write right but the key thing is it's doing sort of the equivalent of implicit resolution so it's looking at the parameters to service and seeing what types of these what definitions do I have in scope that are off the right types and and it's not using a clitoris and that's specifically it's a design goal of Mac wire so it handles implicit through one system was using a pixel resolution of one thing it wants to deal with things that are not implicit so there is a lot of library in macro which is just about traversing scopes and finding these things and it's a non-trivial problem it's a very difficult problem 350 lines of code way longer than anything that I've shown and presumably took a long time to get right and the point there is merely that if you find yourself doing things like this you're using the wrong approach right you can rely on built-in mechanisms of Scala to do a lot of a heavy lifting so you don't have to write it in your master programming that was that was all it was I thought it was quite interesting when I found out when I was sort of browsing the source code I thought okay I thought this is really easy but actually it's quite hard and it's pretty impressive what they've done anymore so then okay so the second example you had you were using labeled generic as far as I know that's also implemented with macros underneath their arm yes there are some small macros at the core of of shapeless so you need a macro to get hold of the field names so you know seems to be replacing a macro implementation with the library that uses my crew I have a question for you what is the best part of macro one you don't have to right yeah absolutely yeah so I mean yes exactly there are there are these things but there you know that the problem with this code is not using the macro the problem is having to maintain the macro so having one centrally maintained macros it's more essentially may maintain macro and it also not only means that you get out having to maintain it there are all sorts of I've had macros that I thought would work really well where when somebody rather than using values is a lazy Val it crashes a compiler so this since you know and we're talking about star reflect here and this is why scholar Mehta is coming along we can get a better abstraction from the compiler and it's safer and it is reason about but there are there will be situations crows that you haven't thought about basically do okay cool all right well thank you very much everyone we'll go to break [Applause]
Info
Channel: Scala Days Conferences
Views: 1,769
Rating: undefined out of 5
Keywords: scala, conference, scala days, scaladays, 2017, copenhagen, Gurnell, @davegurnell, underscore, developer, metaprogramming, macros, shapeless, code, generation, technique, programming, algebraic, data, talk, session, macro, tools, type classes
Id: FBg7K6LKdVg
Channel Id: undefined
Length: 42min 34sec (2554 seconds)
Published: Wed Jun 28 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.