The more things change, the more they stay the same.

This post is part of the thread: Technology & Society - an ongoing story on this site. View the thread timeline for more context on this post.

But there’s more to any cafeteria than the serving line, and Sprig’s app offers no photograph of that other part. This is the Amazon move: absolute obfuscation of labor and logistics behind a friendly buy button. The experience for a Sprig customer is super convenient, almost magical; the experience for a chef or courier…? We don’t know. We don’t get to know. We’re just here to press the button.

This post is part of the thread: Technology & Society - an ongoing story on this site. View the thread timeline for more context on this post.

All of these stories are really interesting, and I highly recommend all of them, but this one stuck out to me. .io is an extremely popular domain name, and while I had heard about the controversy surrounding the use of the .ly TLD, there wasn’t any similar outrage abou the rise of .io. Many of the interesting TLDs are tied to countries, and .io is tied to the British Indian Ocean Territories, a collection of islands that were straight up stolen from the people who lived there so Great Britain and the United States could use them for a military base.

This post is part of the thread: Technology & Society - an ongoing story on this site. View the thread timeline for more context on this post.

Recursive Closures in PHP

I don’t know how often this comes up, but I recently needed to create a one-off recursive function. Here’s how I did it in PHP.

In this case, I had a set of items that were both nested and could be disabled at any level. So you could have a 3 widgets, all of a type “useful”, and all of the “useful” level widgets were then grouped by “kind”.1 Represented visually something like this:

         "kind"
          /
       "type"
   /     |     
widget widget widget

(Insofar as that graph has any meaning to anyone.)

Imagine this extending outwards, so there were many “types”, each with 2 or 3 widgets, and each “kind” then has 2 or 3 “types”. If any “type” has no widgets, it too gets disabled; same for “kind.” And obviously, the total universe of things has many kinds.

My problem was that these items could be disabled at any time, at any level, and when that happens, it and all of its “children” needed to be removed. Given our particular data structure, this turned into a 3 step process, but the first was to check for deactivated items.

So we need to go through each item, and check that it is both active (as per the dates set) as well as has children (except for the widget level). Ultimately, we needed to write a function that’s used in this one context.

The obvious solution is to just create a method that has a name that could be called, which is certainly doable but not really necessary if you have a very small method that’s only used once.

Another option is to use a closure. In JavaScript, it’s pretty easy to write one of these, as the variables within the function’s scope are accessible when the function is run:

var widgets = [...arrayOfWidgets];
var remove = function(widgetId) {
    widgets[widgetId].getChildWidgetIds().forEach(function(childWidgetId) {
        // `remove` is defined and accessible
        // at the time this is called
        remove(widgets[childWidgetId]);
    });

    delete widgets[$pageId];
};

remove(widgets[pageId]);

But we can’t do this as directly in PHP, because we don’t have closure scoping, and its closest equivalent, the use statement will throw an error if the variable hasn’t been defined when it’s made available to the closure at runtime. In order to get around this, we need to pass the name of the variable by reference:

$widgets = [...arrayOfWidgets];
$remove = function($widgetId) use (&$widgets, &$remove) {
    foreach ($widgets[$widgetId]->getChildWidgetIds() as $childWidgetId) {
        $remove($widgets[$childWidgetId]);
    }

    unset($widgets[$widgetId]);
};

$remove($widgets[widgetId]);

This makes the $remove variable function kind of like JavaScript’s closure scoping. At the time the closure is defined, the reference is to the value of a variable that doesn’t exist yet. When the closure is executed, the reference will be the closure assigned to that variable.2 You’re using the same variable within the closure as outside. This way, the closure can use and call itself recursively, until it’s done what it needs to do.

And that’s how you do recursive closures in PHP.

Just note one thing: with XDebug turn on, the stack depth is limited to 200, and it will error out if it goes deeper than that. You can increase it, obviously, in your php.ini settings; otherwise, PHP’s max stack depth is limited by its memory allocation at runtime, generally speaking. On the other hand, JavaScript’s max stack depth varies by browser and implementation.


  1. Specifics redacted to protect the guilty. 

  2. Which, curiously, is an object in PHP, with the magic method __invoke defined as the closure. 

This is not only a super-interesting story, but a great example of how culture and code are inextricably intertwined.

This post is part of the thread: Technology & Society - an ongoing story on this site. View the thread timeline for more context on this post.

This article is fan-fucking-tastic.

tw/cw: racism.

For all our convictions in the democratic and egalitarian potential of technology and the Internet, someway, somehow, we still end up reinscribing all the same problems found in “meat space.” Or sometimes, as this study suggests, making them worse.

This post is part of the thread: Technology & Society - an ongoing story on this site. View the thread timeline for more context on this post.

But much of what Jose [CEO of Knewton] says, at least to the media, is the opposite. No responsible educator or parent should adopt a product—even if it is free—from a company whose CEO describes it as a “robot tutor in the sky that can semi-read your mind” and give you content “proven most effective for people like you every single time.” I’m sorry, but this sort of quasi-mystical garbage debases the very notion of education and harms Knewton’s brand in the process.

There’s a pretty direct line to trace between Backbone’s inheritance model and the inclusion of class in ES6. This is a path we’re going to regret.

Three years later, Backbone exploded and had an .extend() method that mimicked class inheritance, including all its nastiest features such as brittle object hierarchies. That’s when all hell broke loose.

Question about WP-API best practices: Two plugins built by the same developer; should they use a shared vendor prefix? How would this impact index discoverability?