 I think we're going to get started in about a minute or so. And the mic's off. All right, I think we're about to get started. There's my microphone on. All right, I think we are ready to get started here. Before we actually dive in, a quick show of hands. Who here has no idea what this functional stuff is, and they're here to figure out what I'm talking about? OK, who here knows what functional programming is, and is here to figure out how in the world it applies to PHP? OK, so about evenly split. I think I saw some people raise their hand twice. Who raised their hand twice? Yeah, I knew someone had. OK, so let's dive right in. Thank you all for coming. The second session is functional PHP. A bit about me. My name is Larry Garfield. I'm a senior architect at Palantir.net, for a Drupal development shop based in Chicago. I'm an advisor to the Drupal Association, one of the initiative owners for Drupal 8, co-author of Drupal 7 Module Development. And I talk a lot about software architecture, and shoot my colleagues with Nerf guns. That's basically what I do during the day. At Palantir, we do mostly institutional not-for-profits with Drupal. So Journal of Foreign Affairs is one of our sites. The Field Museum of Natural History in Chicago. It's a very large museum, all Drupal now. OpenSource.com, which is run by Red Hat, a partnership between us and Acquia. How many Americans are there in the audience at this point? OK, so a few of you know what I'm talking about these places, Marketplace. That's the kind of work we do. That's kind of my background with Drupal. But here we're talking about functional programming, which is not a Drupal-specific topic. So there's going to be very little Drupal in this session. I'm going to warn you right now. This is going to be a kind of heavy session. Please bear with me. But at the same time, if you are a hardcore functional programming person, you're probably going to be upset that I am not going into more academic detail. So I'm going to try and annoy both groups equally. So let's set the way back machine for the early history of computer science, as we understand it today. And a man named John Van Neumann. John Van Neumann was an early mathematician, physicist, computer scientist, and all-around insanely smart person. Among other things, he was responsible for set theory, operational theory. He was involved in quantum theory that he actually considered that his greatest contribution. He worked on the Manhattan Project. He's just way too smart for us to not all know who he is. But one of the things that he is credited for is something called the Van Neumann architecture. The Van Neumann architecture is basically the way all computers work. So you've probably seen a diagram like this at some point. A computer consists of some kind of processing unit, some kind of memory system to store information, and input and output, all connected via this data bus. Every computer you have in this room works on this model. Basics of the Van Neumann architecture. A program is just data. This is the concept of stored program. This is one of the fundamental building blocks of computer science as something that you can use a keyboard for instead of a screwdriver. A program is simply a series of steps. That's all it is at a basic level. Those steps execute in linear sequence one after another. And the purpose of those steps is to alter registers in memory, places in memory that hold some value. The purpose of a step in a program is to change state. One of the things that you can change is what that next step is so you can have flow of control. So if the value in this register is something, then the register that says what the next instruction is to some other value, and you can jump around like that. That's assembly. Who's actually done assembly of some form? Wow. Who's done assembly not in school? Much smaller group, I thought so. This is the concept of imperative programming. By imperative, we mean like the imperative mood in a human language. Go here, do this, change that, say this. That's that type of programming. It's just a series of commands for the computer, a series of very precise instructions that are carried out in order. And you have state. State is those memory registers. They are values that change over time. And the reason you have the program is to change that state. Every single computer today works on this model. Everything we do, every programming language, is syntactic sugar on top of that. Imperative programming conceptually is following a recipe for a cake. You have this bowl that is your state, and you say, OK, add this ingredient to it. I've changed my state. Add this ingredient. I've changed my state. Mix it. I've changed my state. That is imperative programming. Procedural programming, which we should all be familiar with if we work in Drupal, is really just an evolved form of that. Introduces the concept of a procedure, which is a reusable series of commands, sometimes called a subroutine, depending on the language. And when you have this reusable set of commands, you can do more complex things with it. You also get structured programming, which are these very familiar control structures, so that you can logically say, if this do that, do this X number of times, rather than playing around with if this value set the jump register to this thing. Because really, who wants to do that? I thought so. So very simple procedural program here. We have some variable that's a list of numbers. We want to find the biggest one, so we have that variable. We define a procedure that just modifies and checks these values, and we call it, and then we can print the value. This is your fairly basic procedural program. Older programming languages work exactly like this. This is not a syntax from an existing language as far as I'm aware, but they all work essentially the same way. So if imperative programming is following a recipe for a cake, procedural programming is like singing a song, where you have a refrain. Do these things, and then call the refrain. Say these things, and call the refrain. This is all just the concept behind how most programming languages that we use work. When you're dealing in imperative programming, your job as a programmer is to define how a program works. How being the key word there. You say exactly what the program will do when, and the program does it. And it's up to you to not screw up, because the program will do exactly what you tell it to, which is the problem. Contrast this to a different approach to programming, declarative programming. Pretty much everyone in here, I'm going to bet, has done some declarative programming. Who here has written an SQL? Declareative programming. You are not saying how the database should go about joining tables or finding values or aggregating things. You say what it should do. You're telling it, find me this value out of this column when this is true from my data set. Just go do it. And then it's up to the program to figure out what that actually means in terms of moving memory registers around. You're not concerned with that. That's not your job. Your job is to think at a higher level. This brings us to our next super smart person, a man named John Bacchus. You may have heard of him, or may not, but he is most notable for, among other things, inventing Fortran, one of the first programming languages, first high-level programming languages. And as penance for inventing Fortran, he then spent the rest of his career coming up with good ways to write programs instead. So he is, for instance, one of the people behind Bacchus in our form. Does anyone remember that from school? OK, it's that guy. This is a standard way of defining the syntax of a programming language. He was one of the people involved in that. He was one of the co-developers of ALGOL, which is another tool for defining algorithms in a way that makes sense. And in 1977, when he was accepting a Turing Award, he presented a paper on functional-level programming called Can Programming Be Liberated from the Von Neumann Style? Functional Style and Algebra Programs. Now, he did not invent functional programming. The concepts behind functional programming had been around for a long time. They go back to advanced mathematics from the beginning of the 20th century, lambda calculus and such, which I will not mention again. That will not be on the test. But this is really when the concepts started to become popular. List people will argue that list-invented functional programming, but then list people consider lists of invented everything. Functional programming is a kind of declarative programming that is based on algorithm-first thinking, not steps, algorithms. In functional programming, you simply declare what the algorithm is you want to use. And then it's the job of the compiler to turn that into a series of steps. And when we say functions here, we mean functions in mathematical sense. PHP functions and what most languages we're used to call functions are actually subroutines. They're procedures. And you can use them as mathematical functions, but most people don't in practice. Functional programming is built on this different definition of the word function. Functional programming is built on a couple of concepts. Pure functions. Pure functions are functions that have all the properties of a function that you remember from math class in school. Higher order functions and first class functions. Technically, slightly different things, but for our purposes, we're going to say they're close enough that I'm going to refer to them as the same thing. These are functions that you can treat the same as any other variable. A variable can be a function. And you can then, therefore, pass it to other functions as you can any other variable. Immutable variables, that is, once you set the value of a variable, it does not change. Think about that. A variable you can only set the value of once. That's weird. But actually can be very useful at times. And of course, recursion. Let's talk about each of these. Pure functions. A function is pure if it has no side effects. That is, when you call it, the only thing that changes as a result of you calling it is you get back a return value. Nothing else changes. Nothing is printed to the screen. Nothing is written to the database. No global variables have changed. No values in the input objects have changed. Everything is a very explicit input and a very explicit output. Very clearly defined what your parameters are and what you get back. They are stateless. When you call a pure function, then call a pure function again, that the first call to it has zero impact on the second call. And you can guarantee that. You know this for a fact if it is a pure function. All it does is take input, give output, period. That's a pure function. As an example, you can do a theme function that is pure. This is not quite what theme list looks like in Drupal, but it's a viable implementation of it. You get in two variables, an array and a list. Neither of those changes as a result of this function. There's no globals, there's no state retained, there's no statics, and you return a string at the end. That's it. You can call this function 1,000 times, and it will have no impact on the 1,001th time you call it. You can call this function 1,000 times, nothing anywhere else in your program will change, guaranteed. That is a pure function. Now think about that, a function where you know that there's no side effects. You know it only depends on the things you know about. That actually makes testing really easy, doesn't it? Or it can. Testability is one of the main benefits of pure functions because you know you don't have weird side effects you need to keep track of. There's no global states to worry about. They're inherently thread safe. Now this doesn't matter in PHP so much, but in many languages that have pure functions explicitly, the language interpreter is able to make optimizations and say, this function, I know I can break off and run in a separate thread. I can break off and run on a separate CPU. I can run on a separate computer if it's a distributed program, and you know that's safe to do. Again, PHP doesn't use threads, but conceptually it still frees you from a lot of, wait, what's the side effect of this? What's this going to do over here? Is this going to break this thing? If it's a pure function, you know it's not going to. It's only going to break things that depend on its return value. They're fairly self-evident. If you look at a functional program, you know everything that goes into it. That function we saw a moment ago. Those six lines or so is all there is to know. You can wrap your head around that and not worry about what's this global state happening over here and does this matter what the input value was? No. You have this little black box, and that's the extent of what you need to know. They're also idempotent, which is the fancy academic way of saying if you put in one value and get a result, if you put in that value again, you'll get the same result. You're guaranteed that if you call this function with 5i, a string i, and you get back 17 through whatever that magic algorithm is, you know for a fact that the next time you call it with 5 and i, you'll get back that same value. You know this, and you can prove this. And that turns out to be really, really powerful. First-class functions. Functions as a variable. Therefore, functions can be a parameter to another function. So you can pass a function to a function, and it can then return a function. We here's worked in JavaScript as well. JavaScript does this all over the place. Oops, there we go. Example, yeah. In PHP, as a 5.3, you have the ability to have functions you can pass around. So this variable here, dollar function, is a function. And you can pass it wherever you want, like any other function. And you can call it at any point. We'll get back to these. They're really, really nice. Benefits, for the OO people in the room who I think are an increasing number, you know strategy pattern? OK, really, really easy because you pass a function to a function, pass function A to function B, function B calls function A. That's strategy pattern. That's the entirety of it, wrapped up there in two functions, each of which can be one line long if you want. You can do some really cool things with partial evaluation and curing, and we'll get back to this in a moment. And you can also do lazy evaluation because you can declare a function and then use it sometime later, but not actually use it if you don't need it. Immutable variables. These are simply variables that are not allowed to change. If you want, but if you have a new function, then they have a new value there. So for example, if you have a language that has immutable functions, which PHP is not, so don't get too worried, then the way you would change something, change a value, is you call another function with a parameter of that variable plus five, or whatever. And when you're doing, when you're thinking in algorithms, not in steps, that's actually really easy to do. That's a natural way of doing it. Benefits, you don't need to worry about the value changing off from under you. If once you know it has this value, you know it's not going to change. If you actually know that, then the engine, the compiler, can do some optimizations and not copy data around. It just moves your references. So you can actually, in a purely functional language, get some very good performance and memory optimizations by the fact that it can make assumptions about what you're going to do. And that can save a lot of memory. And it forces you to think in a stateless way. It forces you to think algorithmically rather than change a value and change it again and change it again and change it again and change it again and oh wait, what happened? Yeah. It forces you to not fall into that trap. Recursion. Now everyone here understands recursion, right? Okay, then you understand recursion. All recursion is, is a function that calls itself. It recurses on itself. And you can use that actually to replace loops. There are programming languages that do not have loops. All they have are recursive functions which actually can do everything a loop does. So kind of the canonical example here, computing a factorial of a number is, one factorial is one, factorial. People know who that is actually? Factorial. Is a mathematical operation. What's that? They don't know it's a number. Yeah, you may remember this from middle school. So fact of number factorial is a number times all of its smaller numbers. Five factorial is five times four times three times two times one. 10 factorial, 10 times nine times eight and so forth. So any number factorial is the number one less than it, factorial times the number. So we define it exactly that way. One factorial is one, anything else is that value times the next thing down from it. And so in six lines, and I'm being verbose here about it, we have that entire algorithm. And we have a termination, so it's not gonna go into an infinite loop. This turns out to be extremely common in any kind of programming that is not purely business logic. You end up with this kind of problem space. Benefits of recursion. Divide and conquer. Probably the most important rule that any programmer can follow. The way to approach a problem is to break it down to smaller problems that are dead simple to solve and then build it back up. With recursion, what you typically are doing is taking a problem and slicing it into a smaller piece and solving that piece. By slicing it into a smaller piece and solving it. By slicing that into a smaller piece and solving it. Very, very common approach. And many languages, PHP not being one of them, unfortunately, can recognize when you're doing that and translate, tail recursion, where the last statement in the function is a recursive call, into an iterative loop approach down in the compiler. Which means that it's really fast, but still really easy for you to debug because you can just look at the algorithm and see what it is. You don't have to deal with implementation. You're just like a definition of the algorithm. And it can be stateless. Why is stateless important? Stateless is important because state is the number one source of bugs. State is the number one source of bugs because keeping track of state is hard. State messes with your logic. Debugging logic, when you have lots of state messing with it, is hard. If you can eliminate all of these variables that are changing the way you're going to behave and just deal with the algorithm, it's a lot easier to wrap your head around what's going on. It means you're more likely to run into an error that is a syntax error than a logic error you need to step through a debugger for an hour to find it. So let's put all of these together. A canonical example for functional programming and recursion, I believe in tradition. The Fibonacci series, which is yet another one of those mathematical things you learned about in school and probably have since forgotten, which is just a series of numbers where each number is equal to the sum of the previous two numbers. And I never had any idea what that was useful for, but apparently it's actually very useful in fractal research and it shows up in nature a lot. So botanists use it, which is kind of bizarre. But okay, let's define it that way. So if A is zero, then that's the zero-width number. If it's one, then it's one. And for anything else, it's just A minus one and A minus two added together, which is exactly the definition of this series. And so you want to know the fifth Fibonacci number? Okay. We calculate that by getting the fourth and the third. And we calculate the third by getting the second and first and so forth. And you have a very simple, straightforward piece of code that you can look at and know exactly how it works. It's pure. There's no state change going on here. If you actually can guarantee that all of these things are true, which this has, there's a lot that you can then do in the compiler or just in your own head in terms of optimizing how you think about a problem. So if imperative programming is following a recipe for baking and procedural programming is singing, functional programming is plugging values and formulas into a spreadsheet. Think about it. We've all used spreadsheets, right? Excel or Google spreadsheet or whatever. You simply put in, you know, the value in this cell is equal to the sum of the value of these cells. You don't care how those get added up. You just care that it's equal to that sum. Same in this column. And then this cell over here is these two numbers divided by themselves. And when you change some input, it just updates. You don't need to concern yourself with what order things update in. You don't need to concern yourself with maintaining state of the addition process. You're just declaring this cell means some of these others. This cell means these two cells divided. It's a lot that you don't have to worry about that way. There are a lot of languages that are built on these concepts. So for instance, ML is one of the older languages. Haskell came out, I think, in the early-mid-'80s originally. It's still around. Very popular in purely functional circles. Erlang is one of the few programming, functional programming languages that people actually use in production. One of the most popular Java servers is actually written in Erlang, eJabberD. Erlang was developed originally by Ericsson to run network switches because it then can be massively parallel. The programmer as an author doesn't care how parallel the program is because every function can be its own thread. In fact, you can replace functions at runtime without shutting down a program in Erlang because of all of these restrictions. Because you know it's stateless, because you know that function is not going to affect anything else. So if you find a bug, you can fix it in production after testing it, of course, but you can upload, you know, your fixed-to-production and load that new component without shutting the program down and nothing breaks. That's really important when you're running a network switch that's carrying 5,000 voice calls a minute. There are a lot of others, too. And you're probably never going to run into any of them in practice because as you saw, most of these examples are mathematical. They're very academically oriented, and that is where most purely functional languages are. This has been changing a bit more recently because when you get right down to it, if everything you have is pure, then your program doesn't do anything. If your program cannot generate output, it's kind of a useless program, right? Most functional languages, therefore, have introduced little gaps in these rules where you can carve out and say, okay, this part of my program is not going to follow these rules so that I can actually have input and output here. And you also have a lot of traditional imperative languages that have been adding functional components to them, saying, okay, I want to get something done, but this actually is kind of useful. This approach is valid. I just need to still be able to break out of it. So you've been having in the past couple of years these two families of language kind of head towards each other. They're starting to converge. And PHP is one of them. You can do everything we just talked about in PHP. You don't get the full benefits of doing so necessarily because the PHP engine doesn't take advantage of it automatically, but you can still take the mental advantage of it. PHP doesn't enforce it, but you can. PHP is as functional as Lisp. I just pissed off all the Lisp people in the room, I'm sure, in that you can do things functionally if you want to. And you can do things procedurally if you want to. And you can do things object-oriented if you want to. And you can mix and match these techniques depending on which makes sense in your use case. This is one of the nice things about PHP as a language. I know it's fun to rag on PHP, but the fact that you can mix and match these different approaches effectively is really, really nice. So let's have a look at how this works. PHP 5.3 introduced anonymous functions. And they work like this. This value equals the function keyword with no actual name that takes these two parameters and does whatever it's going to do. So in this case, we're saying, you know, are these two card objects a pair? And then you can call it just like any other function. You pass in values and you get back, you know, in this case, a boolean. Okay? Now, the way PHP does this is kind of interesting. And purists will tell you that PHP is not truly functional because of the way it does it. I say, meh, it works. Internally, what happens, PHP translates this into this. So as of PHP 5.3, all classes can have an invoke magic method, which gets called when you call the object with, you know, as if it were a function. These two are exactly equivalent as far as the PHP runtime is concerned or close enough to it that we don't need to worry about the differences. Actually, there was one subtle difference. You don't need to worry about name collisions because it's actually anonymous. It's whatever your variable is called. So you don't pull out your namespace with this extra class name. Closures. People argue about this all the time what qualifies as a closure. I'm going to go take this approach. A closure is when an anonymous function references stuff from outside it. So in this case, this is just straight PHP syntax. Use wild while being this card. Okay. That makes wild available in the scope of this function. Now, you do this in JavaScript all the time. In JavaScript, it's implicit. If you use a variable name that is defined in the parent scope of where that function is defined, it just gets bound to it and used magically. In PHP, you have to specify it explicitly. And again, many people will tell you that PHP's implementation of anonymous functions and closures is crap because of this. I actually think this helps avoid security issues, the kind that plague JavaScript all the time. But whatever your opinion, this is how PHP works. And then this is functionally identical to this. Wild. Use that as a growing the constructor. And then when you invoke, you just call this wild. Okay. This is eight lines of code. This is 17. This, you're going to need to create an extra class for it. This, you don't. It's effectively just an easier syntax around the system on the bottom here but lets you think about things in a cleaner fashion. If we have first class functions, functions that can be past the functions, you can nest this kind of thing. So, let's say, is this card a wild card? We're just comparing those two. So now we have this anonymous function that is bound as a closure over this variable. And then our find pair as a closure over is wild. So what happens when we call find pair? Well, find pair takes two arguments and compares those two values out of those and then it calls that function and checks that and then it calls that function again with a different input. But this knows nothing about what the wild card is. This function does, and that's all we need. Cool? Cool. Another advantage is, as I said, delayed execution. Let's say we have a class called container and we use PHP's magic get and set functions on it. And I can go into how those work, but if you don't specify, if you define these and then use a variable, a property on an object that is not set, these get called instead. Okay. And so we say con is equal to this anonymous function, which takes one parameter. Okay. This function, which just returns this array. So we've assigned these into this array here. So when we call container con, that says, okay, get that anonymous function out of that array and call it with this object, which means that C is that container and then we can reference con info, which calls back to that, and we can now instantiate our database connection only when we're about to use it. You've all heard me talk about dependency injection before, at least a lot of you. That's all it is. 11 lines of code with white space. Anonymous functions are very, very powerful when you use them properly. If you want to see this technique in more detail, have a look at pimple, which is a very small dependency injection library written by Fabien Pontoncier, who's our Thursday keynote speaker, which is built on exactly this principle. It's actually more advanced than this, but not by much. It's less than 100 lines of code, but it really exercises anonymous functions in PHP very, very well. Lexical scoping. We were talking about using use before. This is where it comes in handy. To take some array of values and call a function to all of them. Well, array map. It's a very easy way to do that in PHP, and you pass it the name of a function. Okay. And if I want to do something other than double, I now need to define yet another function. So I need to define statically every function I might possibly need. That's gross. Well, we could set a global, and then have multiply just grab that global value, and if you do that, I'll shoot you. This is terrible. I think we've gotten most of these out of Drupal, I hope. Or make it easier on yourself. You can use an anonymous function in almost every place you can use the name of a function. So we say, okay, array map that function. So take that array and apply this anonymous function to every single value in it, and get back the result. And use factor in there. So whatever that is, we now have a function that can multiply by anything on the fly, and we've not polluted our name space. And it's even fewer lines of code than the other things are, too. This is an example of where we are, in fact, using this in Drupal. I copied this out of Drupal 8th this morning. So one of the things we're doing in Drupal 8 is switching to a simply based router to replace the menu system. But we haven't converted all of our thousand or so menu items over to it. So we need some way for them to keep working in the new system. Okay. We've already got the system set up here. So if we've ignored this stuff for a moment, the symphony-based stuff, we can get the information about the menu item. And then if the controller, page callback, is a function, then replace it with an anonymous function. That will call that function. Why in the world would we add that extra wrapper? Precisely for this reason, so that we can get this information where we want it. As an example, the reason we did this is just trying to pass through normal functions as is when we were porting the system over. We got about 40% of page callbacks broke because of just quirks in the way they worked that didn't map to the way symphony worked. We can just grab all of the arguments and show them in here cleanly, and everything suddenly worked. This is a five-line backward compatibility layer that is very fast and keeps all of the people working while we build a new system. It brings us through currying, which has nothing to do with Indian food whatsoever. I apologize. The name currying, actually, you know, listening to it, you'd think it's some fancy mathematical term, or, you know, it has to do with carrying variables spelled differently. Actually, it's just named for Mr. Curry, who is also the person that the Haskell language is named after even though he apparently hated his first name, go figure. I'm not going to go into too much detail on him other than to say yet another one of these crazy smart mathematicians that very few people have heard of, which is very unfortunate. Currying is simply splitting a multi-parameter function into a series of single-parameter functions that get called in sequence. So you take the result of calling the first function and call it with the second parameter that gives you back a function which you call the third parameter. There's various reasons for why you would want to do that. I'm not going to go into detail on those, but this is just a special case of partial application. Partial application meaning halfway call a function. Halfway call a function? Sure. So let's say we've got a function that adds two numbers. We could also say, I want to be able to add one number to this, to a lot of different things. So we have a function add whose sole purpose is to return another function that adds a single value to stuff. So when we call add one, we get back a function that will take whatever is past the it and add a to it, a being one, because we have a closure over that value. Another one add five, this will add five, because in this case this is a separate function, separate object, separate instance, separate anonymous function that's bound to a different value. And then we can call add five and it will add five to whatever we want. Eh, this gets interesting when you then are able to preconfigure functions. So instead we have an adder that we say, okay, I want to be able to add some user defined value to all of these and practice something, you're going to do something a bit more complicated than that, but let's keep it simple. And now you have this function without the overhead of a class, without the overhead of loading, without the overhead of any of this other stuff that people are resistant to. And you can now call this on whatever you want to get back that value and get dependent on that user-supplied data. Make sense? You can also then use that anonymous function in things like ArrayMap and say, okay, cool. I want to take everything and apply some operation to it, but that operation depends on some configured value. Memoization. It's another fun, fancy academic word. Memoization is really a fancy name for caching results. I'm sure there's some better academic term for it, but really that's what it is. And this works only on pure item-potent functions. You get the same input. You get the same output every time. You can take advantage of that fact and optimize your code. And in Drupal, in fact, does this all over the place. Who has seen this code in Drupal somewhere? We've got, you know, passing some value. We have a static cache of the values. Compute them and then return that. And the next time we call it with that value, we just say, oh, it's already in the array, so we don't do any of this expensive stuff and just return it. You've all seen that somewhere, right? That's memoization. Kind of a poor man's memoization, but that's memoization. It's really all it is. Unfortunately, we usually do that around stateful operations like database lookups, which means that we run into really bizarre caching problems when we use the system in ways we don't expect, like unit testing, but that's another issue. But you can memoize a function externally as well. Languages like Haskell will do this automatically. In PHP, you have to do a little work for yourself, but it works. What do you imagine happens with this code? This is an anonymous version of that factorial function we saw before. So we say, okay, this function would use it itself, and therefore it takes itself by reference, so that this is how you can recurs an anonymous function. And we print out what we're about to do, and then have that exact same logic as before. What do you think happens when you call this twice? Well, we get a lot of useless runs of this code, because we call it, you know, three factorial, which calls two factorial, which calls one factorial, and then four factorial, which calls three factorial and two factorial and one factorial. Now, assuming that our logic was actually more complex than multiplying, this could end up being a huge time suck. I have tested this, this does work. If you have a memoize function, which takes whatever function you pass in, and you say you use it, so it's available in the scope, and we just wrap that same static logic around it, you can now take any function, including sometimes recursive functions, and cache its results externally. So now, we don't bother calling three and two and one multiple times, we just call four, and then three is already cached and we're done. That's cool! Does anyone else think that's cool? Okay, someone raised their hand. I thought this was cool when I realized this was actually possible. This works on any normally defined function, a names function. It works on anonymous functions. It works on anonymous recursive functions if the function is still in its declared scope when you do so. So it's a bit tricky there. This does in fact work if it's all in one file together, but I have tested it. You can in fact memoize any function this way, or any non-recursive function. It's biffy! And then you can pass this memoized version around and call its, as if it were the original function, always get the caching. And if you want to throw away the cache, you delete that variable, you drop that variable, you recreate it by re-memorizing, and that cache goes away, because that cache is part of that anonymous function. Cool! Pure functions are awesome. Really. They allow you to do a lot of really cool things, even if the engine isn't taking advantage of it. You can. The key, though, is separating your logic from your I.O., because I.O. makes things impure. So if you want to take advantage of this kind of technique, this kind of style programming, you have to separate your logic from your I.O., which really you should be doing anyway. Even if you're not doing any of this stuff, you should still be separating your I.O. from your business logic. There's a couple of other things that are functional style techniques that you can, again, do in PHP. MapReduce. Who's heard the term MapReduce before? Okay. I see you grinning at me. MapReduce is useful for embarrassingly parallel problems. That is really big problems where one piece of it has no impact on another piece. It contains two parts. Map, which is take a problem and divide it up into identical sub-problems that are independent of each other. And then distribute those to separate workers. Separate workers could be separate threads. It could be separate iterations. It could be separate computers on different continents. It doesn't actually matter conceptually. Because they are independent of each other, because those are pure, the code for you is the same either way. And then reduce, which is, okay, take all of those results, combine them back together in some logical fashion, whatever makes sense in your use case. This is really useful for epically huge data sets, say Google Search, or Parsing Twitter, or other problem sets along those lines. And could get very complicated, depending on your use case, or in PHP, that's what ArrayMap does. Who's used ArrayMap before seeing it in this presentation? Yeah, that's MapReduce. Not a very complicated MapReduce, but it's MapReduce. ArrayMap takes some kind of callback, which can be any callable, which includes anonymous functions, and then an array. So we call it ArrayMap, your logic here in the array. And whatever that array is, that function gets applied to every element, and you get back an array. PHP is not actually going to break it out into separate threads, but you can still conceptually think about it as separate problems. Inside this anonymous function, you deal with only a single value at once, and that lets you zone in on that one problem space. ArrayMap also lets you pass in multiple arrays and get back a single array. So it's a trivial example. Pass in two arrays, add the corresponding values and add the zero with value to the zero with value, first value to first value and so forth, and get back a single array. Conceptually, then, if the PHP developers ever actually managed to parallelize that within the PHP engine, your system would suddenly get faster. You don't have to think about iterating and combining and foreaching, and which array is which, and what's my I offset and so forth. You don't have to worry about any of that. You just deal with this function, and you can get back a single value or with these two values or whatever. Accomplish is the same kind of thing as foreach, but it lets you separate the looping logic from your business logic. And any time you can separate out two different things, it's good. It is slightly slower than doing a foreach, but unless you're running XDbug, it's close enough that it doesn't really matter. If you're running XDbug, function calls get very expensive. So if you're going to benchmark this turn off XDbug first. Fold. This is the academic definition of fold from Wikipedia. Analyze your recursive data structure and recombine through the use of a given combining operation the results of recursively processing its consistent parts building up a return value. I don't understand that either. Iterate over a list and turn it into a single value. That's fold. Take big list, crunch down to single value. And you do that stepwise. So let's say you want to have a sum. And simple mathematical examples. We could do it this way and say, all right, keep track of our results and iterate over this array and just add it up that way and keep changing the result. Or we could use array reduce, which takes an array and then a function, which is backwards from array map because PHP can't get that right to save its life. And so we say, okay, grab this initial value and then starting from that initial value, turn through each item in the array and return the new result that way. Make sense? This is an operation common in functional programming in functional languages that we can do in PHP today and have been able to do for, I think since PHP 4 or so, filter, reduce a data set to relevant elements. Well, that's kind of what the name means. Filter, take this long list and drop it down to the list I care about. It's very similar to the map operation in that you can do it in parallel. And the PHP is the array filter function, which, again, takes an array and then a filter, which is the order that array reduce does, not the array map. It's PHP. What do you want? What's that? Array map takes multiple arrays, filter, I don't believe does. The concept of, you can do it in parallel still applies. So we say, all right, we take this array of values and apply this function to it. That function returns true or false. If it returns true, whatever that value is should be in the result. If it returns false, it doesn't. Most common use to this, if you don't specify a filter function, then PHP just casts the value to a boolean. So if we have this string, if this array, 0, 4, negative 4, some string, false and null, let's see, in PHP, that's false, that's true, that's true, that's true, that's false, that's false. Array filter. We just get back the true ones. Easy. Where is this useful? Oh, I don't know. Multiple checkboxes where you get back an array that is ID equals ID or ID equals 0. But you don't want to save the whole thing. Call array filter on that, boom. You get down to just the values that actually were checked. One line of code. Cool. If you want to do something fancier, provide your own function inline like that so you don't need to pull out your namespace. The code is right there where you can see it. You know what your entire algorithm is. Neat. Key takeaways. I hope you get from this session. Pure functions are awesome. Mostly. There are plenty of places where it just makes your life more difficult. Mathematically, it's been shown. Imperative programming and functional programming are equally expressive. There is no algorithm. There is no program that you cannot write in either of them. It's just sometimes way easier to do it in one or the other. There are plenty of cases where doing something in a procedural fashion is way easier than functional. There are also plenty of cases of doing something functionally and it's way easier than doing it procedurally. In PHP, you get to pick and choose case by case, depending on what makes sense for you. To do that, separate your pure functions, your pure routines from your impure ones. That's just good practice in general even if you're not doing anything functionally. Even if you're doing all-o-o, the same concept applies. Separate out your data and your logic and your I-O. People will tell you that PHP's anonymous functions are not real anonymous functions. PHP is not really functional. Whatever. I ignore that. They're cool. They are powerful. They're even more powerful in PHP 5.4 where you can, in fact, bind them to an object. So you can use anonymous functions to add methods to an object at runtime, which is just slick. And try to think logically, not in terms of state. Think of your algorithm. Think of what you're trying to accomplish, not the nitty-gritty details you don't want to get trapped at that level. Think at a higher level. Think in terms of logic and algorithm, which can be difficult if you're not used to it. Try and force yourself to think at that higher level first and then dip down further if you actually need to. Functional programming is not a language. It's a methodology. It's an approach. It's a thought process. It's a state of mind. It's the way you go about solving problems. And you can use that methodology in PHP, effectively. I think we've got about seven minutes for questions, and then please rate the session online. I think there's a microphone around here someplace. Where's the microphone? There's a microphone here somewhere, I think. No, just yell out a question. Any questions? Yes. The question for the recording is when you use a variable in an anonymous function, can you write to it? There are other ways you can do that. If you just specify the variable name, then it passes by value the same way as a function parameter, which means that if it's an array or a primitive and you modify it, it's a new instance so it doesn't affect the parent scope. If it's an object, then they're both handled to the same object so it will. If you pass it with an ampersand, then it passes by reference, or you use it with an ampersand, it passes by reference, and then it's exactly the same as a function parameter again. If you modify it, then it is the same variable. You can go either way with it depending on what fits your use case. Other questions? Yes. The question is that if you call an anonymous function repeatedly, does PHP recompile it? Not as far as I know. My understanding, someone who has been inside the PHP engine, please correct me, is that the file step turns it into that class-like implementation, so it's only parsed the one time and then it has some garbage internal only name. So, yeah, it should not recompile that every time. That does happen if you're using the create function commands, which is how you use to define functions at runtime before 5.3. Dear God, never do that. And if you use eval, it will recompile it every time. Anonymous functions avoid that problem. That's one of the reasons why they're so nice. So, with anonymous functions, eval and the create function should both be purged from your memory. There's another question here, I think. Someone? Where are the plans to integrate these kinds of things into Drupal? My position at this point is anonymous functions are a tool. Use them where appropriate. If you find some place that they're appropriate, go ahead and use it. If you find some place that they're totally not appropriate, don't use them. Anonymous functions in particular, you know, we are using it a few places right now in court, not many. I have, in fact, seen client code that clients of mine have written where they use anonymous functions as a form callback, a submit callback. That does, in fact, work, which kind of surprised me, but it does. I haven't done that myself, but it does make sense for you. The concept of, you know, pure functions and pure routines and so forth, you should be doing, just as a matter of course, in your programming, Drupal or otherwise, trying to think in that mindset. As far as I know, there's no big anonymous function everything in Drupal like there is with object orientation, and I don't think there should be. But if they fit the problem space and they do what you need them to do, go ahead and use them. We're introduced in PHP 5.3, Drupal 7. You should be running on PHP 5.3 anyway at this point because it's much faster than 5.2, and Drupal 8 is going to require PHP 5.3. So, yeah. The official requirement for Drupal 7 is PHP 5.2, which does not have anonymous functions. If you use anonymous functions in a module, declare a minimum version, and then people have to have 5.3 in order to use your module, which is fine. Plenty of modules did that for requiring 5.2 back in Drupal 6. Yes. So the question is, given this, what's the future of procedural code in Drupal? My expectation is that through Drupal 8 and Drupal 9 will become predominantly OO and use anonymous functions where they make sense but not as an integral core part of the entire system because we're not JavaScript, and that doesn't really make sense to do just the way the language works. Even in JavaScripts, you can get carried away with anonymous functions too if you're not careful. So I don't see Drupal turning into this big all-anonymous function framework. I would again be against that myself. So for readability, is it better to declare a function and then make it a parameter to another call or to inline it? It depends on the use case. If that's the only place you're going to use it, I usually will go ahead and inline it. But to a large extent, that's kind of stylistic. If you have a large array, do you inline it into a function call or do you make it a separate variable and pass it in? Case by case, whatever looks most readable. I usually, like with an array map or something like that, I will usually default to inlining it. But I don't think either way is wrong. Uh-oh, checks. Yeah, so this point, just because we have anonymous functions doesn't mean we're going to turn all functions in Drupal into anonymous functions. That would be a very bad idea. Possibly so. If most things in Drupal are classes and some are anonymous functions, what do we do with the remaining named functions? We'll figure it out when we get there. We're not to that point yet. Any other questions? Back there? Okay, so I'm going to be focusing on different programming paradigms, functional or procedural or OO. Conceptually, I'm okay with it. A system should probably have kind of its primary paradigm and Drupal traditionally has been primarily procedural. Drupal 8, and definitely by Drupal 9, I think would be primarily OO. But, as I said, if anonymous functions are the best way to get something done, if functional programming is the easiest way to use it, if that means you have an anonymous function that you're defining inside an object somewhere and then passing off somewhere else, okay, it works. I'm not a purist and pedant about which one you're using. I just want you to use one that makes sense, has the best