marcioAlmada / yay

Yay is a high level PHP preprocessor
https://github.com/marcioAlmada/yay
MIT License
572 stars 35 forks source link

Anonymous self-binding closure example? #34

Closed mpyw closed 7 years ago

mpyw commented 8 years ago

I have implemented anonymous recursion like this.

Source

<?php

macro ·recursion {
     selfbind ·closure()·f
} >> {
    current([
        $wrapper = function (...$args) use (&$wrapper, &$closure) {
            return $closure->bindTo($wrapper)(...$args);
        },
        $closure = ·f,
    ])
}

// Naive Fibonacci 
$format = "Processing x = %d\n";
var_dump(
    (selfbind function ($x) use ($format) {
        printf($format, $x);
        return $x < 3 ? 1 : $this($x - 1) + $this($x - 2);
    })(5)
);

Compiled

<?php

// Naive Fibonacci 
$format = "Processing x = %d\n";
var_dump(
    (current([
        $wrapper·cfcd208495d565ef66e7dff9f98764da = function (...$args·cfcd208495d565ef66e7dff9f98764da) use (&$wrapper·cfcd208495d565ef66e7dff9f98764da, &$closure·cfcd208495d565ef66e7dff9f98764da) {
            return $closure·cfcd208495d565ef66e7dff9f98764da->bindTo($wrapper·cfcd208495d565ef66e7dff9f98764da)(...$args·cfcd208495d565ef66e7dff9f98764da);
        },
        $closure·cfcd208495d565ef66e7dff9f98764da = function($x)use($format){printf($format, $x);
        return $x < 3 ? 1 : $this($x - 1) + $this($x - 2);
    },
    ]))(5)
);

Result

Processing x = 5
Processing x = 4
Processing x = 3
Processing x = 2
Processing x = 1
Processing x = 2
Processing x = 3
Processing x = 2
Processing x = 1
int(5)

However, it looks odd a little. Are there any better ways?

marcioAlmada commented 7 years ago

Sorry for the wait, I'm not having much time for this project.

Your example could have been implemented in other ways but this looks ok to me. Macros generally do look odd because nearly every self hosted language feature is a corner case of the host language, with the exception of really simple syntax sugar scenarios.

👍