Functional Programming with Kotlin • Hadi Hariri • GOTO 2018

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

FYI, here's the talk Abstract

In this talk we'll explain the basics of functional programming, where it fits in with the Object Orientation paradigm and how we can use functional programming in our every day work. We’ll cover important concepts functional programming such as: Lambdas, Higher Order Functions, Partial Functions, Monads and more, and see how we can apply these in a series of functional patterns to cut down our codebase and at the same time make sure we keep it maintainable.

👍︎︎ 4 👤︎︎ u/goto-con 📅︎︎ May 03 2019 🗫︎ replies
Captions
[Music] welcome to this talk on functional programming in Kotlin how many of you know Carl in Nice how many of you have never seen it how many of you have never heard about it I'm near you in the wrong room ok does who who did Kotlin before May 17th 2007 teen right that was the day that Google announced that I about Scotland who heard of it after that announcement and not before yeah quite a few of you like that that just confirms that I wasted six years of my life just talking about katli thank you anyway I could've just waited and waited for them to say something so I'm gonna give you a brief introduction in in terms of functional programming with Kotlin what is there what there is not what you can use through third parties and yeah just give you enough so that you can maybe look into it a little bit more if you're interested like this isn't the session for you to actually learn something right I mean like seriously conference talks aren't about learning are they did I say that anyway I always like to start with why right so I'll start with why over here take a look at this code don't judge me it was it's only demo code which is like all the code I write and tell me as soon as you know what it does raise your hands and don't shout don't like say oh I know what it does I'll tell you just just raise your hands and tell me you know what it does and if you were in my workshop yesterday don't raise your hand because that would be unfair anyone know we got one two three okay thank you put your hands down down I'm good take a look at this raise your hands when you know what it does right so yeah we get the hands raising much quicker so when people say why functional programming well because it's hip right it's it's the hipster thing to do nowadays but also because it's potentially easier for us to understand right the idea behind functional programming is to remove certain things and add certain things that make our code a little bit more understandable and comprehensible so if you look at these two pieces of code it does something also is exactly the same as it does something sure that the return type might be different but the principle of what it does is exactly the same and if you look take a look at this code what you're looking at is a whole bunch of code where in your head you have to have this entire mental model of what exactly is going on right I have to have a little storage area over here of my cache to cache my variables to figure out what is going on with those variables increment them as they go along figure out what the operations are doing what each operation is doing whether it's a statement whether it's an expression whether it's what is returning store that and try and basically become a compiler right and become the application to interpret this whereas with this one it's essentially the same thing the only difference is that I've abstracted some of that functionality into some other thing which is called a function right and I've given those functions good names so everybody kind of understands what the concept of group-by means even if they do not understand the syntax of Kotlin or they do not understand the concept of what the actual function group is but they pretty much know what it means right and pair everyone knows what pair does and everyone knows what not you don't maybe not know what map does but generally as soon as you understand what these functions do this becomes much easier to follow and that is one of the goals of functional programming I mean every person have their has their own goal functional programming but the benefits that I found in functional programming are about essentially raising the level of abstraction making those abstractions essentially functions and then using that to write more expressive and concise code and there's an important factor here because concise doesn't always lead to comprehensible right we can't have concise code take one of those esoteric languages on on Wikipedia that starts with a b and finishes with a k and you know that that is very condensed but it's not understandable so this is about still keeping code that is comprehensible right and that's where i think the the what you would call the you know because often people say like if i'm doing functional programming where do I start where do I end what is the you know the the the ultimate epiphany of functional programming where is it it's just the journey that each time you start to understand more and more and then when you understand these things more and more that's where you're comfortable and that's where you can stay ok so now in terms of Kotlin what we're gonna do is kind of show some of the functional aspects of Colin because Colin as you know is if you're not familiar with Colin Colin is an object-oriented programming language with functional constructs what does that mean that means it's also a functional language what is a functional language well there's many definitions it depends who you ask if you ask a Haskell programmer generally they will say it's only Haskell if you ask a f-sharp programmer they'll say it's only F sharp generally the the agreed sentiment is that any language that gives support to functions as first-class citizens can be considered a functional language so what is first-class citizens that the ability that I can essentially have functions that I can pass around as parameters which give way to higher-order functions the ability to maybe have some sort of immutability in terms of state management etc this function is called in a functional language by far it is of course otherwise what what am I doing here like what are you doing here right you know I'm not gonna give a talk on programming in calling functionally and use something like I don't know VB so it is why that account functional because in calling you have the ability to do certain things okay and but let's go through the basics in case you're not that familiar with Cortland over here so let me create a new file and not a scratch file it's over here and we'll do column file live me I love naming stuff okay so and what we're gonna see here is essentially some syntax for Kotla now calling object-oriented so I have a class customer there you go that's a class you've just declared a class in custom in Kotlin and I can create a function in Cortland as well that says do print message and I'll have a value that I'm passing in and then I can you know do whatever I want with that parameter okay so this is the basic of a function in in calling a function by default returns unit so if you do not specify unit it is assumed that it's returning unit unit is exactly the same as void except it's not void there you go that's my explanation there the difference is that unit is actually an object so if you're not familiar again object is in Cortland we can have classes and you can create instance of classes and then you can also have objects which are kind of like Java Script okay and please every time I say Java Script think about the good things of JavaScript I never make the comparison of JavaScript as in all the hell that JavaScript is okay so it's kind of like JavaScript in terms of an object now this actually means that's a call and returns something in fact you know if I do four if I do result prints message and passing some value and then I do a print line of result this is going to give me back a value which is actually unit right so you can see that it gives me back unit okay now in calling you can actually have a function indicates that a function never returns and you do that by saying that it turns nothing and when I say nothing I literally mean nothing so you write nothing and then that function never returns so you can see that this immediately says that this well in that case just yet that one doesn't work and here you can see that this is unreachable code right because by all accounts now the compiler interprets that that function is never going to return so you wonder why would I ever want to do that well for instance there's one function built into the standard library which is called to do implement this and if you go to do you can see that it essentially throws a not implemented error exception and it returns nothing okay so if anyone ever asks you what is the top-level object in Kotlin it's called any and they ask you what's the what's at the very bottom you say nothing and it won't you turn in the truth and if you don't know you just say nothing anyways well and yeah think you're right okay so in calling we try and be concise I mean you can see how concise a class is so I can also do for instance a fun sum if I write some X int y int I don't have to do something like this return X plus y I can do it much shorter as a single expression function and just return the value there type inference will now allow me to the type inference we'll know the return type based on the parameter types and I can just express every function essentially as a single expression function considering most of us now have 4k monitors we don't even have the limitation of 80 columns so you can have really really really long single expression functions okay now this is great but one of the things that I said around caught by the way that was a joke about the column so it's just I don't care if you don't laugh on my jokes but sometimes people are like did he really say something that's stupid yes I did so in in Carlin you know you couldn't consider it a functional language if we didn't have the ability to pass around functions which essentially leads to higher order functions so now I have a higher order function in Kotlin I can write higher order and then this one is going to take a a parameter and so I can say it's going to take a function and then I pass in the actual signature of the function so in this case I'll say that this function is an int and it takes an Internet int and returns an int right so essentially what this is saying is that this one is what this one is is essentially taking a function that takes two parameters of type integer and returns an integer okay by the way you can make this really cool instead of writing funk I can actually put lambda watch this I'll put is that cool or what like if you learn nothing else in this talk you know how to type lambdas now so that I'm not gonna tell you how to do it but you know that is possible no it's just with a live templates anyway so this is essentially the lambda which is passing in a high order function this is a high order function that is taking a parameter which is another function so now I can call this higher order and I can pass in the lambda anything that takes this signature to begin with I can pass in an existing function you dereference that you reference that in Kotlin by just using colon colon some right so here I am passing in the function sum because it matches our signature so I can pass this in if I want I can actually pass in a lambda and there I'm having a lambda that is being passed in right and what is saying to me is this this hint is essentially saying that you can do this in a more efficient way or a nicer way or more idiomatic way in Kotlin which is that if a last parameter to a function is another function I don't have to enclose it in the brackets right so I can just exclude this from the brackets and put it outside of the brackets right and the brackets would go here now given that I don't have any other parameters I can just drop those brackets as well because they're redundant okay in Collin if you have a single parameter lambda you can also put that on multiple lines so you can do something like that and if you have higher order functions which are just with single parameter so we have a hospital which just takes a single parameter what you can do is write Hospital of doing X is X plus y you can essentially just write it plus y okay so single parameter lambdas can be used with it name instead of being explicit this gives me the similar if you are familiar with groovy it's essentially the same thing right so these are how you declare higher-order functions and how you can essentially like you know have your own now in the in the language itself we don't have any higher-order functions as such we have all of that in the standard library which is a very small library that is part of the Kotlin that ships as run time so for instance if I do numbers equals 1 to 100 I have a whole bunch of new functions here right so for instance filter that I do filter 5 equals 0 and then on this I map that to 20 and then on this for instance I can do a for each and print line the actual result okay and now you get this nice little wonderful pipeline of functions and you can say look I'm doing functional programming ok and then in about 10 years we'll go to this and it'll be 60 lines and we'll wonder where we went wrong and we'll call it enterprise functional code ok but don't worry by that time something else will come around that we'll be promoting so what will always have a job in this life right we will always have a job right we are part of destroying things that we later come and fix ourselves ok so all of these are part of the standard library which it's all defined as extension functions so it's very small and available on a whole bunch of different things extension functions for those that are not familiar in in Kotlin you can have any class you can have any extend any type of new functionality so if I have a string class that I want to do a to camel case I can write to camel case and now basically this is implemented now what happens is that if I take any string I have the - camel case function right so this is now available to me anywhere where that it is defined in the package so these filter not that you see here they're all essentially extension functions on iterables generica timbrels so they're available pretty much everything okay this is kind of nice and also gives us a whole bunch of functionality inside the standard library around strings and fun and extension functions around all of the strings stuff so which is quite which is pretty decent also one thing that we're going to be using that you'll notice is well in in Kotlin you can actually call functions within fix notation so if I have an extension function that we can call is the same as that takes a parameter which is value that checks whether this equals value and this is the actual instance then I can write it like this you know me is same as me and also I can write it in infix notation okay I can write it like that ignore the error so it's same as right you so you add the in fix and then you can write it essentially the same way so this looks beautiful right this is no no okay now before diving more into into the ends of the functions let me just point out a couple of things first of all well anybody know what a lambda is I just showed one right there you go what's an anonymous function it's a lambda right so if you go to if you go to Wikipedia which is the source of truth and you say whiskey glass I love whiskey and you say you know lambda and you come down oh look I got it right lambda lambda computers in computer science say you got anyway in Wikipedia it says that lambda otherwise known as an anonymous function is blah blah blah now in all languages lambdas are the same as anonymous functions except in calling in column we actually have anonymous functions as well okay so if you want to do anonymous functions you can actually type something like like this over here so for instance if I have my higher order my higher order function right so instead of passing in a lambda like that I can pass in a fun X Y and then inside of that for example do return X plus y okay and why is that give me a and and unit and oh there you go okay so that is a different to a lambda in Kotlin so you have the concept of anonymous function then you have the concept of lambdas and this is important because lambdas have certain behaviors that it's important for you to to know so for instance if I have a function that is a container and I don't mean docker because there's way more containers and are nowadays and if I pass in for example a lambda over here that takes for instance an int and returns an int right and then I'll do something like you know numbers well numbers equals 1 to 100 and then I'll do numbers for each then if numbers is dividable by 0 right I'm going to do a return ok so if I if you take a look at that code and let's just we don't even need this so take a look at that code right that is a that is a lambda expression in in Kotlin which I'm passing to for each for each is a higher-order function and I say to you return and then I'm gonna write here for example print line hello right and then let's format this so I'm gonna write print line hello there okay now if I take a look if I'd say to you if I run that code container what is it gonna print on the screen what would you intuitively say well it's either going to print hello or nothing which one is it going to be hello hello hi it's me No so yes no it's actually not gonna print hello I never like why like this is completely counterintuitive right I'm in the forage I'm in a lambda I'm gonna do a return why is it not gonna print hello well the reason it's not going to be in hello is because in Kotlin when you return from a lambda you do a non-local return you do not do a local return so that means that this is going to return outside of the container function and like way why why is this well let's take a look at the implementation of for each take a look at the implementation for each it is looping over elements it's just a higher-order function however it's got this little thing over here called inline right now in line is a very fancy word for copy-paste so when you actually invoke this what's going to happen it's that it's going to copy and paste that code into the actual content the the calling code so it's not going to have like a call stack calling another function it's going to copy and paste that code so there is no outer function there is just one function which is container and when you do a return it's gonna come out of that container right what happens if I don't have an inline function so if I you know declare my own function over here or an inline function that doesn't am I for each that doesn't have inline then you cannot do a local return a non-local return if you write return here it's gonna give you an error now if you want to actually do a local return going back to the anonymous function instead of passing in a lambda you can then pass in an anonymous function as we saw here in this case return will actually perform what's called the local return so it will return to the container another way is if you don't want to do that you can use the labels which is essentially the ability to call return at the lambda so if this lambda cause for each then this if this function is called for each then this return would be at for each right if this function is called Jo then it will be returned at Jo okay no this is going to the question is if it's going to print hello four times no it's going to repeat it none do i oh they're mine now completely changes everything right anyway thank you bye so yes no that was meant to be outside of the the forage okay okay so now we'll stop up functions for a moment one other thing that we have in cotton is the ability to have immutability the ability to have immutability I'm just a poet today aren't I so if I have a data class for instance Val customer string and Val phone string this is essentially customer good customer Vega class good customer this is essentially creating a DTO for me with some two string equals hash code etc and call in and I've got two immutable properties Val means immutable that means that I cannot read and write and then I cannot write to them once I've initialized them right so you generally want to stay away from maintain changing state one of the premises of functional programming is stay away from state and with data classes for instance it's always good to have immutable properties because one of the things that you will remove by having immutable properties is the the concept of a data class not actually being valid right so let's say that you have a customer and you that customer has read and write properties at some point somebody writes to that customers updates a property you have to have some now validation logic inside our customer to validate whether it is still valid or not if you go by the the idea that I cannot create an invalid object make all of your properties read-only and you know that once that object is created it's always valid and you have to worry about that okay now this read only is great because I cannot do anything like changes so if I have N equals one I can't do any calls to I can't do that anymore because this is saying that it's it's a vowel it's read only I can't do any assignment and we have the same things in classes so if I do Val customer and initialize that value that property cannot be changed the problem is that there are situations where it can be so for instance here I have an object and I have a property called value which is Val this means that it's immutable this means that there is no way for me to be able to do something like this it is immutable okay this one is also immutable except it's not immutable right because this one is has a property with a custom getter which is possible in Kotlin but what it's doing in this case it's actually changing all the time because it's calling a function that the end result of that function is not a constant expression so in cases where you want to avoid these scenarios because like why like I can't reassign the value the value itself is immutable if you want to be explicit about that that is where you can use the Const in Kotlin and indicate that this essentially has to be a constant expression so it has to be initialized as a constant in order to be able to remain truly immutable in terms of inheritance in calling again we don't close in you know you property has a reference and that reference is another object that that has mutable properties there is no way actually to guarantee the immutability all the way down right but otherwise you you you know in this case you can do certain things to guarantee properties in terms of them being constants so let's now start to get into some of these things we can do with these data classes right so a lot of times when you write some code you say for example process entry and your rights I don't know some data that takes a string and then you say if data is not empty then then print line day or data print line data is good else and then we do our general error management right which is throw exception and we generally just throw exception like the top level I it's good enough it's fine it's fine everything is okay so now this is cool okay this is really really cool but this sucks in in what sense this sucks because if I look at that signature that signature is not guaranteeing it's lying to me right that signature saying this function returns a unit it's not true this function can potentially return something else it's the same as something like this if I write divide X int Y int right X divided by Y that's a lie they've been lying to us all our lives because that is not true because for 0 that is not going to return an integer yeah so this is what's called a partial function in that it doesn't work for all potential input values as opposed to a total function which for all potential values it will work so how can I be explicit about this right how can I say that for example process entry can actually throw an exception well we can use checked exceptions like in Java now I'm joking or you can just use Java know so generally some people tend to shy away from using exceptions for error management and they do something like result right so now they'll create a class called result and then in that results they might have for instance a property which is you know value string and then they'll have another property which is called error boolean right which then they'll say you know if the result is okay then I will return result good and boolean false and we can use default parameters here so default and otherwise I will return okay now that's nice isn't it and if you're generally in JavaScript error is represented as an e so that you can spend time figuring out if it's event or error so in this case I will return a result true now what's wrong with you every time there you go thank you so what's wrong with you now so that works except the problem here is that if I have two parameters or if I have three that need to be returned as a result now I have to figure out looking at that what exactly is is in the context of a valid result and what exactly is in the context of an invalid result which in this case we move away from this and we can say hey why don't we do something else why don't we just have a base class which is result and then I can have a class which is success that inherits from result and I have a class which is failure that inherits from result two and why can't I do this because in Kotlin by default everything is final so now I can do return success and here I can do result failure right and then the failure success is going to have a property which is value for instance of type string and failure is going to have a property of type message for example saying the actual error message okay so now I even get more information here so this is message okay so okay because you can make this nested class as well which is even nicer because now I can enclose it into a specific context okay so now I can have my result dot success and result of failure and now it gives me more contextual information about when is it a result when is it a failure now this is it's nice the problem is that now comes my friend and goes to a file that is not owned by the standard library and says Oh data class sometimes that also inherits from result right there you go and now if we go back to my thing over here I have just introduced a new class which potentially I don't know about right and now there's a third case what I'm generally showing you here is the concept of the algebraic data type which is essentially a type that can be of one type or another type now in Colleen as soon as you declare a class open anyone can inherit from it if you want to close our hierarchy what you can do is call it sealed right so instead of open you create it says sealed and what that means is that essentially only classes in this specific file are allowed to inherit from this so in that sense you do get some safety in that you will see all of the types so if we go back to live me you can see that down now this gives me an error saying that you can no longer inherit from sometimes okay now this is a pattern that is quite good because I can use this over and over again right instead of I can try and move away from exceptions and move towards this data classes which allow me to return different results based on success or failure the problem is that it's a lot of boilerplate code that I constantly have to write over and over again so how can I try and solve this problem well you can use for example one of multiple libraries one of them is called arrow anyone here heard of arrow right so arrow has this concept basically built in arrow is a is a library which is available it was a it was a excuse me it was a merge between two libraries one of them called category with a K another one called functionality yeah you guessed it was okay and they joined efforts and made a single library called arrow and they offer out-of-the-box certain additional functionality to make some of these things smoother so one of those things that they provide is the ability to have this kind of like this or that data class okay so in this case I have an either the either is a type that's available an arrow that says either something so the result of something is either the type on the left or the type on the right so in this case I can say that this function returns either are not applicable which in this case is just a simple object or a double okay then when I want to return the result I do either left and the actual result either right and the actual result so this starts to be nice because now I don't I've just cut down all of that boilerplate code that I wanted to write and I only specifically returned the actual type that I want to provide now this starts to provide me with some other things that we'll get into like for example you know is left is left it not only returns at the the actual ADT for me but it also returns additional functionality which then I can call and pass to other functions and kind of do this pipelining that we saw previously such as one of them four instances is left is left tells me if the value returned is is left or is it if is right exists will tell me whether the given a predicate it exists if the value is left and then from then on continue to do other types of executions so moving away from exceptions we get this kind of like return types that we can use back kind of like use to define how we want to return values but there are times for instance that I want to actually stick to the concept of exceptions and there's another type that is part of arrow as well which is called try which allows me to exactly do this right so in this case what try does is it essentially says that this signature this function can return either an exception or a string right so it's being explicit it is now moving away from lying to me right because if this was just a string then I know that this is going to just return a string but in this case it's saying no this I can actually fail so it's kind of like checked exceptions except you don't have to mess around with all of those checked exceptions so in this case I say return a try and the try if you know if it's if it's a valid URL then return the contents otherwise throw exception so now if I do get page with throw and I pass in some value and I run this this is not going to do anything because it's absolutely fine it's just return the contents I mean if I do a print line here it would return return the value of the contents but essentially it's absolutely fine but again we go back to this isn't only about introducing a type with nothing else it's introducing a type with more functionality one of those things is for example get or else right so get or else what this allows me to do is say ok get this value or else if you cannot get this value if an exception is thrown do something with it right so I can say print line and then you know error occurred right and what is this this is a lambda so since it's a lambda it's taking a parameter if we look at the parameter of get or elles is taking a throwable what is the throwable it's the exact throwable that we're throwing since it's a single parameter I can refer it to it as it I don't have to be explicit so if I run this and I pass in an M if I run this and I pass in an empty string then that is going to say error occurred and it's going to tell me the actual exception that has been thrown but it's not throwing the exception for me if I want to I could then throw that exception for whatever reason but it's allowing me to gracefully manage these situations okay so you can continue to use exceptions but you can do them in a more one would say you know a more subtle and clean away okay so one other thing that you're having caught in which you're all familiar with is nulls or not nulls so if I write a string and that string is nullable right and if I do if s is not null then print line something this I can do in shorthand by just doing something like all print line s dot length for instance this I can do in shorthand by using the safe operator so I can do safe right this is the same as doing an if essentially it's like if it's not null then do this right now this is built out of the box in Colleen it's the safe operator in many other languages such as for example Java you have option right where you can basically say if it's not null then do something but that concept of option doesn't have to exist only for the case of null the concept of option is more broader that exists for something having a value or not having a value otherwise also known as a maybe so for instance here I have a function that returns an option of string which essentially means is the value is it returning an actual value or is it returning empty empty can one day be mapped to null in the case of safe operator other times it can just be considered empty and then I can do things like well if it if the result is defined there is a value again it gives me not only this concept of the data class but a whole bunch of new functionality on this data class right so now I can say if the value is defined do something but what else can it do so for instance here here what I have is a function divide that now becomes total remember the initial function we had that was partial now this becomes total so in this case what I'm saying is divide two numbers option int and if it's greater than 0 then return the value you call that with a just you say empty just the value otherwise return empty and then in my when statement I can say when result is non print line this won't work otherwise print line result and T refers to the actual type the value that is returning ok so now I have this case where I can change between none and some but let's to continue on with this because this kind of pattern starts to become cumbersome right because if I'm starting to work with these option types and every single time that I have this option type I have to do if it is empty do this if it is not empty do that this starts to become cumbersome like here I'm taking an int imagine for instance that I wanted to take an option as an input what would I have to do I would have to come here and say if you know if we change this to option of int now I have to say if X is defined then do something with the result otherwise do something else and when you start to have all of these functions that start to take options and you start to change these it becomes quite cumbersome boilerplate code and of course this is already solved for you right because in in arrow you can you have the ability to have this built in which is essentially a map a map is a general concept that comes from functional programming which is called a functor which essentially knows how to work with a value apply a function to that value so what I do here is I have a function that's called squared option that takes an actual option and I say map that with inside values so map under the covers now knows that if it's not empty perform this predicate on that if it is empty then don't do anything right and again map gives me back the ability to start to do other types of chaining right so here I have map in this case I have triple option so I can pass in trouble option empty so now this is essentially not going to return anything because it's triple option on Mt it returns none right if I put in a value here for instance triple option of just three just three this if I got it wrong right it should return some 27 okay and then I can actually get the actual value from that and we can continue to build on this and take it further so for instance here we introduce another thing which is essentially flat map which is very again common in functional programming and flat map is the idea that now I'm not going to just return the value I'm going to return an option of that and operate on that and the end result of that flat map has to be an actual option that is returned this then allows me to take it to the next level which is something that you may have heard very common in functional programming which is called binds right and if you've ever heard of the table of the monad type or the type classed monad a monad has this function called bind which essentially allows me to do monadic comprehensions with this generally means take all of all of these different operations that are referring returning these types these monads all of these options try either these are examples of monads right so we've just seen monads without saying monad and combine these in operations so for instance here I can now start to do a sequence of operations that are independent that do not depend on each other and then combine these and get results and have all of the error handling done for me behind the scenes in the much nicer way okay so the either option binding try all of these are some of the things that are available in Aero if you are interested in it check out the library and start to play with that it does give you some nice things out of the box now one thing I want to also touch on briefly before we finish which is very functional in terms of Kotlin is some other things that you can do with functions in common okay so let me start with you're all familiar with the concept of a DSL right domain-specific language right which the explanation of a domain-specific language is a language that is specific to a certain domain there you go so hope I have for instance a class configuration that says for instance has a string port a string a host string and let's say it has a port information of type port and then I'm going to have a class port which has for instance a value and then is it is it is secure boolean right so these are VARs because I'm going to set now in calling there's multiple ways to initialize this right what you want to do is you wouldn't do like Val configuration configuration let's just set some default parameters here so we'll do that is that port is port and then here we'll say is false sorry false and int equals zero right so you could do configuration and then here do configuration and then you know set the sorry Val config configuration and then set host host and then set some value etc or you could do something like with C and then inside C now you get access to host and then you get access to port so inside here you would do with port and then inside here you would say for example you know value equals 90 and is secure equals true and then host I could put for example one two seven zero zero one right now this is nice the problem is that this is kind of like a little bit ugly because I've got this with over here right and what I want to do is like if this is called config for instance what I want to do is why can't I get rid of this and just do something like that right and kind of like create my own configuration DSL right just like JSON just like anything else like I've created a configuration file for configuring my ports but imagine that this could be some business logic or whatever like tax information I want to be able to have this ability to write this kind of code and have completion and have type checking and all of this for me can I do this in Kotlin well actually we can so what is this what is exactly that we're doing here this is essentially an object right config in this case is an object and what I'm trying to do if you look at the pattern I'm putting some lambdas so what I'm trying to do is invoke that object can I do that in Colleen you can I can have a class for example Q right and then I can come here and create a new class right by the way this is not this is actually true a friend of mine was doing a live talk one day there was two of them on stage and he was saying you know one of them is like typing the other one is doing speaking he says ah hey he's like Richard create a queue for me so what does Richard do he creates a queue called foo queue right and the other one is like saying right now we've got this flu queue and he says i Richard create a second queue for me what does it do it creates a fluke YouTube so that's why you should never name your stuff foo so if I have this foo I can now invoke it how can I invoke it you see I just hit alt enter that's how I invoke it so what is this doing let's call this fool basically what I want to do is create an operator in Kotlin which is called invoke as soon as I do that I can now invoke this object so if I can do it there let's do it here let's create an invocation now when I invoke we're not what parameter should I be passing in here so let's see what I need access to I need access to host and port what our host imports their properties of configuration right now what is a high order function in Kotlin it's a lambda right that takes a lambda what is an extension function it's a function can I pass extension functions to high order functions in college yes you can it's it's unique to call in the concept is called lambdas with receivers so I can pass in a lambda with receiver here which the type is actually an extension function to configuration right so this is an extension function to configuration given that it's an extension function to configuration it means that it has access to the properties of configuration which means that suddenly this is no longer read and I'll do the exact same operation here keeps giving the same thing so I'll do function what do I need access to here port right so I'll do port unit and then come down voila I have my dear so right so I've done DSL driven development I started out with what I wanted and I've driven in and out using alt-enter now I don't even need to know Colin so but the point is here of course I've just done a small DSL which is specific to a configuration setting now you might not go to this extension to do something for configuration but the idea here is that you can really embrace the ability of using courtland's functions and lambdas with receivers and the ability to invoke objects and create DSL for your specific parts of your application because I mean if you're doing for instance things like domain driven design right one of the key aspects of domain driven design is to have an ubiquitous language which is the same language you use in your code matches that of the business domain and now you can start to leverage that you know creating the sl's isn't only about creating HTML the new version of that which you don't need to it's called markdown ok anyway that's all the time we have for now I don't know if we have time ne for any questions if not I'm around a little bit afterwards anyway so one question so just a short question the last part why isn't that default is there some drawbacks of having that functionality what part is not default or having a DSL on your on your object why would you have to why do we have to implement those methods oh well I mean yes I mean first of all not everyone is going to want to have a DSL on their object right and that's a whole lot of added code that is gonna have to be generated in some sense second of all that technically would only be possible to do using some kind of like a pro post-processing like using capped for instance a call in-house right which you can analyze your codebase and based on that generate some DSL but again it's like I don't think it would be something that you want to have every single class have this ability to be honest with you okay thanks thank you [Applause] you you
Info
Channel: GOTO Conferences
Views: 30,995
Rating: 4.8451614 out of 5
Keywords: GOTO, GOTOcon, GOTO Conference, GOTO (Software Conference), Videos for Developers, Computer Science, GOTOams, GOTO Amsterdam, Kotlin, Hadi Hariri, functional programming, JetBrains
Id: eNe5Nokrjdg
Channel Id: undefined
Length: 51min 31sec (3091 seconds)
Published: Wed Jun 27 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.