[parenscript-devel] Multiple value calls
Red Daly
reddaly at gmail.com
Sun Nov 1 20:41:16 UTC 2009
On Sun, Nov 1, 2009 at 9:50 AM, Daniel Gackle <danielgackle at gmail.com>wrote:
> It might help to use a PS special variable and make MULTIPLE-VALUE-BIND
> responsible for cleanup.
>
> (ps (defvar *mv* undefined))
>
> (defpsmacro values (main &rest additional)
> (with-ps-gensyms (mv)
> `(let ((,mv (list , at additional)))
> (when (defined *mv*)
> (setf *mv* ,mv))
> (return ,main))))
>
> (defpsmacro multiple-value-bind (vars expr &body body)
> `(let ((*mv* '()))
> (let ((,(car vars) ,expr))
> (destructuring-bind ,(cdr vars) *mv*
> , at body))))
>
> This works in the obvious cases. I'm not sure it handles Red's scenarios.
> Red, can you supply an example where this breaks?
>
The main case I am concerned about is dealing with non-parenscript functions
that will not manipulate the mv state. Something like the following would
break the above code:
(defun foo ()
(let ((my-callback (lambda (x) (values 1 10)))
(multiple-value-bind (a b)
(add-to-result my-callback 2)))
=>
// imagine this is a non-Parenscript function that we cannot manipulate with
the
// Parenscript compiler
function addToResult(callback, x) {
// returns the result of adding x to the result of calling the callback
return callback() + x;
}
function foo () {
var myCallback = function (x) {
if (MV !== undefined)
MV = [10];
return 1;
};
var old_MV = MV; // begin let
MV = null;
var a = addToResult(myCallback, 2);
var b = MV ? MV[0] : null;
// now b === 10 but it should be nil
// this is because addToResult did not reset MV
MV = old_MV; // end let
}
This is why I think you might need to identify the callee in another
special variable, and for emitted functions reset the MV_CALLEE variable
before returning (and maybe in other places?).
Red
>
> Daniel
>
> p.s. I took the easy way out of making VALUES always prepend RETURN, but
> once Vladimir bestows implicit RETURN upon us we can take that out ;)
>
>
> On Sat, Oct 31, 2009 at 9:53 PM, Red Daly <reddaly at gmail.com> wrote:
>
>> I apologize for sending the first half of this email in error earlier:
>>
>> On Sat, Oct 31, 2009 at 8:35 PM, Red Daly <reddaly at gmail.com> wrote:
>>
>>> Hi Parenscripters,
>>>
>>> As far as I can tell, multiple-value function calls are a unique feature
>>> of lisp. I would like the ability to perform multiple-value calls in
>>> Parenscript but I don't know if a sane solution exists or not.
>>>
>>> Can anyone come up with a scheme for returning multiple values that
>>> translates well to Javascript? Ideally such a scheme would not introduce
>>> much overhead for usual functions that do not use or return multiple values
>>> (though perhaps setting some sort of global MV flag might be inexpensive
>>> enough). Functions that return multiple values should also only appear to
>>> return a single value when called by a function that expects only one return
>>> value (including native javascript functions).
>>>
>>> (defun paren-mv-returner ()
>>> (return (values 1 2 3)))
>>>
>>> =>
>>>
>>>
>>> function parenMvReturner() {
>>> /* do some magic with the values 2 and 3 */
>>> return 1;
>>> }
>>>
>>> // one implementation might be
>>> var mv = undefined;
>>>
>>> function parenMvReturner() {
>>> mv = [2, 3];
>>> return 1;
>>> }
>>>
>>> // this scheme needs to adjust the return statement of every function so
>>> it might not be sufficient
>>> // consider this other function
>>>
>>> function parenMySingleReturner () {
>>> var x = parenMvReturner();
>>>
>> return x;
>> }
>>
>> // parenMySingleReturner() will appear to return multiple values unless it
>> modifies the mv value itself
>>
>> // correction:
>>
>> function parenMySingleReturner () {
>> var x = parenMvReturner();
>> mv = null;
>> return x;
>> }
>>
>> But it seems like this solution will fall apart for calls to native
>> Javascript functions over which we have no control. If we pass a
>> multiple-value returning function as an argument to a native function, the
>> native function will not perform the necessary mv-nulling when it returns.
>>
>> someForeignJavascriptFunction( someMVReturningFunction)
>>
>> will return whatever the someForeignJavascriptFunction should return, but
>> it will also appear to return the other values that someMVReturningFunction
>> set in the mv variable, since someForeignJavascriptFunction performs no
>> cleanup.
>>
>> Maybe this limitation can be avoided by having an mv-returning function A
>> set a global variable "mvFunctionReturner" equal to the function A and a
>> mv-receiver can check that mvFunctionReturner is set according to the
>> function it called expecting multiple values. Does this scheme miss any
>> cases?
>>
>> Anyway I have thought a little bit about this and I thought I would pass
>> it off to the rest of the Parenscripters as a thought experiment. Assume
>> you can do a lot more semantic analysis than Parenscript currently does and
>> transform the compiled source however you want. But any compiled functions
>> must still be able to be treated as normal Javascript functions and all and
>> only functions that should return multiple values appear to return them.
>>
>> Cheers,
>> Red
>>
>> _______________________________________________
>> parenscript-devel mailing list
>> parenscript-devel at common-lisp.net
>> http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
>>
>>
>
> _______________________________________________
> parenscript-devel mailing list
> parenscript-devel at common-lisp.net
> http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/parenscript-devel/attachments/20091101/b343d061/attachment.html>
More information about the parenscript-devel
mailing list