Scala: Beyond the basics with Christopher Batey

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone hear me yeah well thanks for everyone for taking the time to come to the talk we're going to be talking about some of the more advanced language features or of Scala so maybe not advanced but ones that haven't made it into mainstream languages like C sharp or Java the theme of the talk is going to be trying to rely on the language or the compiler or the standard library rather than using thing other proprietary frameworks that perhaps use things like runtime reflection under the covers so my name is Chris Feb 84 light Bend which is the company one of the main backers of the scarlet programming language and one of the main contributors to the to the Scala compiler but I actually prepared this talk before joining so that is a a complete and complete coincidence and most of the examples that I come from come from building things like web apps and spark data pipelines and things rather than anything to eat satiric however since joining light Bend I've worked on this this this library and framework it's a curve it is a concurrency it's an actor based concurrency model as well as a distributed systems toolkit and that's definitely fed more content into this talk because Acker itself is written entirely in Scala so that's the language which I work in 95% at the time however it has a fully fledged Java API so every time I come to add a feature to occur or I'm reviewing a pull request for a feature inside akka whoever's done it needs to provide with this scarlet and a Java API which i think is quite interesting so I constantly get to see the differences between the two programming languages the different feature sets and what are the different idiomatic ways to use the the two two languages so the agenda for the talk is going to be I'm going to talk a little bit about programming language terminology to make sure I don't use any terms we're not familiar with for the rest of it I'm then going to go into the main motivation for the talk that one like the one that the whole talk was going to be about originally which is to use function composition partial application and currying instead of a traditional layered and hexagonal or ports an adapter start start style architecture I'm then gonna go into something which if you'd asked me five ten years ago working in Java would this be a useful feature for the mainstream I'd have said no but the way programming is going and the fact that more and more of our programs are going to be asynchronous and the fact that we're representing that asynchrony in the type system with things like completable futures in java and futures in Scala I think the ability to abstract over higher kind of types is something which will hopefully get into that the mainstream if you don't know what that is that's what the talks about so I will introduce that and so why I think it's going to be useful I'm going to end up on definitely the most controversial part I think of the Scala programming language and Zhun probably the talk is to talk about implicit so implicit sort of feature of Scala which if you've doubled slightly oh you've got a colleague at work you hate Scala I would bet they would say it's because of implicit Sand we're not going to use scarlet because of that but there isn't one implicit feature there are many I'll go through a couple today and if you want to discuss some of the other some of the other ones and their use cases and their pros and cons and just just grab me after as the talk goes along will be will be going through more and more advanced features so if the start you're like I know what that is from one that stuff that is the basics don't worry it's gonna get more advanced but I didn't want to leave anyone behind so programming languages who hear programs in Scala on a day to day basis okay you might get bored but know who's what languages are you programming in Java yep c-sharp a few Kotlin well fewer than I expected right so I think programming languages are fun I think learning new programming languages is fun and I think as you as you learn them you you're able to pick up programming languages more quickly especially if the programming languages are in the same paradigm and one of the biggest obstacles to programming in Scala is the fact that it is a new paradigm you know you can do pure functional programming in Scala and 10% of the old 5% of the ecosystem might do that and then the skill set from Haskell might be useful you can also write virtual Java with with the removing some of the warts but I don't think that is the essence of what's fun about programming in Scala I think it's better to treat it as that languages it was designed to be and that's a hybrid between functional and object orientation and some of the examples I'm going to show you today are using things that you would normally find in a functional programming language are for instance function composition current partial application where we're still going user even if restructuring our objects our our program in terms of classes and and objects so we're gonna start off with something that I think is the most fundamental part of a programming language and it's both distinguishing and learning the different semantics and syntax of a programming language so semantics of approp the semantics of a programming language are its behavior what the stuff you write actually means so is it expression based or is it statement based is immutability the default how do you do concurrency and parallelism these things are really important but they're also really easy to learn if you don't know Scala and I don't know Kotlin and we went for a coffee together we could teach each other semantics of a programming language very quickly you could tell me whether the control from can flow control flow structures or expressions or whether they're statements and I would leave that conversation knowing the language very well however syntax which is what we type I do we have curly braces or is it less space do we need semicolons that's the kind of thing which takes a long time to learn you have to type from this year that's your genius and you're able to memorize this stuff very quickly it takes a long time to learn and become very fluent in the syntax of a programming language and maybe that's not important but why are you still thinking about the syntax of a programming language it's very hard to actually concentrate on other on on it on the core semantics and the actual business functionality to try and you you're trying to develop and I certainly have this problem and I think we a lot of people have this problem that when we when we when we get into unfamiliar syntax from learning a new programming language I was seeing a different paradigm then we often confuse this unfamiliar syntax with complexity and we forget that we've been programming in C style language for 10 years and we and we're so used to that so there's one thing to take in mind I'm going to show you quite a lot of new syntax throughout this talk if you've not used if you've not you've done a lot of Scala and what I want you to do is not go whoo-hoo-hoo that looks horrible you know let's just try and take away the semantics in the behavior of the programming language so what is the most important thing about a new programming language when you're when you're going to learn it well I would say whether it's expression based or statement based so it's a question for the audience this is Java not Scala what evaluate - in Java and he say the value of X is 12 any guesses oh it doesn't it doesn't compile and this is the only bit of Java or Scala in this presentation that doesn't compile that the way I create my slides is is crating is it's scraped code from an actual project which you can take away and pulls it into HTML slides and the reason this doesn't compile in Java is it's a statement based language which means your control flow structures like ifs and whiles they don't evaluate to a value you have to do something side affecting inside the blocks otherwise you you may have well have not have written it so here's another bit of Java which does compile and if things are statement based then what it encourages is mutability because one of the fundamental side effects of programming is is Muta is mutating a mutating state now the only I think exception in the java programming language would be the ternary operator which does evaluate to something so you can assign the results of a ternary operator directly to it to a variable what about this does this compile well I've already told you really because I said there's only one bit of code that doesn't compile but this compiles in Java but if you were to use the should act variable any point in the rest of your code it would stop compiling because it would save you uninitialized and that's one of the interesting side effects of a program being statement based of a programming language being statement based so with about this this is scarless so what does this evaluate to in Scala let's say the value of X is 12 I'd hoped it would evaluate to true and the fundamental difference between Scala and Java as a programming language is the things like control flow structures in in Scala expression based which allows you to do things like this which seems like a very trivial thing but it means that like Scala libraries ants and most Scala code can default to things being immutable rather than mutable which I think fundamentally changes how you program in that language of course there some other syntactic differences for instance I could write it this way in Scala but that doesn't really matter maybe you really like curly braces and parentheses and things but you don't necessarily need them so much in Scala so the kind of takeaway knits quite a simple one really is that if your statement based you typically have to have side effects where if your expression based then your programs can evaluate to values and the if the purest form of this is your pure functional programming and things like haskell and parts of the Scarlet ecosystem where your entire program evaluates to a value and has no side effects I mean probably think why would you want to do that and I'm I'm not advocating that I'm just saying that if we make a large part of our program evaluate two values and work with things with work with immutability then I think we get an easier program to to read about so the other part of functional programming which I want to take into to Scala is referential transparency so again if all of your program just evaluates to a value then it's referentially transparent and what does that mean so imagine we've got a value that's X and the question marks is actually valid Scala syntax it type text to anything here type checks to the bottle that the type system and if we have a value Y which is derived from the value X and it's x times X what does it mean for this statement to be referentially transparent or more accurately what does it mean for this expression to be to be referentially transparent well it means that if I were to be able to substitute X the right hand side of X so these question marks whatever code I were to write there into the into the expression that creates Y then I'd end up with the same program so hopefully it's quite clear to see that if the value of x was four then this would be a referentially transparent program and there are many benefits to this I can you can substitute things you can reason about them you don't have to look at the implementations of functions if you know that referentially transparent but what about this is this referentially transparent well I would hope the answer is no because if we were to substitute this value of x into the button to the above expression then we'd end up with the thing printed twice rather than once and this seems like quite a trivial thing but this could be hitting a database this could be adding latency this could have the side effect that if the database was down for the second time then you know the function that your program would blow up rather than work so when you use the terms reference you transparent semantics syntax and all these things quite a lot but now let's jump directly into the one the main topics of the talk which is function composition so function what is functional programming well functional programming has many definitions but in reality kind just means composing your software out of functions and one of the fundamental techniques for doing that is function composition and function composition allows us to take different functions and stick them together to create our actual business software and there's some wonderful benefits to this is we can completely independently test our functions and they apart from the types that need to line up between them we don't need to worry that there are not couple like there would be if you're passing in dependency say say in two insane to an object the example I'm going to use is a basic HTTP request and whatever web framework you're using or web library and I'm assuming a lot of people here are doing HTTP things I'm gonna guess at the fundamental part of it is taking HTTP requests I'm putting them into HTTP responses if you haven't seen this before this dis syntax I'll this piece of functionality and Scala is called the type alias and the bit on the right of the type alias is just that syntax for saying it's a function from HTTP request to HTTP response type aliases are a really cool feature I think because they allow you to to give names to what could be quite complex complex things which makes your code more more readable so to do that we're going to need some some classes we're gonna have some data involved in this I haven't seen this before this is a case class this is our case crescents Carla is immutable by default it's a value object so it's equivalent of if you're using Lombok or immutables in Java or if you're using IntelliJ or Eclipse to define hashcode and equals which is based off the value of all of the fields of course this is just a syntax difference between Scala and Java you could create the exact same thing in Java or C sharp it would be a lot more of a books but you'd end up with the same functionality and normally I don't care too much about syntax but this is the one bit of syntax which I think it's extremely important in Scala because it allows me to define my entire domain model my entire set of data classes on a single page and that's what I would typically do in a project if I was using Scala or something like F sharp as a programming language whereas if we have to put them in separate files and there's lots of boilerplate it means I can't just look at my domain in in one file the next thing we're gonna see is a trait we're only going to use traits and scholar as interfaces in this talk so I'm guessing if you're taking things from the internet or things from the network at some point you're going to have to turn them into bytes or from HTTP requests and responses into some classes that we can program to so I'm going to guess they're just functions from customers to HTTP response and HTTP requests into people well quite used to this layered architecture in in our ecosystem so we often have things like controllers or call it whatever you like it's the thing which knows about the HTTP library you're using and you might be using some annotation based framework to do this but essentially the first thing you'll typically do is somehow turn it from an HTTP request into some kind of useful thing that you can program to we then probably pass it to some service some other code which is down down here which doesn't know about our HTTP framework and then finally when we get the final result we need to serialize it back and this is one way of structuring our application what does the application service look like well it doesn't really matter for this talk so I don't actually write on the application code but we can validate it we can decide whether we want this person as a customer maybe we do maybe we don't maybe we like them maybe we don't but at some point we might want to save it so we might interact with the database but because we want to keep our abstraction layers very separate we'd say okay that's kind of infrastructure I don't really want my like domain proper code to know about databases so I'll inject some kind of repository or introductory class and again that would be a trait who he is structured and applicate who has structures applications kind of this way but you separate HTTP database and core business logic and call between them that's most most people in the audience so this part of the talk is about doing it completely differently because what I would say is that way of structuring your code is kind of like do-it-yourself wiring so there are two things going on here in the code we've seen so far there's dependency injection so I'm when we pass our customer repository into our into some some service it's the first bit of wiring that we're doing ourselves but will often use some kind of di framework for that which is probably based on action the other bit of wiring we're doing is the interaction between the layers and it's quite common then to think all because I want to make sure that my you know business logic does eventually make the customer persistent I'll probably test it perhaps with the mocking library or somewhat some similar mechanism what I want to suggest is that we use some language features to avoid having to do this which might reduce the amount of testing we have to do and certainly will reduce the coupling between these layers because even if you pick a really good interface between these between these layers you're still passing in an implementation of it there's still the code is still coupled together it could obviously be worse in the language features we're going to use a function composition kering and partial application so to describe these I'm going to move away from the are the the web requests example go to something really simple like adding and multiplying numbers and then apply it back to that back to that the HTTP example so here's the most complex function I've written or certainly in the last five minutes it's caught its add it takes two integers and adds them together here's a specialized version of that function so I've taken a bit of a bit of code which I've written and I've created a more specialized and this is a way to basically partially apply a function in a language doesn't support curring and partial application and I've done it manually I've just said ads and I've hard code I've hard coded ten I could have another function called multiply which does the same and then I could partially I could partially apply that and hopefully you can see the bit at the bottom the other thing we can do is we can compose functions together to create new functionality so if you can't see the bottom there to realize it's it's a flat room then what I've done is I've created a new function it takes in an integer it passes it to add ten and then the output of that goes into multiplied by ten and just like the layered architecture which explicitly calls from layer to layer I'd say this is again doing the wiring of functional composition myself so how could I do that in Scala well first let's do it the same way so I've got an odd function I've got an add ten function the syntax is slightly different but fundamentally this is the same code the bit of functionality which you've got in scarlet which you don't have in some other language is the fact that you can define courage functions a curried function is one let each parameter is separate so you can pass one parameter in and then what you get back is a function with one fewer parameters and in Scala you have to be explicit about it in certain languages you don't and the advantage of that is I don't need to pass in all of the parameters so what I can do is I can take this current function here and I can Cris call add add adds I can call it and pass in one of the parameters and I guess the question to think about is what type is that I've assigned it to a value what type do you think that is it's a function from integer to integer because we've just partially applied it now because Scala has this weird it either things aren't curried by default you can just take the top one and call dot card on it so that would be the equivalent code so let's just see that if there the the original example altogether so we have two current functions add and multiply and then if we wanted to combine these by partially applying them it's by specializing them and then sticking them together we can do it in one line in Scala so we can say we're going to do add 10 then we're going to compose multiply by 10 and that's the equivalent code the only difference is we've used two built-in bit of functionality in Scala the first is part is the curried function which allows us to partially apply and the other is the compose so compose goes from right to left which works well in maths but sometimes when I'm defining business functionality this way it works better the other way so Scala has two functions for doing functional composition it's a mouthful one is a compose which goes from right to left and one is unde n which goes from left to right so these two pieces of functionality are the same thing now these two terms curring a partial application that can we can very easily be confused because that the Verret they're very intertwined so just to make sure it's clear curring is the is that is is the piece of functionality which allows us to define functions which take multiple parameter lists and the pure version of it is that each parameter list just takes one parameter partial application is making use of that curring so that we can we can specialize our functions and create new functions from existing ones by only passing in a subset of the and function composition is gluing two functions together so that a simple example would be if you have a function from string to int and inter bananas and you want to do you want to compose these together first the types have to line up so the output of F has to be the input of G and we can we can write G compose F or F and then G now I'm guessing not many people work in the domain of turning strings into bananas so let's go back to something a bit more realistic which is this so this was the original code this hasn't changed from before it stole it's all the same code our goal is to build a function from HTTP request to HTTP response without doing any explicit wiring and calling and calling the things calling between layers explicitly just to remind you what the application service looks like it looks a bit like this so the end goal is to end up with a function from HTTP request to HTTP response because that's what we do most of the time if we just do HTTP and G RPC and and back in that's like that and if we think about D serialization right that really is just a function from HTTP request to some object which has been validated and you care about so I'm going to say that's we're going to term HTTP requests into into people into person now we then need to decide whether we want to turn this person into a customer and I would say rather than all that trait and class stuff that's really just a function from person to customer saving a customer so we're talking about interacting with a database that could be a function from customer to void or unit in the scholar or it could be a function from customer to customer if it's augmented somehow say with some kind of some kind of ID and then the final step is obviously to go back to something our web a web layer our web library understand so that would be a custom function from customer to HTTP response so can anyone kind of imagine now what our program will look like rather than the traits and the layers and the classes well it's just one big set of function composition and this is perfect this is compiling Scala code I haven't implemented the functions but we're not not going to worry about that but right now the function which I can give to my web framework now it could be class and method based but there's nothing stopping me from constructing micro this way is ID serialize the person I create the customer and then I save the customer and i serialize it and this type check stewart to a web request and the thing i really like about this i think this works really well for things like request response it works really well for like data pipelines I've written spark code this way is that each of the functions are completely independent you can test them without mocking and passing them in to be passing things in to each other the only dependency between them is that the types have to line up so I think this is like really good for a bit for building like decoupled code so I guess the question is are we done is this gonna work if we're gonna be able to build our applications this way well if I look back at the function that I look at this this saved customer who here has written a function which saves something to a database without something like a database connection that's a I think I've just made I've made them too idealistic so the next step is how do we deal with things like database connections and HTTP client libraries and all the things we actually need to make useful code work and that's where currying and partial application is going to work because function composition in reality is not going to work for us in these in real life applications unless we can massage our functions to make the types line up so my assumption throughout the rest of the talk I don't know what database library people use but there's going to be some object which is which is that which is the database connection and if I'm realistically going to write a function which saves something to a database I'm going to assume that function requires one of these so we'll talk about different ways to get that in there so if you haven't seen Scala objects they're just a way of defining functions everything is static you can't instantiate them it's a way of grouping like-minded functions so my safe customer function is now going to be a curried function and its first parameter list is going to be a database connection its second one is going to be a customer and it's going to return the saved customer so if we want this to work with our lovely idealistic web request which goes from HTTP request to HTTP response all we need to do is partially apply this function so in the bootstrap portion of our application inside your main method or however your web framework like starts an application what we do is we create add connection fools you know these kind of things we can partially apply the functions and then we can we can compose our requests and our logic and this definitely isn't pure functional programming someone would hit me with a stick if I even suggested it words that it's definitely not referentially transparent now but we're still using language techniques rather that rather than explicitly passing things between each of them and because this type checks to customer to customer we can then use this code again so that's one way of doing it but who here writes one function which interacts with the database normally you've got lots right you're saving lots of things you're retrieving things you're updating things so that's where classes in scale have become very useful so one way of thinking about a class if you're not seeing this syntax its exam as having a constructor in Java or having a set of fight and having a set of private final fields it's just it's like slightly less syntax to to consume but another way of thinking about a class in Scala is a group of curried functions where the first parameter list is the constructor and the second parameter list is whatever happens to be on the function on them on the methods it just happens we've got six methods that interact with the database all of them need a database connection and I don't want to type database connection parameter list in front of them all so when I instantiate this class I can think about this of partially applying all of these group of functions now I've only got one but imagine you had you had many and then when I need to compose my application I can pull off a method from an a class from an object and I can still type check it from customer to customer except it's going to be using that shared database connection I find this again a useful way to structure applications another way of doing it and the final part of this talk is going to be talking about implicit but another feature which Scala has here is the ability for the final parameter list to be implicit and what that means in Scala is that the compiler itself will look in the current scope for something which type checks to that parameter list in this case a database connection and it will pass it in for you if there's more than one in scope it will compiler it look like which one should which one should I pass in and this is definitely a controversial way to do things some people like it some people don't often the gateway to Scala is doing spark and spark uses this a lot you've never you don't explicitly pass around the spark context the equivalent of your you know your database connection in a spark application when using Scala but you do when you're using it from Java inside a cure we use this very sparingly just inside inside passing around things to allow us to materialize their streams and things but for this to compile if we still want to get back to a function from customer to customer when we write this when we do this when we assign it to a variable of type customer to customer the only way this will compile if there's something if this is in scope so there's a database connection and the only difference for when we've defined it before is it has the word implicit before so implicit in Scala are quite explicit they don't it doesn't instantiate things it's not like a DI framework which is going to look at the class have a look and instantiate it for your using reflection this would have to be valid at compile time so that is the end of the section on this topic but not the end of the example we're going to keep expanding that example as we go through the rest of the talk so the kind of the techniques which we've gone through a function composition occurring and partial application and come to think of it I don't actually think these are the main benefits I think the main benefit is the fact that the functions are completely separate and testable and the fact that there are decoupled so the next thing is higher kind of types this is a feature which may become mainstream in programming languages in the next five years or so hope so types we all like types we're all a DevOps conference I very soon there's some JavaScript and closure and things here but we like static types I like static types we've got different types of types right we've got types like string and int in person and customer these are real proper concrete types that we can like hold and lick or something and then we've got these other type of types in Java and c-sharp and Scala the difference between them is these aren't really proper types they take something a tea like a string or an INT and then they become a proper type they're often called generics or parametric polymorphism and another way of thinking of these is that they're a function which goes that takes in a type and gives you a real type like list of string rather than list of T something you don't know of course in Java for backward compatibility reasons list is a real type but you get compiler warnings if you if you use it that way as of Java 1/5 we can write these types of types with more than one parameter so Matt for instance takes two of them before it comes a real type and this is obviously not a feature which is unique to Scala this is obviously in Java and c-sharp and other languages the feature which is unique to scholar and other more powerful programming languages somewhat unique is being able to abstract over them so we're used to creating abstract code that's based on generics were like putting T's and angle brackets and square brackets if you're in Scala that's a very common thing but when you moved from Java 1/4 to Java 1/5 I bet you or I certainly had a little problem with all that new syntax that was there because we're very used to now this I'd say most developers like see that and don't even bat an eyelid but imagine if you could abstract over the other side on a name for things like lists and sets and future and all these things which take a type parameter in most literature it's called a type constructor because it constructs a proper type now this is weird to me tea isn't a real type here by the way it's it's it's representing something like a type variable so we're say we're going to write a function which tapes anything that takes one type parameter that's an integer that's a little bit weird isn't it whereas we could actually abstract over both and that's by far a common and I find that very weird when I first came across this feature you end up with very abstract code so before we dive into what the syntax is like in Scala I want to talk about some motivation for learning about this feature so the world is going asynchronous I think we'd agree especially as we're building services which tend to call out to other services because someone told you to do microservices but they definitely probably talked to queuing systems and databases and one of the scalability bottlenecks that most caught that a lot of applications have is the fact that it's a threat per request not a threat in Java and the JVM is an operating system thread which is a an expensive resource so web service these days so I can hate gtp very like represents a HD a rep request like this and you've got reactive spring and this is very common these days a future here do not think of the Java 1.5 future think of the Java 8 completable future and they're very very similar in Scala and Java so instead of representing our HTTP requests every one that goes from HTTP requests to response we're going to stick a future in there the the goal of this is so that when we interact with databases and queuing systems and calling or calling out to other services is we're not going to block an operating system thread so it can be used for other for other requests another motivating thing might be that we might want to stop using exceptions some people like exceptions some people don't some people think they'll go - I'll let you decide and one way of doing that in Scala is to use this thing called an either and this is where you basically say I'm going to return an HTTP response or some type checked error like a throwable or but you don't throw it you just pass it around or just some custom enum that you're passing around to say what the problem is now before we see how hire kinda types and obstructing over them can help us we have to address the fact that we've completely broken our function composition all that stuff I've just talked about in the previous section is broken because we've introduced parts of our logic like interacting with databases and queuing systems and calling out to services they will need to return futures now or something equivalent like a rx Java observable or a completable future and I'm going to assume serialization is still going to be synchronous in CPU bound so sterilizing something and deserialize at something I'm going to assume those function signatures are going to remain the same however creating a customer maybe that involves a call out to some external registry in your company to see whether they're already a customer though they've been blacklisted so I'm gonna make that one a future and I'm gonna make saving a customer a future because that definitely will be that definitely will be asynchronous and if we go back to our function composition we get about this far we can deserialize the person and then we can create the customer but then we end up with the wrong type rather than HTTP request a customer which would compose RIT nicely with our saved customer we've got a bloody future in there which is very upsetting and when these two functions to fix this I think we only need two one is called flat map this is a function on the Scala future it's called then compose on the Java completable future and map on the future which is called then apply on the Java completable future what does this allow us to do well it allows you to take a future of something a in this case what do we have I've forgotten we have a future of customer and then it takes another function which goes from that a into another future it's another asynchronous computation and it returns a future of B and that's going to allow us to put in our save customer because that's the type signature is it happens a and B are actually the same type in this case but that doesn't matter so let's see how that works so we'll just define a function on the fly so this is a way I can just create a function on the fly so I'm going to take an HTTP request which is the hey char on there on the right hand side there I'm going to call the first step the function composition that still worked and then I'm going to call flatmap but save customer and that gets me nearly there the last thing I need to do is do the serialization now that didn't introduce any new futures so we're not going to implement that with flatmap we're going to implement that with map and we can actually do all this on one line with a for comprehension but I won't go into that cuz that's a whole new set of syntax to introduce and this pattern is very very common as soon as you start representing things like a synchronicity in the type system with something like a future you always want to be you don't want function composition to go from A to B and B to C you always want this extra thing in here like a future or a completable future or or something else and I call it super compose but it's got fancy names in some libraries if this is uh interesting to you there's a whole book which will teach you about this in Scala or just this very particular concept there's a blog there and I'll I'll tweet out my slides if you want to read about this but rather news that cool every which is called cats which is an excellent name for a software project we're just going to write all of the same code again but we're going to use either because we changed our mind between wanting to use futures or either we're not really so lots of new syntax on this slide what we've got here is a type parameter which we're used to having but normally it's like a or B or T but it's got a weird thing after it it's got like an underscore what this means in the scale of programming language is it's some type we don't know what it is our but it we all there anything we know about it is it takes one type parameter and this is what we mean by abstracting over these type constructors or or higher credit types we can actually write things like classes and things and we can have a type parameter which is just some type constructor that type constructor could be list or future or completable future it could be anything however if it was anything it would be pretty damn useless because what can you call on anything hash code equals not very useful so the other bit of syntax that we're going to introduce the other feature is to say okay I need to be able to turn it into a mapable and what's a mappable well a mapable just has two functions because they're the only functions we used our business logic obviously deals with customers and all of the other things there but when we were doing our composition we only use two functions and wow that's a lot of square brackets and stuff but we don't need to worry about that you just need to take away that the functionality this is going to give us is we can write all of that composition in terms of some type parameter which we're used to doing the thing we're not used to doing is that type parameter is actually something like a list or a future and we can decide later and if I'm not going to show all of the machinery that's required for that but if you want to see it it's in the example project but let's see how the composition works now well we're not dealing with futures now we're dealing with something we don't know what it is it's just F and we can still compose our two functions from this we can still deserialize and we can still create the customer and we can then use flatmap because we know the only thing we know about F is it's got flat map and it's got map so we can still do the composition we directly did with future but we don't know what it is yet and we could instantiate a version of this for future and if I were to type check this full request it wouldn't be from F because we've specialized it down to a future that's a weird feature and that's something that there's not really an equivalent thing that you can say oh it's a bit like this in another programming languages apart from languages like Haskell and the question I would be thinking about if I was if I was in the audience was is this useful how often do you want to do this well about five years ago the last time I worked on a on a big project in in a language which didn't support higher kind of types it was Java it needed to be synchronous for scalability so we needed some async web framework and this was rat-pack not sure if you ever use that rat-pack has its own asynchronous construct like it's called a promise we used hystrix because netflix told us to and hysterics is a library for wrapping external requests and putting things like circuit breakers and deterministic timeouts and logging they if you want to be asynchronous use Eric's Java observable we had a database because everyone has a database and that was using guava listenable future and then our own code and code within the company was using Java rates completable future what do you think our code looked like it was just converting between these types that business logic was lost in it all of these types here they have and they take one type parameter so we can abstract over it and they all have a function which does exactly what flatmap does and exactly what map does so last section of the talk is implicit because I very foolishly maybe I'll very quickly said all you can just call flat map on it because of that type that that F was there with its mappable but implicit switch are quite a controversial feature they're required to build the machinery so the previous code worked and the takeaway is kind of from the implicit section is I think most sensible uses of implicit sin the Scala programming language replaced runtime reflection so things like sterilization libraries and dependency injection all these things we either going to use implicit so we're going to use partial application etc and I for me the big event advantage of implicit since Carla is that it's a language feature which I get to learn and then it's applicable for the rest of my career using the Scala programming language if I learn how a particular framework does it uses reflection to achieve something similar it's completely proprietary to that framework and it's not like a transferable skill fortunately spring is so dominant that it probably will be applicable for the rest of your rest of your career and I think it goes without saying that the complicit features I'm about to show you are far more explicit than think you then reflection because they're either at compile-time and B those rules associated with what they do however because I'm a realist I'm going to talk about a terrible use of implicit someone which really kind of get I think gives them a bad name and that's type conversions so in Scala you can explicitly convert from one type to another using an implicit and a terrible use case in my opinion of course is this objective is to go from a concrete type like cut and turn it into a concrete type like dog so imagine I've had dogs before and they get very dirty when you take them for a walk so what I'd really like to do is be able to clean the dogs all case classes in Scala have a copy constructor where you can just override certain fields that's what that is and I can just say the status of this dog is it's been cleaned with a host pipe right I have a cart type many cats one of which of my cats is called Ruby now do you think in a statically typed programming language that we should be able to pass Ruby into clean dog who thinks we should be able to clean Ruby with a hose pipe no one one person thinks it right this is Ruby who still thinks we should be able to clean Ruby with the host pipe anyone he stares - now what Oh she helped me prepare the talk anyway Ruby's quite a nice car if I cleaned it with a hose pipe she would forgive me within a very short amount of time and she'd be back back on my on my knee her sister would not forgive me she's a very like picky car and when I suggested to her that she was cleaned like a dog that was the facial expression but I got however you can do this in Scala in a statically typed programming language I could write this which i think is a very bad use of implicit of course I've said a couple of times that implicit in Scala you need to explicitly use them you need to bring them into scope so I would have to have a function like this for this to work and for those at the back there it's a function which turns cats into dogs why you'd want to do that I don't know and the only difference is it's got the word implicit in front of it and that means the Scala compiler when it's time to type check this thing here this clean dog with the rubian if it doesn't compile it can search around all of the implicit syn scope and turn poor ruby into a dog and then cleaner I think the only really good use case of this is when building like embedded DSL and even certain in certain libraries but at that point you're not really programming scholar you're programming - embedded DSL and those kind of things you just have to learn but I don't I'm not a fun one thing I am a fan of though is something I'm gonna call principle type conversion I don't know why it's principles really but it's going to be principle and we've already seen this so if we create types like this markable and the only way we can turn things like futures and completable futures and either's into this type and use it as a mapable thing is via an implicit conversion I think it's a good thing one of the reasons I think why I think it's a good thing is if I want to find out what implicit stuff is happening what do I need to do the only thing I need to do is find the implementations of this trait which means that I can just go into my I can just go into my IDE press ctrl shift B and it tells me it tells me all the implementations and I know which types in my ecosystem can conform to this mapable so I know that my business logic can be defined in terms of them what does that machinery look like well what we need for the previous code to compile that I showed you if the colon Muffy ball after after after the after the F is this in scope so we need to show that the Scala compiler how how a future is mapable and it's it's really quite straightforward to make a future malleable because we pick the methods or muffle from methods on the scale the future so we just call map and we just call flat map it's not always as easy so if we decides that we don't like scarless future and we've some bizarre reason wanted to use the judge at a Java's completable feature from from Scala then we could do the same thing so it's been cut off a bit but the important thing to note here is I'm still making a complete a future completable future mapable but I'm calling different methods on the completable feature I'm calling then apply or I'm calling then compose and I think this is a really good use case of implicit since sites Carla and I allows a lot of the cool functionality that we probably rely on if you program in Scala so had a bunch more uses of implicit but I had to add to cut them off because I was going to run out of time so the kind of summary of that of the talk is that what I want to well not really want to show is that we can use like features of a programming language it doesn't need to be scholar it could be whatever rather than relying on things like runtime reflection and some of the the most important one I think is the function composition over layers I really like structuring applications applications that way the higher kind of types thing it can be very hard to use something like that unless you move to a program a programming language like Scala or high school and I wanted to like give a sales pitch for scalar implicit because I actually think they have a bad name and they have there's some really good use cases of them that offer some some good functionality that said if I've somehow unsuspectedly inspired you to go and find a new job in Scala or convince your team that you should you should use Scala these are kind of my top tips that maybe I didn't follow when I first moved is you really need to be prepared to be a beginner in this programming language it's not like moving from Java to c-sharp which may be the syntax and the runtime changes a lot but the semantics of it are very very similar all moving from say even Java and cotton a far far more similar programming languages Scala really is a different paradigm the collections you use work in a completely different way by default you'll be using persistent immutable collections which are completely different and have completely different behavior and runtime costs than than the ones you'd say be used to be using in something like Java and you really do need to pick a programming paradigm in Scala because you could write it just like Java you could use mutable state and you could not not programming thing in terms of expressions and values you can do that and you can program as if it was Haskell like there's that broader spectrum of ways you can use the scale the programming language I really hope that you would pick something in the middle use some of the cool features which you don't have in in other programming languages but still reuse a lot of the log that they're useful knowledge that you've gained by doing object-oriented programming and of course pick a style guideline them one thing the scarlet ecosystem has is a lot of static analysis tools and there are some gotchas in the scale of programming language but this thing's like wart remover like a build tool tuggin that'll say do you really want to do this you're falling into one of the traps of the programming language and on that note I just want to say thank you very much for for listening and I will we've got a few minutes left for questions so has anyone got any questions yeah there we go any more questions so the project there is basically an SBT project which is the build tool for Scala and it builds a set of HTML slides as well as by pulling the code out there so you can go around and play with the code it's also got the full mechanics required to make the higher kind of type stuff work and it's not using like a library or anything it's got it all the code is there but in reality if you're doing that style of programming you'd use a library called cut like like like cuts which is a an awesome name any more questions nope thanks very much for listening and actually coming [Applause]
Info
Channel: Devoxx
Views: 33,196
Rating: 4.9812207 out of 5
Keywords: DevoxxUK, DevoxxUK2018
Id: 4QIgEMvUfIE
Channel Id: undefined
Length: 48min 5sec (2885 seconds)
Published: Wed May 16 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.