Deferred Statements

Tags:

Hier ist ein Feature, das ich gerne in PHP hätte: Deferred Statements (à la Go).

Mittels des defer Schlüsswortes können Statements auf einen Stack (LIFO; last in, first out) geworfen werden, welcher abgearbeitet wird, sobald eine Funktion verlassen wird.

Aus ...

<?php
function test() {
    defer echo 'bai';
    defer echo 'thx';
    echo 'k';
}

... wird ...

<?php
function test() {
    echo 'k';
    echo 'thx';
    echo 'bai';
}

Der Nutzen liegt darin, dass man Clean-Up Code direkt dort schreiben kann, wo der Müll anfällt. Ein Beispiel:

<?php
function f($a, $b) {
    $fa = fopen($a, 'r');
    if (!$fa) {
        throw new InvalidArgumentException('...');
    }
    defer fclose($fa);

    $fb = fopen($a, 'w');
    if (!$fb) {
        throw new InvalidArgumentException('...');
    }
    defer fclose($fb);

    $tmpFile = tempnam('/tmp', 'log');
    if (!$tmpFile) {
        throw new LoginException('...');
    }
    defer unlink($tmpFile);

    // do stuff ...
}

... wird zu ...

<?php
function f($a, $b) {
    $fa = fopen($a, 'r');
    if (!$fa) {
        throw new InvalidArgumentException('...');
    }

    $fb = fopen($a, 'w');
    if (!$fb) {
        fclose($fa);
        throw new InvalidArgumentException('...');
    }

    $tmpFile = tempnam('/tmp', 'log');
    if (!$tmpFile) {
        fclose($fb);
        fclose($fa);
        throw new LoginException('...');
    }

    // do stuff ...

    unlink($tmpFile);
    fclose($fb);
    fclose($fa);
}

Egal was nach dem Öffnen/Erstellen der Dateien passiert, sie werden auf jeden Fall geschlossen/entfernt werden. Ausserdem ist die Logik zum Schliessen/Löschen nun direkt bei der zum Öffnen/Erstellen. Das macht den Code übersichtlicher.

defer sollte natürlich auch mit selbstaufrufenden Funktionen klappen.

<?php
function inc($i) {
    defer function() use (&$i) {
        $i += 5;
    }();

    $i *= 10;
    return $i;
}

Der Rückgabewert von inc(2) sollte 25 sein.

Leider habe ich keine Anhung was der Overhead bezüglich Speicher und Performance wäre. Es müsste ja für jeden Funktionsaufruf ein Stack (oder ein Pointer zu einem) gespeichert werden, oder?! Vielleicht könnte der Code aber auch schon beim Kompilieren in den Opcode optimiert werden, so dass es gar keinen Stack braucht...

Ähnliche Artikel

Kommentare