KotlinConf 2018 - Creating Internal DSLs in Kotlin by Venkat Subramaniam

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] [Applause] [Music] alright let's get started welcome to the session on creating internal D assaults with Kotlin my name is Venkat Subramanyam we're going to talk about just a little bit about what DSL are and why internal DSL and then we'll talk about why cotton is a really good language for it and then we'll dive into some examples on how do we how do we really create dsls and how we can play with it well let's talk a little bit about DSL it's domain-specific languages well generally speaking we use languages that are what we call as general purpose languages we can write pretty much any code but a DSL is a language we create which is very specific to a particular domain or a particular application this gives a lot of opportunity for us to give a very targeted API for the users of our application depending on what who the users are so as a result this can be very useful in applications where our users can provide input to the application where they can configure a certain things or provide certain domain specific rules and our business logic and so on so it's really to really help them to ease into the use of the application itself let's talk about some examples of DSL that we have seen we've actually seen a lot of these in our lives sometimes we don't realize that these are actually dear selves when it comes to D yourselves when I'm going to talk about the examples we'll talk about the types of DSL along the way as well so what are external DSL versus internal DSL x' well when it comes to examples of dear cells we normally talk about things like for example if you remember the good old makefile we used to use way back in time and then you can think about the end files you can think about CSS cascading style sheet so these are all really a convenient way to specify something very specific CSS is really a good example where you are specifying their styling information in a in a kind of a weird syntax but once you get used to it it becomes really expressive but when it comes to DSL there are two types of it external versus internal so external DSL is where you get to define your own language you get to define your own syntax you get to define everything all by yourself but the disadvantage of external DSL is you have to take the burden of parsing it as well I remember way back in time one of the very first jobs I had out of the university I was asked to maintain there Lex and yak parser and when I joined the team I thought they wanted me to do this wonderful work of maintaining the Lex and yak parser because was really good well then once you take your first job after a year you realize they give you things to do not because you're really good they give you things to do because nobody else wants to do it and and I had to do this for the next three years until I quit actually and the point really is that you have to do a lot of Lex and yak parsing and that cannot be a lot of fun if you have to do this over and over but but the beauty of an external dsls you have the flexibility of the syntax like I said the disadvantage is it's a lot of work to maintain this parsing an internal DSL on the other hand is a DSL that rides on an existing language so you're not going to sit down and write a parser for it the language compiler itself and the language runtime itself becomes the tool that you can leverage the benefit of courses you're not spending your time writing parsers and and that can be an incredibly tough job but the disadvantage of an internal DSL is that you have to really work within the confines of the language if your language is really flexible and fluent you have a little bit more you know ability to be fluent in your own DSL if the language is not that fluent there's not a whole lot you can do with it other than you know stay with the limitations the nice thing about an internal DSL is you are able to bend the language so one of the things that you really need to do when it comes into all DSLRs you have to be a little bit more creative for example you want to be able to express a certain syntax and you got to sit there and say how do we make this language really work this way and and how do you really get to that point where you can actually bend the language to do it well I in my experience there are two things that I think are very useful to create internal dia cells one is a lot of patience you really have to have patience because things won't just won't work when you want them to work the other thing that's helped me a lot is coffee just drink a lot of coffee and then sit down and just you know soldier through Word and you'll get a spur of a moment inspiration and say ah look I never thought I could do this and you can vent the language to do it but before we talk about how to do this let's talk about some of the characteristics of internal DSLR just deer cells in general so what are the first and foremost things about a DSL is a context a context is extremely important so why is a context important a context helps us to remove the noise and one of the things about a DSL is that it is very you know easy to express what you want in a DSL and as a result a context is extremely important so what is a context provide for us humans context provides then ability to continue a conversation for example maybe my wife and I saw a movie a week ago and and we are at home maybe in different parts of the house across the hall and and we hear one of the kids say something that is something similar to what we heard in the movie we could look at each other and we could smile and we just communicated even though we didn't use any words I know that sounds really romantic but the point is that there's a context in the conversation so when you have a context you need fewer words you can be very expressive and and one of the key things about DSL are they carry the context the second thing a DSL cares about a lot is fluency a fluency is how you can be very expressive in terms of the code begins to read like English if you want to you know think about it that way and so it doesn't feel like code that's the whole point about fluency is it doesn't feel like code so so in in a language which is very fluent you have the ability to be more fluent in a language that's less fluent that becomes really hard so there are characteristics are characteristics of a language that can make things really easy for you so what make Scotland really a good language or creating internal DSL and and one of the things that is exciting about languages like Cortland is that by nature the language is very fluent and and then the addition to it the language also gives you a quite a number of interesting capabilities to do things that usually is really hard in a static type statically typed language but I personally believe that Cartland pushes the boundaries quite a bit so there are things you can do in Cartland that you're like wow that's pretty amazing how I'm able to do that that's kind of a moment I had when I started learning the language so let's talk about a few things that make Kotlin really good I'm gonna talk about you know discrete number of different features and then I'll put them together to see how we can make use of those features to create fluent syntax and code and NTS else you will see a lot of different examples of DSL surround so I won't go into details over here I'll focus more on creating DSL rather than using existing D ourselves but if you want to look for existing da cells there are quite a number of things we can look at for example to take a look at the types if HTML builder that's available in Kotlin that's a really good example of seeing how you can create your own da cells that are type safe as well another example to look at is a spring foo and an spring uses a very fluent DSL to express you know services and configurations that's another inspiration you can look at as well but let's dive in and talk about what makes Carlin special and then we'll talk about how to really use it to create our own DSL the first and foremost is that semicolon is optional now this may be may not really sound that you know useful in the beginning but to me this is a huge benefit for a language to not to have type semicolons those of us who were programmed in predominantly languages like Java our pinkie has gotten used to hitting that semicolon over and over and over isn't it well with language like Cartland you don't have to put semicolons the other day I went back to programming in Java and I forgot to put the semicolon and the compiler complained that I'm missing the semicolon I was arguing with the compiler saying I'm not really missing it you see the white really is that you know language is kind of you know ask you to put semicolons but I can go ahead and type this over here and say for example hello and and the beauty of this is I can just run this code right here and and you don't have to put that semicolon and of course if you put semicolon Cartland doesn't complain to you but it kind of kindly looks at you and says you'll get over it over time but the point really is you don't have to really put semicolons and and as or so when you start programming in Catalan your right pinky actually becomes a little better if you notice that you know it's like I'm not being abused to press this semicolon over and over it can do other meaningful things so that's one thing but why is it so important that we don't put semicolons because semicolons break the flow when you are reading something the semicolon literally tells us this is not like writing fluent you know a language it is it is a kodesh so you want to get away from as much as possible things that look like code and more fluency and and semicolon breaks fluency so that's one of the reasons why it's nice to have languages that don't insist on semicolon that makes it really nice well the second thing is we can get to the point where we can drop a few other ceremonies and let ceremony it is the more fluent the code is so let's talk about how this would would help us so let's look at a class called car for a minute and I'm gonna write a method over here called the drive and let's go ahead and provide a distance it doesn't really matter what the value here is and I'm going to now go ahead and write this code and I'm going to simply you know print out let's say our driving right here but I want to go ahead and you know use this particular method so I can say car equal to car create an object of car and then of course I'm going to say car drive let's say 10 whatever that 10 means and I'm gonna run this little code but but as you can see on line number eight that looks really you know kodesh but what if I want a bit of fluency in this code wouldn't it be nice to simply see a car drive 10 and drop the dart and drop the parentheses well that would be really nice because then we can we don't have to have those noises and and somebody who is you know not keen on programming or who's not a programmer can come in and start writing these Kansa configurations we can then take it and and run it in the code that would be really awesome what Carlene has a few limitations around it but at the same time it does offer some flexibilities so if I try to run this code obviously that doesn't work but that's because it kind of gives us a clue right there about something called infix so what you can do here is you can go to this function and you can mark it as an infix function well the minute you put in fix you're telling the compiler can be a little bit flexible about this so as a result the drive becomes an infix notation in this case so when I go ahead and run this code you can see it does say driving both both the times so you can drop the dart and the parentheses by creating methods that are in fix what's really cool about this is not only can you do this for your own methods you can also do for methods you add to other classes talking about which let's talk about extension methods that you can actually use which is pretty you know amazing feature for you to be able to extend existing classes or when would you want to do something like this I was working for application where we're dealing with a lot of insurance you know related data and one of the things we wanted to do in the application was we have insurance policies and insurance policies you know have durations they come into you know effect on a certain day they expire on a certain other day as we were working on the application what would be really cool as if we can take a particular date object given to us and we could say date dot is in effect and pass the insurance object to it now clearly you could take your insurance object and you could say is he's effective on and you could pass the data with nothing wrong with it but the factors we have a date object we want to be able to go back and forth for fluency so if you can take a date object and say date dark effective you know effective on and person insurance object to it wouldn't that be cool well the problem is though the date is not a class that we created the date belongs to the JDK so what do you do if you want to take a date object but you want to add your own domain specific methods on to it that would be really convenient isn't it but of course this does a feature that could be abuse you know oftentimes people complain that if you have a lot of extension methods you have no clue where it comes from so there is a certain amount of discipline that's needed when it comes to using extension methods but if we have their discipline if we follow a particular structure this can be really effective way to do this let's look at an example of an extension method just to get a feel for how we can actually use that so what I want to do here is to take the greet over here and let's go ahead and say this is hello and and what I want to do is start by printing the greet but maybe you saw a buddy of yours after a very long time and you see a buddy after a very long time you're not gonna whisper greet to them you're gonna shout greet to them so I want to express my excitement about seeing a buddy after a long time I would I call the shout method and and when I run this code of course unfortunately it doesn't work but personally I think they should really have a shout method because it's so exciting to shout at some point but but you can't you don't have to take no for an answer if you think shout is a method that a string should have you should have the right to add such a method so what I'm gonna do here is to go to this and say I'm gonna take a string class and I'm going to add a shout method to it and this method simply is gonna turn it on and call the to uppercase and and route it to that particular method and and now as a result if you notice over here when I run this code it takes the hello and prints all in uppercase now you look at this code and say you say wait wait wait did you just take the sacred Java dart you know Lang dart string and add a method to it absolutely at the last time I checked we live in a free country right so absolutely we can add methods to anything we want to add in this case we just add it to the shout method method to the string class so you can use extension methods like this so what is the benefit of this the benefit of this is you can start bending your classes even though it's a third party class you can start injecting methods into third party class to suit your own convenience and like I said a certain lot of discipline is still needed but that's true for almost everything we do in our field or discipline is absolutely needed and and if we can you know have the kind of discipline this can be really effective to do so that's basically what we did here is we took the string class and added a shout method and you can provide whatever implementation you want here so you don't have to really doubt you to uppercase you could you could you know it return something else completely from here as well like you just you know stub your toe or something you can do that as well so you can you can start returning whatever methods you want to return so how does this really work internally when it comes to the compiler well the way this works is this is a pretty interesting way that Carlene actually does this and the way that Carlene does this is unlike other languages coddling doesn't do bytecode injection and I'm thankful for that what they do instead is this is purely a syntactic sugar by the compiler the compiler literally makes the shout method as a method that takes an argument as a parameter of the type string so they rewire this as a call to the shout method and then past the greet to it and that's basically what they do here so as a result this was purely kept external to the bytecode itself and this is purely available through the through the static method they create solar leaders another thing you can also make use of to gain on fluency I'm a big fan of code that is less noisy I care a lot about clarity of code when I look into a file I always believe a good code invites the reader a bad code pushes them away so I want the code to invite me and say thanks for reading this I want to make it pleasant experience for you read it and and the less noise you have in the code the placenta tease to read it and and and I'm of the firm belief that more parentheses we have and more semicolons we have it really creates noise in the code so anything we can do to minimize that is a good thing so let's look at an example of that right here suppose we create a function called process and this takes a funk as a parameter here and that's going to take value of integer and it doesn't return anything so we'll say unit and I'm going to take an integer right next to it and and what I'm gonna do in this function is call the function given to me take the value n times two and just pass to it so what is the process method look like so I'm gonna go ahead and call this method some element given to me I want to just bring that element and then I'm gonna pass a value of two so what's the score I'm going to do the two is you know binding to N and I'm gonna take that value and over here if you will and then I'm going to pass that n times two is two times two is four but I'm passing the four in here to this lambda and I'm going to just print the value of four that's all I'm doing right now while this code is working this is a poor design from the fluency point of view if you notice over here look at this noise and the smell in this code you put a parenthesis and a curly and a comma if there's a way to reduce a lot of these things that can be really pleasant so what am I going to do just a small little feature if you just go back here and say this is an int comma and I'm gonna remove this function from here and just swap the two parameters as a result I'm gonna say do comma and I'm gonna rewrite it this way so at this point we didn't get a whole lot of benefit except that this leads to something really beneficial from the point of view of DSL and are our fluency and and that is notice in this process now not only did we take the number as the first argument and the lambda as the second but more important the lambda is the last parameter when a lambda is a last parameter it gets a special treatment kind of like how parents treat their last child in a very special way I know it because I was not one of them and the point really is that you can actually give a special treatment to it and that's the whole idea so what I can do here is rather than writing it this way I can simply say process right here and I passed the two but that last one can step outside of this and I can simply say print line II and I can write it this way so you saved a parenthesis well you kinda say the parenthesis in the end but more important the comma is not there and as a result that is a little less noisy at the beginning you may not realize the benefit of this but as time goes on every little thing you can share a way from the distraction and the clutter is a step in the right direction so this is one of the reasons why I like to have the lambdas at the last argument then you can just move them outside and you don't have to really put them inside the parentheses that becomes really fluent and useful to work with so that is one benefit you get out of the lambda is by keeping that as a last argument you can get a little bit more fluency in the code so that is the what in a1 approach you can gain from then comes along yet another feature and and this again is one of the features that I was just blown away but when I looked at it I really had trouble understanding it in the beginning so I struggled with a little bit and and what really made it easy for me is to relate to something else that I was already familiar with so I'm gonna take a detour and I'll come back and talk about it so I'm gonna talk about JavaScript for a few minutes well JavaScript is an extremely flexible language but javascript is a dynamically typed language we know that Kotlin is a statically typed language well the beauty of Carlin is it provides the power one of the powers that you have in JavaScript but at the same time giving us the ability to be fully statically typed and and that I think is pretty darn exciting so let's talk about JavaScript just for a minute before we talk about what caught wind from whites in this context so this is JavaScript and in JavaScript I'm gonna take a function called let's call it as greet and the greet function takes let's say a name as an argument and and what I'm gonna do here is simply say output let's go ahead and you know print out a name here if you will so all I'm doing here is printing the name and I'm gonna call greet and send Jane over here so when I you know call it what is it going to do it is going to print the value of this object so you can see that it printed Jane but I'm going to change this a little bit one of the cool features of you know JavaScript is when you when you look at language like Java and you know a lot of other languages you traditionally like methods that belong to classes JavaScript is special of course it's special for a lot of reasons but but javascript is special in one way you can just walk along and say hey look you function you look really nice I want to run you in the context of my class in other words you can take arbitrary functions and turn them into methods of your class I know that sounds really weird but you know that coming into JavaScript already but the point really is that it is really where you can just take an arbitrary function and turn into running it has a method of your class so how do we do that so notice what I'm gonna do here I'm gonna say this dart to uppercase so all of a sudden I am using something called this right in the middle of this but what in the world is this of course when I run this that's going to say undefined but what does that really mean where is it coming from and if I call this as a method it's gonna blow up but what is this really well this is the beauty of JavaScript you can go to this method you can do a call on that method and you can pass for example hello and when I run this code you can see it says hello Jane so this is a feature of JavaScript where you can take an arbitrary object but you can attach a context object to that particular function when you execute it knowing this really helped me to understand how Cartland does things because you can do this in Cartland except rather than being an arbitrary function you can pretty much hijack a particular lambda and say I want to run that lambda in the context of my object which is a really powerful way of doing things and so let's take a look at how that works in the context of Kotlin so what I want to do here is to show how we can use what's called an implicit receiver and notice when I that did the call to the call method I pass the two arguments to that method that really is helpful to think about Cartland does it stuff so let's take a look at an example here I want to create a function called call and that takes agreed which is a function and this takes the name which is a string and I'm gonna not return anything from it let's take baby steps go to words that so I'm gonna call greet and Paris Jane to it as you would expect right here and I'm gonna call the call method right here but what am I gonna pass to the call method I'm gonna just go ahead and print and I'm getting a name as an argument as you can see the string is coming in and that's being passed in here as well so I'm gonna take the name as an argument that I get and all I'm gonna do here is simply print out the name right in here in the call so at this point all I did was I'm just writing that particular you know method where I'm passing a great method to it and lambda rather and I'm gonna ask you to print that value but but I want to really send a context object to it how do I do that well clearly you could have passed two arguments to this function but remember in the in the case of the greet and the JavaScript I didn't pass two objects I passed one parameter but the other one was a context object well so what I can do is I can take this lambda and I can tell Cartland hey this is not just a normal lambda but I want to take this arbitrary lambda that's being passed to me but I want to run this lambda in the context of another object and the context object you can specify right in front of the lambda how do you read this stuff well we dis first as a lambda well that's a lambda but that lambda has a context object associated with it that's a very easy way to think about it so this lambda is just a block of code but when that lambda executes it's going to run in the context of this object how do we pass the context object I can follow what JavaScript did a few minutes ago and I can simply say over here hello like this and of course when I come in here I can say this right here and then of course if I wanted to do uppercase just like I did in the case of JavaScript I can call that method to uppercase or writing here if I if I if I to still and so when they run this code you can see that that this is bound to that object that I just passed in but of course you don't have to do it this way but knowing that you can do this this way really helped it for me because I can relate to what's going on in this context but in the case of Cartland what you can actually do is you can say hello dart greet and then you can pass Jane to it in other words you can say I want to just run that object in the context of this object but as you saw both the pieces of code actually worked either you can pass the context object as a parameter to wit or you can use the context object on the left side and then do a dart and and saying that I want to run that lambda like it's a method of my object so this gives you a bit of a flexibility in fact the beauty of this is imagine writing this as a generic type and you say this is a pea rather than a string then your lambda could be running on as a context object of several other objects not just the alone so that would type safety which is pretty phenomenal in terms of your ability to run this so in other words lambdas can have a context object so what does the tell us it tells us not only can you pass parameters to lambdas but you can also have a context object and remember one of the key features of a dsl is that you have a context so as a result you can start writing your DSL which can run with the particular context behind the scenes that can be very effective one other quick thing to mention here is this and it can come in really handy so for example over here I'm not suggesting you do this but you can specify it over here and as a result you can you say it instead of using object name I would feel insulted if anybody called me it so that's not the intent here but the point really is that you can actually take the parameter if there's one parameter you could use this so as a result sorry you can use it so this and it can become per parameters in the context object and you can use them pretty effectively in your code as well so that becomes another a point of fluency okay that's all good we talked about a number of different things that makes Carlene really exciting let's build a few little DSL and play with it how about doing something like this two days ago and two days from now that would be really nice Lewin C to ad isn't it so I'm gonna go ahead and say two days ago that is that awesome or what so I'm gonna run it but sadly that doesn't work so what am I going to do I want to make that work but we gotta take baby steps towards it let's take one step at a time you can create enums if you want to but I'm going to be lazy here so I'm gonna just define a go as I go so that's a little first step but then what am I gonna do I want to take this too so what in the world is do we know to is an integer so what I'm gonna do is to say int dark and I'm gonna say days and we're going to inject a method into the integer and simply say that days is a method and I'm gonna say it tens over here and this is gonna be just a string again like I said you could use the enum for this but I'm gonna be a little lazy right now all I'm gonna do is just say called here for a minute and just see if that actually works it doesn't what's the problem the problem is you could have written it this way you know with all the parentheses in the dart but you know that this will not make you new friends you really want to make it more fluent so what do you do you drop the parentheses you drop the dart but for that to work you're gonna say in fix right here and as a result you can say it says called over there so we were able to make that little piece of code to work but we can then go a little further and say when and we can say tens and in this case we can say if this is a go what do I want to do well if it's a go what I want to do here is I want to say print and let's go ahead and just import right now Java dot time dart and in this case we could simply say local daytime and then and now and we could say - what is that - days and this and this is the context object that's being passed in dot too long because I think that the - days is requiring a long so I can provide that implementation as you can see and we can then come down and call that method so so as a result we are able to do that particular DSL implementation so we can just call the to long and execute it otherwise I'm gonna simply just put a little question mark for now so let's see if that actually works so when I execute it this is going to be Oh dot now of course so let's go ahead and make that a method call so execute this little code and that says third today being the fifth that's two days ago so you can see that's actually working similarly you could go ahead and add one more we could say from now and and a game in this case notice how I chose an underscore this is what I was talking about earlier you have to kind of play by the rules of the language the language wouldn't all of you spaces and you're thinking what can I do to really make it a little bit more fluent and you can figure out ways to do this so in this case what I want to do is to provide a from now and and of course you can say this is from now and in this we could go ahead and just copy and paste this for a minute and we can then say this is going to be providing not a minus but a plus number of days so you could try this too and we could say our days from now and you can try to execute that code and hopefully that shows you two days from now which is the seventh as you can see so that gives you an idea about how you can write an infix function and inject the days into the integer so this gives you an ability to write some kind of these kinds of fluency in your code so that can be something you could try to do to get that kind of behavior let's push this a little bit further we all love meetings isn't it in fact we often have meetings about having meetings so why not talk about meetings so we can say plan let's say planning a meeting and then I will say starts at when does it start well it starts at 3:15 you know that's when the planning meeting is starting well will this actually work well okay we knows already a few things to make something like this work but what about this one right here we could try a few things if you look at this : I want you to just bend that : like that so you can just kind of turn that around and and what is that really well it turns out this actually is something meaningful in cotton this is where you can play with the language just a little bit so we'll come back to this in just a little bit I'll just save that away let's go ahead and print 3.15 what in the world is that and you can see that okay that was very helpful it's a 3d : : 15 but I want to ask for the question you know what is the class of a dart class and ask for what that class really is and we can find out what what the class is let's say java class and ask for the information about the class itself and it says it's an inter Ange so we could bend this a little bit and say oh that's a range object maybe I can leverage that to do some work with it let's grab our little code right now back in here so how do I make something like this work well obviously that won't work at the moment so we'll take baby steps so let's comment that out let's go back to this and you know we can put a dot over here so we'll start with a little baby steps so I'm going to take the string and I'm going to provide a meeping method on the string let's start with that first what does this really return it's gonna return a meeting object so let's try to do that I'm gonna return a meeting object from it and this is going to be a class called a meeting so let's start with that a little bit and and what is the meeting class really take it takes a name of the meeting we'll pass it as a string if you will so so now that we have that we will return a meeting and pass the current object to it so all that it's going to do is return the meeting object when that code is executed so we can start with baby steps but that requires a lambda isn't it it says too many arguments fair enough so how do I work with that well now I can say this is gonna take a block of code but what does the block of code going to do that's taking nothing right now and it's returning nothing right now and that's a block I'm gonna pass to that particular function so when I execute that code it actually executed with no errors in fact let's make sure it is okay for now and then we can come back and you know modify this and make this a little bit better as we go it says okay so we cannot cut to that little part but I want to drop the space we know exactly how to do that alrighty so to make this work I'm gonna go ahead and say this is in fix and as a result it's not going to require that one so that kind of worked a little bit what is the next thing I'm gonna do oh I need to call the start but wait a minute what in the word is start I don't have any start defined already we could write this as a global method but that doesn't really seem right hmm I need to do something to make this work this is where you need to go get a cup of coffee and think about this a little bit more and then you realize aha this is this dart start after all and we don't need to put this in front of variables so if somehow start can be a variable in the meeting I can pull that and use it but wait a minute I want to run this block of code in the context of meeting how do I do that well for that I could simply say meeting Dart and we could run that in the context of the meeting well then I can come here and say start is equal to this and I can provide a function called add right here and what does that take it takes a time which is an inter Ange object and and now I can simply say you know dollar name if you will starts at and I can print out the time when it's going to start let's see if that's gonna take us anywhere so what I did was I created a meeting object and then I said to myself that meeting is a function that is going to fire up this particular call right in here and then of course when that comes through all we are gonna do is to take this context object start and we're gonna call the add method of course you know already for this to word I'm gonna make this an in fix method and that calls the add and passes the date/time to it and so as a result we can pass that to that particular function and see how that actually works where is the name coming from the name is coming from here so we can run this code now and see if that works and at this point we are calling the act method and this is supposed to come and tell us that the meeting is starting at their particular time so let's go ahead and fire this up and see what happens so so the start is going to be the current object and we are calling the act on it I don't see this running right now so we'll see what I did wrong anybody sees the error so so this is going to run with this particular method in that context and of course when it comes in here it should execute that particular method I'm not sure exactly why it doesn't run but we'll try to debug this in just a second otherwise we'll move on and see where it takes us so so all I'm gonna do just to make sure that I'm going to go ahead and print it out here let's see if that part is working so far so I'm calling oh of course of course of course venket is sleeping at the wheel I need to call the block isn't it that would be a really nice idea so what I'm gonna do here is I'm going to execute the block of code that's what I want to really do so once we get the meeting we can say meeting over here dot block and execute the block of code in that context and you can see at this point we're gonna create an object of the meeting that we are interested in creating and then of course I don't need to return anything from here at this point so so we can simply say fire that block of code in the context of that meeting and execute it so we can definitely do that so let's see what it's kind of complaining about no value passed as a parameter to name of course the name of the meeting I should pass this here when I create the meeting object so this becomes the this because that's a context object isn't it so let's see if that actually gets us anywhere and there you go so the planning you know a meeting if you want to put the word meeting so planning meeting starts at 3:15 and you can of course separate the darts and you can put a colon on the output you can do all those good stuff if you want to do so that's that's an example of how you can make that a little bit fluent I'm gonna show you one final example to wrap this up what if we can extend this kind of fluency a little bit more so for that I'm going to create a little robot and do the operation like this I'm just gonna copy this over here and I'm going to replace this part I want this to execute how do we make this work obviously that doesn't work right now but what are the tricks I can do to make that part again let's take baby steps towards it so let's go ahead and comment this out let's start with the operate so fun operate and what is the stake we clearly know what it takes it takes a lambda a block of code so we will go ahead and say a block and and right now this block takes nothing and returns nothing so that's a good start so what do I want to do call this method operate we'll just say called over here so we can get that little part working to pass that into the call so that that works but what I want to do is to say it done where does this work this is going to be on a robot so it's a class robot and and within this I'm gonna say left is equal to left again you could create these as items if you want to do right is equal to right and I'm gonna say fast is equal to just a fast so we'll just start with this now look at this first liner for a minute so it says it turns left what in the world is it well it is gonna be the parameter that you receive in here isn't it so whatever that parameter is we don't care to give a name for it so what that tells us is you can call the block and you can pass or about to it and that becomes the it well that's good so far and and just for a minute let's put a left as a string right in here and as a result turns is a method that we want on the robot because it now is a robot being passed in left is a string but I need a turns method so what am I gonna do fun and I'm gonna say turns and in this case direction and we'll say string for now and then I'm going to simply go ahead and print out right in here will simply say are turns and we'll put the direction right in there so so when I run with this code of course I need to mark it as in fixes ended so we'll go ahead and say in fix on this one again and when I run this little code what is what is that going to do are too many arguments to the constructor so this requires a robot as a parameter so let's go ahead and run that through now and you can say turns left but then I want to provide the next one it becomes turns right after that oh wait it doesn't know what a right is well don't worry about it right now we'll come back do it and then what I'm going to do is provide the next method it runs fast again I'll put a string on the fast for a minute so it requires another method so we'll go ahead and say fun runs and this is going to be speed which is going to be a string and all I'm gonna do right now is simply say something along the lines of print and we will say you know runs and we would say speed so so so far so good we got almost where we wanted to but one of the other things I wanted to really emphasize doing this is I like to kind of experiment and grow the code I don't try to shoot for a big distance because a big jump usually is a big fail so just experiment with it and see how you can really get to it to be a little bit more fluent but almost there but what about this string the string is not really that Pleasant what can I do about it there are a couple of things you can do you can provide a completely different context object if you wanted to it doesn't have to be here and it could be a completely different object for example I could say for instance directions are our we could say properties for like a better word and and the properties could be even could be an object if you world right so you can then make that a context object I'm gonna not gonna do that right now but you can definitely go towards that so it doesn't have to be associated with the same object it could be with something else if you really want to do but for now I define those in the robot so what am I going to do notice I go back here and say robot dart and I'm gonna run that in the context of a robot so then I can simply say robot is equal to and we could simply create an object of robot like I said if it's a different context object use that as a context object and then you can save about dart and you can just pass that object as a context object right here and as a result that can become the context object to run under so what is the benefit of doing this I can drop these now as you can see right in here and I can simply say this is going to be the left right and fast but where does this come from well if you don't say what it is it's going to struggle but we know one thing though when you mentioned properties either they are lexically scoped are they come from the context object so you have to have a eyes to read this when you look at it you say ah that's a dis dot right and I know that this is the context object I'm gonna run it from and as a result it pulls that from there as you can see and you're able to write code with the kind of fluency with that so that gives you an ability to bend the rules a little bit but like I said if you really want a completely different context object you can do context which could be a property or whatever and then you could call it in the context object rather than the report and then that's perfectly fine as well so you can have property separate from the object and that gives you the flexibility to run that in the particular context and you can certainly do that as well so hopefully that gives you an idea about how we can bend some of these rules so summarize what we talked about we talked about how we can you know internal versus external DSL internal DSL to expect fluency from the language you have to work within the constraints of the language you are working with but if you know how to push the boundaries of the language that becomes really easy and then we looked at why Catalan is really a good language for that we looked at a number of features in Cartland that are very favorable to creating DSL and then we applied some of these ideas most notably you saw how in fix plays a very important role we also saw how the context implicit receiver plays a very vital role as well if you want to download the code examples I showed you here they are available for you to download at the link that I've placed over there hope that was useful thank you [Applause]
Info
Channel: JetBrainsTV
Views: 16,027
Rating: 4.9245281 out of 5
Keywords: Venkat Subramaniam, JetBrains, KotlinConf, Kotlin, KotlinConf18, KotlinConf 2018, programmers, DSL, domain specific languages, programming language
Id: JzTeAM8N1-o
Channel Id: undefined
Length: 46min 20sec (2780 seconds)
Published: Mon Oct 15 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.