• $elem - represents an element defined as a value. In this context, all that "contains" has to do is to apply the function in $set with the parameter $elem. Let's wrap all in a test. And wrap our production code inside FunSets.php into a class: You can actually run this test and it will pass. The set we defined for this test is just a function that always returns true. It is a "true set". ### The Singleton Set If the previous chapter was a little bit confusing or looked useless in logic, this one will clarify it a little bit. We want to define a set with a single element, a singleton set. Remember, this has to be a function, and we will want to use it like in the test below. We need to define a function called "singeltonSet" with a parameter representing an element of the set. In the test, that is the number one (1). Then, we expect our contains method, when called with a singleton function, to return true if the sent in parameter equals one. The code that makes the test pass is as follows: Wow! That's crazy. So, the function "singletonSet" gets as a parameter an element as $elem. Then it returns another function which has a parameter $otherElem and this second function will compare $elem to $otherElem. So, how does this work? First, this line: is transformed into what "singletonSet(1)" returns: Then "contains($singleton, 1)" is called. Which, in turn calls whatever is in $singleton. So the code becomes: Which actually executes the code in it with $otherElem having the value one.

Which is of course true and our test passes.

Are you already smiling? Do you feel your brain starting to boil? I certainly did when I first wrote this example in Scala and I did again when I first wrote this example in PHP. I think this is extraordinary. We managed to define a set, with one element, with the ability to check that it contains the value we passed in to it. We did all these without a single assignment of value. We have no variable containing the value one or having a state of one. No state, no assignment, no mutability, no loops. We are on the right track here.

## Union of Sets

Now that we can create a set with a single value, we need to be able to create a set with several values. The obvious way to do it is to define the union operation on our sets. The union of two singleton sets will represent another union with both values. I want you to take a minute and think about the solution before scrolling to the code, maybe take a peak on the tests below.

We want a function called "union" that gets two parameters, both sets. Remember, sets are just functions for us, so our "union" function will get two functions as parameters. Then, we want to be able to check with "contains" if the union contains an element or not. So, our "union" function must return another function that "contains" can use.

This is actually working quite well. And it is perfectly valid even when your union is called with another union plus a singleton. It calls contains inside itself for each parameter. If it's a union, it will recurse. It's that simple.

## Intersect and Difference

We can apply the same one liner logic with minor changes to obtain the next two most important functions that characterize a set: intersection - contains only the common elements between two sets - and difference - contains only those elements from the first set that are not part of the second set.

I won't flood you with the test code for these two methods. The tests are written and you can check them if you look in the attached code.

## Filter Set

Well, this is a bit more complicated, we won't be able to solve this with a single line of code. A filter is a function that uses two parameters: a set and a filtering function. It applies the filtering function to a set and returns another set that contains only the elements that satisfy the filtering function. To better understand it, here is the test for it.

We create a set with three elements: 1, 2, 3. And we place it into the variable $u123 so it is easily identifiable in our tests. Then we define a function we want to apply to the test and place it into $condition. Finally, we call filter on our $u123 set with $condition and place the resulting set into $filteredSet. Then we run assertions with "contains" to determine if the set looks how we want. Our condition function is simple, it will return true if the element is greater than one. So our final set should contain only the values two and three, and this is what we check in our assertions. And here you go. We implemented filtering with just three lines of code. More precisely, if the condition applies to the provided element, we run a contains on the set for that element. If not, we just return false. That's it. ## Looping Over Elements The next step is to create various looping functions. The first one, "forall()", will take a $set and a $condition and return true if $condition applies to all the elements of the $set. This leads to the following test: We extracted the $u123 creation from the previous test into a private method. Then we define three different conditions: higher than zero, higher than one, and higher than two. As our set contains the numbers one, two, and three, only the higher than zero condition should return true, the rest should be false. Indeed, we can make the test pass with the help of another recursive method use to iterate over all the elements.

We start by defining some limits for our set. The values must be between -1000 and +1000. This is a reasonable limitation we impose in order to keep this example simple enough. The function "forall" will call the private method "forallIterator" with the necessary parameters to recursively decide if all elements respect the condition. In this function, we first test if we are out of bounds. If yes, return true. Then check if our set contains the current value and return the current value applied to the condition together with a logical "AND" with a recursive call to ourselves with the next value. Otherwise, just call ourselves with the next value and return the result.

