What's a Function, Really?
A free video tutorial from Daniel Ciocîrlan
Software Engineer & Best-Selling Instructor
4.7 instructor rating • 11 courses • 40,504 students
Learn more from the full courseScala & Functional Programming for Beginners | Rock the JVM
Become a Scala programmer and get the skills you need to work with Spark, Akka, and any Scala framework!
15:16:06 of on-demand video • Updated May 2020
- understand Scala code in production environments or open-source projects
- think code differently with functional programming
- write applications in Scala from scratch
- contribute to products and open-source projects written in Scala
- skills to start developing with powerful tools on top of Scala: Spark, Akka, Play
English [Auto] How right. Welcome back to the functional programming section people I'm already proud of you for making this far in this video we're going to make the transition from Object-Oriented to functional programming by discussing what function actually is. All right so in the ID I'm going to create a new package just for this section. So on the lecture's package I'm going to create a new package and let's just call this part three functional programming. So here is where we will store our applications for this section for this particular lecture. Let's go ahead and create a new scholar class and let's call this what's a function and make this an object of course and extends app good. Now the whole purpose of the functional programming section is to use and work with functions as first class elements. What that means is that we want to work with functions like we work with plain values. That's the dream. The problem is that we come from an Object-Oriented world. And when you come from an Object-Oriented world and basically everything is an object that means it's an instance of some kind of class. This is how the JVM was originally designed for Java for instances of classes and nothing else. So the only way that you could simulate functional programming was to use classes in instances of those classes. So in Java and also in Object-Oriented Scala we would write a class called Something something like an action with a method called say execute which for example takes an int and returns a string or something else right. So we would write something like this we would write classes and methods and the way that you would use these things as quote unquote functions although I cringe at the term would be to instantiate this class either anonymously or not anonymously. So if you remember what we did with my list if we go to my predicate here right at the end we are using predicates and transformer's like quote unquote functions but there are actually instances of these classes with on the spot override method definitions. So this is how you would work with these functions so to speak you would actually work with these functions simulations right. At most what you would do would be to Generosa as an abstract away most of the boilerplate so that you could use generic types. So our action here would be some kind of abstract type like a trait and action would take parameters type parameters and we would say that this action execute takes an element of Taipei and returns an element of type B. So this is at most what an object oriented language would be able to do. Again this is how the JVM is naturally constructed. So Escala had to resort to some clever trick is to make it look like a truly functional language. So a better design would be to just rename this to call my function and instead of this executed rename this to apply. Which by now you know had a has a special meaning in Scaur. So if we have a little my function say news superfunction let's say doubler which is a new my function let's say this doubles an int. So this is my function from end to end. And the override def apply takes an int amount of type and and returns and. And let's just say the trans element times 2. This is an instance of this little function like CLOS. But the advantage of Skala as opposed to Java is that we can actually call Dobler of two like it were a function. So doubler acts like a function. I'm going to switch to presentation so you can see the output. So if I can run this dubber actually cause the apply method and this is going to print the number for the consul. All right so for now doubler which is an instance of a function like class can be called like a function. Now the interesting thing is that Scott supports these function types out of the box and the function types are function one or function two or function three up to function 22 but for function with one parameter and one result. This is function one with a and b. So this is a function type which is by default supported in scope. So if for example I create a well let's call this a string to convert or. All right. And this will be a new function one. And look at the ID so the ID already suggests the function types for me. So when you function one with say string and end and they work in the same way. So override def apply with string which is of type string and returns an int and then just say the implementation is string to it. So just as a simple implementation. And now I can actually call this string to end converter and let's just say I call it quote unquote call it with string. Say three plus four. So this thing returns an int plus four I should get a 7 at the con.. All right. Now by default Scullin supports these function types up to 22 parameters. So for example if I have a function that takes two ins and returns and lets say after there will be a new function 2 with end and end. So these are the parameter types and this is the result type and the override def apply takes two parameters a and b both and and the return type is in. Well let's just say it returns a plus b for a simple implementation. OK so this is a proper function. Now the type of adder is if I hover. It's this guy and and error. Int which is syntactic sugar for function 2. So if I say adder is a function to with end and end this is the correct type. Right but as syntactic sugar for this type is int and in parentheses these signify the parameters and error. And this is a syntactic sugar for function too. So this is getting closer to functional programming. So we have function types for example function two with two type parameters and the result type parameter. We write this as a B erro. Are we going to start using these a lot more as we go through the functional programming section. But the elephant in the room in this lecture is the major takeaway which is and I'm writing this in all caps or school functions are objects or instances of classes deriving from function one function to etc.. So we're laying the groundwork here for Scala as a functional programming language based on the Java Virtual Machine which was never originally designed with functional programming in mind. The JVM was designed with object orientation in mind and we'll see throughout the section through a series of syntactic features we'll get to Skala as a truly functional language. All right. So let's practice what we've learned. I want you to go through a series of very simple exercises. First I want you to define a function which takes two strings and concatenates them. So this is dead simple. I just want you to use this function type. All right. Second I want you to go ahead and go to the my list implementation and transform the my predicate and my transformer into function XYZ and see what you find. Third I want you to go ahead and define a function which takes an argument an end and returns another function. Which takes an end and returns and first of all I want you to for this exercise define what's the type of the function of this function and how do you how do you do it how to actually implement this special function so to speak. So as always pause the video and think through these exercises and then a couple seconds. Oh jump in with solutions. All right. So I hope you did it. Let's take them in turn. So a function which takes two strings and cabinets and this is dead simple. So let's call this concat Mainer which is of type string string arrow string. All right. And the value for that is going to be a new function two with string string string and the implementation of the apply method is going to be an override def apply. This takes two strings a and b for example right and returns a string and it just concatenates them together. Of course if I name the parameters differently. All right. So this is the concatenate are. And if I print concatenate her applied with hello and Scala then I should receive the string Hello scholar at the console which is exactly what we expected. Now for them my predicate and my transformer. Well let's go back to my list. So switching Let's go and investigate how these guys look like. So my predicate and my transformer are basically function types. If you take a closer look. So my pretty good is basically a function type from Teater bullion and my transformer is a function time from a baby right now the revelation that I wanted you to reach was that the predicate and transformer types that we wrote in the Object-Oriented section don't make sense here anymore because we already have function types so we can safely delete them altogether. And a bunch of things will now not compile but we can fix them. And here we can fix the my list of strict laws by changing the transformer to a function one or two in a era B-type and transformer here is going to be an error on my list of B-type and a predicate as we discussed is a Boolean type. OK. And suddenly all things now seem more functional programming like. So let's change the function of signatures throughout the code. So my transformer is nothing to be all right transformer. Here is a nothing arrow my list of Bheem predicate is of type nothing to boolean bhalo we have Filcher with my predicate which is of type error or boolean. OK now a pretty good test. It doesn't really make sense anymore. So we can either call pretty could apply which would make sense or simply predicate because we can now call it like a function again below. Transformer is an A or B type and the transform method of course does not exist. We can call apply or we can simply call transformer. Right. And on flat map transformer of a to my list of B is just a erro my list of B. So instead of Transworld we can simply leave the apply method. OK. And now the my transformer my predicate my transformer dont really make sense and we can replace them with function 1 K and predicate is a new function or one from two boolean. All right. And transformer here is a function one from end to my list and these methods are not called transform and test but they are simply called apply. OK so we've suddenly turned my list into a more functional collection because it now uses functions as first class values especially when it comes to map flattop and Filcher these in particular are called higher order functions higher order functions either receive functions as parameters or return other functions. As a result higher order functions are critical of concept to functional programming because it now uses functions as first class values especially when it comes to map flattop and filter these in particular are called higher order functions higher order functions either receive functions as parameters or return other functions. As a result higher order functions are a critical concept to functional programming. So that was the exercise number two. Let's switch back to what's a function and actually go to exercise number three which is a special kind of function which returns another function as a result. This is also a higher order function. So first of all we need to decide what type this function is going to take. Well the type is going to be a functional one because first it takes an int as a parameter. So this is the only parameter that this function will receive. So a function of one and the parameters are going to be in and the return type is another function which takes an intern turns and INT. So the return type is going to be function one of intent int. So this is going to be the final type of our special function. Let's use it. So well let's call this special function which is of type. This guy going to copy and paste it. So is it's going to be a new function one of this type and the right to death. Plie takes an end let's say X and returns function one with an int so because it returns a function one with an end. It will return a new function one with intent and so it will have to return an instance of function one right OK and the override def applies here. We'll take another value Y which isn't and returns an int Okay now we're free to supply an implementation here because I didn't really give it to you in the exercise so let's just say that this just adds to numbers x plus y. Ok so because x is defined in the upper function over here X is visible inside the function implementation which starts here. So X is also visible inside the result value. Let's rename this special function. Let's call this Super adder because it's more suggestive of its implementation. Right. And let's create a little velvet adder. Let's call this at or three. That's because I'm going to call super outer with parameter 3. Now at or 3 here is a new function. So the type of or 3 is in error int which is a function one from end to end. Now if I print the line at or three or three with parameter 4 for example then this will return 7 because the implementation of at or 3 Is this guy which adds X which in this case is three past two super outer before and Y which is the actual parameter. So if I can run I'm going to see the value 7 here in the council in the same fashion. I can actually write print line super outer applied with Parowan or three and then applied with parameter 4. Notice how weird this is. So super applied with three returns a function one. And then I can call that with parameter 4. So if I run this guy I'm also going to see the value 7 this special function so to speak is called a curried function. In the same fashion I can actually write print line super outer applied with Perona or three and then apply it with parameter 4. Notice how weird this is. So super applied with three returns a function 1 and then I can call that with parameter 4. So if I run this guy I'm also going to see the value 7 this special function so to speak is called a curried function curried functions have the property that they can be called with multiple parameter lists just by their mere definition. So a occurred function actually receives some kind of parameter and returns another function which receives parameters. So basically super utterer can be called with multiple parameter lists to get to the final result. We are going to talk about higher order functions and curried functions in the next videos but I want you to get a taste of what occurred function looks like. All right so let's recap our main motivation when starting the functional programming section was that we wanted to use functions as first class programming elements. That is we want to be able to pass functions as parameters or return functions as a result. So we basically want to be able to work with functions like we are able to work with any other kind of values. But the problem is that sköll works on top of the Java Virtual Machine which was never designed for functional programming in the first place. It was designed for Jaba for which the first class programming elements are instances of classes. Now the only solution that will work for a functional programming language is to turn all Skala functions into instances of special kind of function like types and in Scala we have function traits of up to 22 parameters and a function trade looks like this. Ignore the variance modifiers for now we also have syntactic sugar for function types. For example if we have a function to which receives two parameters into string and the return type is an int. This function to type has the sugar in string era end and we're going to use the sugars from now on. All right so quite a promising start in this journey towards a truly functional language. Daniel let's continue together in the next video.