Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save morrisonlevi/d550b3b64d2181e4bbf7 to your computer and use it in GitHub Desktop.

Select an option

Save morrisonlevi/d550b3b64d2181e4bbf7 to your computer and use it in GitHub Desktop.

References in PHP suck. Here's an example:

$foo = 1;
func($foo);
// Has $foo changed value?
// You *must* know the definition of func

You may write this off as crazy -- of course you need to be familiar with func to use it, right? Well… depends on who "you" is. I've debugged code that I didn't write many times. Often it calls code that I also didn't write and am not familiar with. In order to know where the variable I care about changes requires me to look at assignments and every single function where it is used as a parameter. This majorly sucks.

Debugging isn't the only area where references suck. Remember how we cannot know if any given function passes a parameter by reference? This makes optimizing code more difficult. In general it makes writing any code that reasons about code more difficult.

Additionally, closures that use references now rely on external state. External state is a lot like references: it makes debugging, optimization and reasoning more difficult. So not only do we have have references (which suck) but we have external state (which sucks).

Consider the following code snippet from two points of view: one where variables are captured by reference in closures and one where they are captured by value.

$initial = 0;
$f = ($fn) ~> ($input) ~> {
    $accumulator = $initial; 
    foreach ($input as $value) {
        $accumulator = $fn($accumulator, $value);
    }
    return $accumulator;
};

$initial = 4;

If closures capture variables by reference then modifying $initial alters the function $f. This is bad enough in any language, but in PHP $initial isn't even guaranteed to be the same type so we could end up with new Foo() and $f will break. This can be exacerbated when $f is defined far away from where it is executed.

Now consider the case where the variables are captured by value. The function $f is now dependent only on the state of the environment and variables in which it was defined. This makes it more resilient to unintentional changes and is easier for humans and tools to reason about.

In summary I am completely in favor of capturing variables by value and oppose capturing variables by reference. I am willing to produce

Copy link

ghost commented Jun 11, 2015

The ability to modify external state is probably the single best feature of closures. With any programming discipline, there's going to be some caveats and some places where a particular approach simply isn't the best option, but you can't throw the baby out with the bathwater.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment