Functional Programming

@_kabal_

Here's two examples of how you can make this work with a standard function (your first example). Code comments are inline; but PM if you have any questions.

Solution 1 method signature (lazy):
Last lambda closure () is what delays the execution.
($key, $cache) -> ($hitcb, $misscb) -> () -> Void

Solution 2 method signature:
($key, $cache) -> ($hitcb, $misscb) -> Void

Note: the final Void return is based on the definition of the $hit / $miss lambda functions; which at the moment don't return anything; they just simply echo something. Naturally you can change this.

PHP:
<?php
// ---------------------------------------------------------------
// Summary: PHP allows functions within functions, ...
//          This allows us to do step processes similar to what
//          other languages like Haskell, F#, Swift, ... offer
//          This is more typically known as currying, of which
//          partial application is also an implementation.
//
//          Partial application however prefills / calculates some of 
//          the parameters to be shared amongst calls. For example:
//          Pre-initialising database functions with connection values.
//
//          The examples I've included more closely mirror what
//          what I believe you are doing, except that I given you two ways
//          to do this; delayed execution (lazy), and immediate  execution.
// ---------------------------------------------------------------

// This is the shared objects for this example; stand-in cache (dictionary), 
// $hit / $miss lambda functions which can be replaced by inline closures.

// Dictionary (example's stand-in for cache)
$appcache = [
  "foo" => 212,
  "bar" => 323,
];

// Cache hit lambda callback function (alternate: inline closure)
$hit = function ($value) {
  echo "cache hit; value = ".$value."\n";
};

// Cache miss lambda callback function (alternate: inline closure)
$miss = function () {
  echo "cache miss\n";
};


// ---------------------------------------------------------------
// Solution 1: Deferred execution until later (lazy)
// Return: value from function call is the composed function
//         wrapped within a lambda function that just needs
//         to be called to evalute.
//         Lazy execute result is value from $hit / $miss 
//         (i.e. void in this example)
// ---------------------------------------------------------------

function getCachedItem($key, $cache) {
  return function ($hitcb, $misscb) use ($key, $cache) {
    return function () use ($hitcb, $misscb, $key, $cache) {
      array_key_exists($key, $cache) ? $hitcb($cache[$key]) : $misscb();
    };
  };
}

$foo = getCachedItem("foo", $appcache)($hit, $miss); // nothing happens here, $foo now holds the delayed function call for "foo"
$foos = getCachedItem("foo", $appcache)($hit, $miss); // nothing happens here, $foos now holds the delayed function call for "foos"

$result = [$foo, $foos];
array_walk($result, function ($callback) { $callback(); }); // Execution happens here, result is: "cache hit; value = 212" followed by "cache miss"

// ---------------------------------------------------------------
// Solution 2: Execute on call
// Return: Immediate execution of $miss / $hit, result is value
//         $miss / $hit (i.e. void in this example)
// ---------------------------------------------------------------
function getCachedItem2($key, $cache) {
  return function ($hitcb, $misscb) use ($key, $cache) {
    array_key_exists($key, $cache)?$hitcb($cache[$key]):$misscb();
  };
}

getCachedItem2("bar", $appcache)($hit, $miss); // output = "cache hit; value = 323"
getCachedItem2("bars", $appcache)($hit, $miss);  // output = "cache miss"

?>
 
Last edited:
That is quite insightful.
Good. Sadly as with a lot of PHP functionality, the documentation is lagging behind significantly, so these gems remain all but hidden for many PHP developers. Still the best reference for closures and lambda functions is the original RFC from 2008. Here's a link (read and enjoy): https://wiki.php.net/rfc/closures

Note on 'use' keyword:
  • The keyword 'use' means something different than at the global scope; in lambda functions we use it to declare what outer values we want to use within the lambda. The default operation of 'use ($variable1, variable2)' is to make a copy of $variable1 and $variable2, which means we achieve something very similar to value types (a type of immutability); changes to $variable1 and $variable2 will not affect the same variables in the outer scope, and internally we won't be affected by any external changes.
  • You can of course override this behaviour by prefixing the variable with ampersand. e.g. 'use (&$variable1, $variable2)' -- here $variable1 is passed by reference; meaning it keeps its mutable state; changes made to this variable both externally and internally will be merged, whereas $variable2 is still copied, because it doesn't have the ampersand prefix.
  • How is this beneficial; well in FP we try to avoid mutability because that not only e.g. introduces hard to diagnose bugs, but also makes it very difficult for concurrency (multi-threading) and delayed execution (lazy). Taking a copy upon entering a lambda will ensure that the result of the lambda is always consistent. Consistency avoids the hard to diagnose bugs, and makes testing much easier.
 