This works just fine, we can implement it in the same manner as "exists()". This returns true if any of the elements satisfies the condition.

The only difference is that we return false when out of bounds and we use "OR" instead of "AND" in the second if.

Now, "map()" will be different, simpler and shorter.

Mapping means we apply an action to all the elements of a set. For map, we need no helper iterator, we can reuse "exists()" and return those elements of "exists" that satisfy the result of $action applied to $element. This may not be obvious at first site, so let's see what is happening.

• We send the set { 1, 2 } and the action $element * 2 (double) to map. • It will return a function, obviously, which has a parameter as an element and uses the set and action from one level higher. • This function will call exists with the set { 1, 2 } and the condition function $currentElement equals $elem * 2. • exists() will iterate over all the elements between -1000 and +1000, our bounds. When it finds an element, double of what comes from "contains" (the value of $currentElement) it will return true.
• In other words, the last comparison will return true for the call to contains with value two, when the value of the current multiplied by two, results in two. So for the first element of the set, one, it will return true on two. For the second element, two, on value four.

## A Practical Example

Well, functional programming is fun but it is far from ideal in PHP. So, I do not recommend you to write whole applications this way. However, now that you've learned what PHP can do functionally, you can apply parts of this knowledge in your everyday projects. Here is an example authentication module. The AuthPlugin class provides a method that receives a user and password and does its magic to authenticate the user and set its permissions.

Now, this may sound OK, but it has a huge problem. 80% of the "authenticate()" method uses information from the "AdminModules". This creates a very strong dependency.

It would be much more reasonable to take the three calls and create a single method on AdminModules.

So, by moving the generation into AdminModules we managed to reduce three dependencies to just one. The public interface of AdminModules was also reduced from three to only a single method. However, we are not yet there. AuthPlugin still directly depends on AdminModules.

### An Object Oriented Approach

If want our authentication plugin to be usable by any module, we need to define a common interface for these modules. Let's inject the dependency and introduce an interface.

AuthPlugin got a constructor. It gets a parameter of type ApplicationModule, an interface, and calls "getPermissions()" on this injected object.

ApplicationModule defines a single public method, "getPermissions()", with a username as a parameter.

Finally, AdminModules needs to implement the ApplicationModule interface.

Now, this is much better. Our AuthPlugin depends only on an interface. AdminModules depends on the same interface, so the AuthPlugin became module agnostic. We can create any number of modules, all implementing ApplicationModule, and AuthPlugin will be able to work with all of them.

### A Functional Approach

Another way to reverse the dependency, and make AdminModule, or any other module, to use the AuthPlugin is to inject into these modules a dependency to AuthPlugin. AuthPlugin will provide a way to set the authentication function and each application will send in its own "getPermission()" function.

We start with AdminModule. It does not implement anything anymore. However, it uses an injected object that has to implement Authentication. In AdminModule there will be an "authenticate()" method that will call "setPermissions()" on AuthPlugin and pass in the function that needs to be used.

The Authentication interface simply defines the two methods.

Finally, AuthPlugin implements Authentication and sets the incoming function in a private class attribute. Then, "authentication()" becomes a dumb method. It just calls the function and then sets the return value. It is completely decoupled of whatever comes in.

If we look at the schema, there are two important changes:

• Instead of AdminModule, AuthPlugin is the one implementing the interface.
• AuthPlugin will "Call Back" AdminModule, or whatever other module sent in the permissions function.

## Which One to Use?

There is no correct answer to this question. I would argue that if the process of determining the permissions is quite dependent on the application module, then the object oriented approach is more appropriate. However, if you think that each application module should be able to provide an authentication function, and your AuthPlugin is just a skeleton providing the authentication functionality but without knowing anything about users and procedures, then you can go with the functional approach.

The functional approach makes your AuthPlugin very abstract and you can depend on it. However, if you plan to allow your AuthPlugin to do more and know more about users and your system, then it will became too concrete, and you don't want to depend on it. In that case choose the object oriented way and let the concrete AuthPlugin depend on the more abstract application modules.