Scriptor / pharen

Lisp to PHP Compiler
http://pharen.org
BSD 3-Clause "New" or "Revised" License
218 stars 31 forks source link

Plambda #42

Closed francescoagati closed 12 years ago

francescoagati commented 12 years ago

this pull request add support for php 5.3 closure with this form:

(def x 100)
(def y 100)
(def sum (plambda (a b) (+ a b x y)))
(def sum3 (plambda (a b) (+ a b)))

a closure is callable in this form (like variable string that is referred to a function): ($sum 1 2)

bind of variables inside the closure is made from pharen scope so this form

(def x 100)
(def y 100)
(def sum (plambda (a b) (+ a b x y)))

is compiled in php

$__scope_id = Lexical::init_closure("plambda", 129);
$x = 100;
Lexical::bind_lexing("plambda", 129, '$x', $x);
$y = 100;
Lexical::bind_lexing("plambda", 129, '$y', $y);
$sum = function ($a, $b){
    $x = Lexical::get_lexical_binding('plambda', 129, '$x', isset($__closure_id)?$__closure_id:0);;
    $y = Lexical::get_lexical_binding('plambda', 129, '$y', isset($__closure_id)?$__closure_id:0);;
    return ($a + $b + $x + $y);
}
Scriptor commented 12 years ago

Thanks Francesco, I'll take a closer look at it once I have a little more time.

For the long term, I'm unfortunately don't think it'd be possible to use plambda as a complete replacement for lambda. I think the following won't work, for example:

((plambda (x) (* 2 x)) 3)

Because PHP's anonymous functions can't be directly called like that. There might also be other issues where this won't work because it's embedding the actual function declaration directly into the code.

An alternative would be to look into using PHP's __invoke magic method. So the previous code would generate the following:

<?php
$__tmplambdafunc = new LambdaObject(function($x) {return 2 * $x});
$__tmplambdafunc(3); // Calls LambdaObject's __invoke() method

So basically, it involves wrapping the anonymous function into a LambdaObject (probably would use a better name) constructor, assigning it to a temporary variable, and passing the variable around. Then the object's invoke method would call the anonymous function we passed to it.

Otherwise, thank you very much for working on this. I think I could use this and build the LambdaObject stuff on top of it.

francescoagati commented 12 years ago

Hi Tamreen, also i think that plambda can't replace lambda function in pharen. I have made this pull request only for library that require the use of anonymous functions like underscore.php, slim, sliex...

Scriptor commented 12 years ago

Ah, that's a good point. Since Pharen's lambdas haven't returned actual functions up till now this will definitely be very useful.

francescoagati commented 12 years ago

exactly imagine underscore.php used with pharen and plambda


(defmacro und (list &body) '(-> (__ ~list) (chain) ~@body ))

(print-r   (und [1 2 3 4 5]          
    (select (plambda (n)  (< n 5)))
    (reject (plambda (n)  (== n 3)))
    (sortBy (plambda (n)  n))
    (value)))
Scriptor commented 12 years ago

Actually, in that example the select and reject calls can be done using Pharen's partially applied functions!


(print-r (und [1 2 3 4 5]
              (select (>= 5)) ; >= because the order is switched
              (reject (== 3))
              (sortBy (plambda (n) n))
              (value)))
Scriptor commented 12 years ago

There were some issues with a conflict and git acting strangely, however it was only related to a whitespace error. Otherwise everything in this has been committed.

Scriptor commented 12 years ago

Hey Francesco,

I just pushed up a change that refactors lambdas completely. They now use the PharenLambda class which implements the invoke method. This means that regular Pharen lambdas are now compatible with the rest of PHP!

For example:

(array-map 
    (lambda (x) (* 2 x))
    (arr [1 2 3]))

This will work now because lambdas return a PharenLambda object. Calling an object as a function results in PHP calling its __invoke magic method, which you can see here: https://github.com/Scriptor/pharen/blob/master/lib/sequence.php#L429

francescoagati commented 12 years ago

Nice work i really like this implementation. In this mode there is no difference between lambda pharen and lambda php

2012/9/11 Tamreen Khan notifications@github.com

Hey Francesco,

I just pushed up a change that refactors lambdas completely. They now use the PharenLambda class which implements the invoke method. This means that regular Pharen lambdas are now compatible with the rest of PHP!

For example:

(array-map (lambda (x) (* 2 x)) (arr [1 2 3]))

This will work now because lambdas return a PharenLambda object. Calling an object as a function results in PHP calling its __invoke magic method, which you can see here: https://github.com/Scriptor/pharen/blob/master/lib/sequence.php#L429

— Reply to this email directly or view it on GitHubhttps://github.com/Scriptor/pharen/pull/42#issuecomment-8469459.

girvo commented 12 years ago

I really dig that implementation too, it should make it quite easy to use certain PHP libraries now (Slim, and Idiorm) for some neat Lisp-y web-dev.

Josh Girvin

e. josh@jgirvin.com m. 0410 930 219

On Wednesday, 12 September 2012 at 1:04 PM, francesco agati wrote:

Nice work i really like this implementation. In this mode there is no
difference between lambda pharen and lambda php

2012/9/11 Tamreen Khan <notifications@github.com (mailto:notifications@github.com)>

Hey Francesco,

I just pushed up a change that refactors lambdas completely. They now use
the PharenLambda class which implements the invoke method. This means that
regular Pharen lambdas are now compatible with the rest of PHP!

For example:

(array-map
(lambda (x) (* 2 x))
(arr [1 2 3]))

This will work now because lambdas return a PharenLambda object. Calling
an object as a function results in PHP calling its __invoke magic method,
which you can see here:
https://github.com/Scriptor/pharen/blob/master/lib/sequence.php#L429


Reply to this email directly or view it on GitHubhttps://github.com/Scriptor/pharen/pull/42#issuecomment-8469459.

— Reply to this email directly or view it on GitHub (https://github.com/Scriptor/pharen/pull/42#issuecomment-8480535).