Last edited:
[)roi(];18697838 said:
Good. Sadly as with a lot of PHP functionality, the documentation is lagging behind significantly, so these gems remain all but hidden for many PHP developers. Still the best reference for closures and lambda functions is the original RFC from 2008. Here's a link (read and enjoy): https://wiki.php.net/rfc/closures

Note on 'use' keyword:
  • The keyword 'use' means something different than at the global scope; in lambda functions we use it to declare what outer values we want to use within the lambda. The default operation of 'use ($variable1, variable2)' is to make a copy of $variable1 and $variable2, which means we achieve something very similar to value types (a type of immutability); changes to $variable1 and $variable2 will not affect the same variables in the outer scope, and internally we won't be affected by any external changes.
  • You can of course override this behaviour by prefixing the variable with ampersand. e.g. 'use (&$variable1, $variable2)' -- here $variable1 is passed by reference; meaning it keeps its mutable state; changes made to this variable both externally and internally will be merged, whereas $variable2 is still copied, because it doesn't have the ampersand prefix.
  • How is this beneficial; well in FP we try to avoid mutability because that not only e.g. introduces hard to diagnose bugs, but also makes it very difficult for concurrency (multi-threading) and delayed execution (lazy). Taking a copy upon entering a lambda will ensure that the result of the lambda is always consistent. Consistency avoids the hard to diagnose bugs, and makes testing much easier.

That was quite an eye opening read (I read all of it and more) - especially https://secure.php.net/manual/en/functions.anonymous.php also here is a nice article about currying - https://zaemis.blogspot.co.za/2009/06/currying-in-php.html

This is also a very nice gem I have - https://leanpub.com/functional-php/ (it's free, but I paid $10 for it since it will benefit me a lot more in the future)

I do like using approaches like this to make use of pure functions
PHP:
<?php
/**
 * Creates an anonymous filter function accepting items > $min
 *
 * Returns a single filter out of a family of "greater than n" filters
 */
function criteria_greater_than($min)
{
    return function($item) use ($min) {
        return $item > $min;
    };
}

$input = array(1, 2, 3, 4, 5, 6);

// Use array_filter on a input with a selected filter function
$output = array_filter($input, criteria_greater_than(3));

print_r($output); // items > 3

PHP:
<?php
$square = function ($arg) {
    return $arg * $arg;
};

$value = $square(2); // 4

I am not sure what exactly functional programming means, but something I think would be quite awesome is using Java inside php example

[Java code - ignore the mybb tag]
PHP:
public class factor {
    public int factor(int num) {
        if ((num == 0) || (num == 1)) return 1;
        return num * factor(num - 1);
    }
}

You can then simply call just one function from your PHP script to do a lot of Java processing.

PHP:
<?php
    $factor = new Java('factor');
    print $factor->factor(4);
?>

This is a small example, but I think this would make for incredible fast applications since you can put a lot of your application logic into the Java classes, which is then properly compiled down into byte code. I imagine if this can be done with C it would be even better?
 
Last edited:
That was quite an eye opening read (I read all of it and more) - especially https://secure.php.net/manual/en/functions.anonymous.php also here is a nice article about currying - https://zaemis.blogspot.co.za/2009/06/currying-in-php.html

This is also a very nice gem I have - https://leanpub.com/functional-php/ (it's free, but I paid $10 for it since it will benefit me a lot more in the future)

I do like using approaches like this to make use of pure functions
PHP:
<?php
/**
 * Creates an anonymous filter function accepting items > $min
 *
 * Returns a single filter out of a family of "greater than n" filters
 */
function criteria_greater_than($min)
{
    return function($item) use ($min) {
        return $item > $min;
    };
}

$input = array(1, 2, 3, 4, 5, 6);

// Use array_filter on a input with a selected filter function
$output = array_filter($input, criteria_greater_than(3));

print_r($output); // items > 3

PHP:
<?php
$square = function ($arg) {
    return $arg * $arg;
};

$value = $square(2); // 4

I am not sure what exactly functional programming means, but something I think would be quite awesome is using Java inside php example

[Java code - ignore the mybb tag]
PHP:
public class factor {
    public int factor(int num) {
        if ((num == 0) || (num == 1)) return 1;
        return num * factor(num - 1);
    }
}

You can then simply call just one function from your PHP script to do a lot of Java processing.

PHP:
<?php
    $factor = new Java('factor');
    print $factor->factor(4);
?>

This is a small example, but I think this would make for incredible fast applications since you can put a lot of your application logic into the Java classes, which is then properly compiled down into byte code. I imagine if this can be done with C it would be even better?
Functional programming like OOP takes time to learn, the book you bought is a good place to start, but also scan youtube, medium.com, and don't restrict yourself to only PHP FP materials; Functional Programming techniques are universal so even Scala, Haskell, F#, Javascript, ... explanations will translate fairly easily to PHP. The FP terms (like Monads, Monoids, Functors, ..) can sometimes be a bit off putting, but that's just because of it's mathematics & category theory origins.

Here's also a good Functional framework for PHP; it not only fills in a lot of functional gaps, but also has code that is quite easy to understand. https://github.com/lstrojny/functional-php

Anyway if you need help with anything, just ask.

As for the Java bit, that's something entirely different; Google PHP Java bridge, there are many solutions for this. Personally I don't see the point.
 
Last edited:
[)roi(];18698314 said:
As for the Java bit, that's something entirely different; Google PHP Java bridge, there are many solutions for this. Personally I don't see the point.

I can think of a few, most specifically ie the first thing I would do is use it for reporting, jasper is marvelous.

I would use php as a pure templating language and use Java as the business logic.

But we/I are/am getting OT, I will create another thread on this later.


As for the rest, amazing world I have a lot to learn, but I'm loving every second of it creating powerful stuff bringing ideas into existence from literally nothing. I love programming so God damn much.
 
I can think of a few, most specifically ie the first thing I would do is use it for reporting, jasper is marvelous.

I would use php as a pure templating language and use Java as the business logic.

But we/I are/am getting OT, I will create another thread on this later.


As for the rest, amazing world I have a lot to learn, but I'm loving every second of it creating powerful stuff bringing ideas into existence from literally nothing. I love programming so God damn much.
Sure Jasper is a nice reporting solution; so too the ETL.
 
I built my own PHP FP library a while back; covering many of the base data types (e.g. Identity, Maybe, Either, Reader, Validation) including many combinators.

You're welcome to a copy of the code if you like?
Yes please, I want to explore this more.

I'm just still struggling to understand where I would use this, but that said I don't have BIG/Complex projects just billing and basic stuff.
 
Yes please, I want to explore this more.

I'm just still struggling to understand where I would use this, but that said I don't have BIG/Complex projects just billing and basic stuff.
Sure, I'll find time this weekend to put up a copy on github; will PM you once it's done.

As for you struggling with where to use it; that's normal for everyone in the beginning & all part of the learning.
The monad can replace almost every parcel of code, because it's an abstraction of very basic units of computation that frequently repeat in every codebase; the why one would do that can also be challenging at first, but the reasons why becomes more obvious the more you use it.

Simply said it will reduce code repetition, make composition of easier and turn imperative style code into code with a declarative style.

I could always do a future functional thread on using monads in PHP if you like.
 
Yes please, I want to explore this more.
Here's a link to my PHPrelude functional programming repo, which is built off a base of the PHP Vector basic functional combinator framework.

There is however no dependency to Vector -- all the Vector code that I use has been builtin and modified to tie in better with my monadic data type implementations.

Data Types & Features
I've implemented the Identity, Maybe, Result, Either, Validation and Reader monad data types, and these are for the most part fully featured monadic data types barring for methods like Traverse, Sequence and Zip -- which btw are fairly easy to add as they hinge off of the other methods that I already implemented.
 
Last edited:
Top
Sign up to the MyBroadband newsletter
X