(I get bounced if the reply includes too much of prev thread, so am truncating to immediate predecessor.)<div><br></div><div><div>I think we should avoid <a href="http://foo.mv">foo.mv</a> and just pass the array as an implicit</div>
<div>arg (see below). First a couple responses:</div><div><br></div><div>< I tried it out in FF and CL-JS and arguments.callee always seems to</div><div>be the function object, even for lambdas. ></div><div><br></div>
<div>We may have crossed a wire here. When you said, "You can do that with</div><div>a global table instead of setting a property on the function object,"</div><div>I thought you had in mind a global table keyed by function *name*,</div>
<div>which is why I asked about lambdas since they have no names. JS won't</div><div>let you use a function object as a key so one would have to concoct</div><div>some naming scheme.</div><div><br></div><div>< In this second call to foo, <a href="http://foo.mv">foo.mv</a> is still the same multiple value array. ></div>
<div><br></div><div>Ok, I get it now. Interestingly, this is the stack problem all over</div><div>again. Foo.mv may not be global but it's global per-function, so it</div><div>fails to work when foo is in the stack more than once.</div>
<div><br></div><div>I still strongly favour your array-passing proposal - namely that</div><div>when compiling a MULTIPLE-VALUE-BIND, PS would pass an extra argument</div><div>in the function call: a mutable array to hold any extra return values;</div>
<div>and when compiling a VALUES, PS would generate code to check whether</div><div>that array was passed and populate it if so.</div><div><br></div><div>But I said something that I now believe to be false: that such an</div>
<div>implicit argument "couldn't very well go anywhere [other than the</div><div>first position] because of things like &REST". Maybe we can sneak it</div><div>into the last position without disturbing anybody else.</div>
<div><br></div><div>Let PS declare a global sentinel value:</div><div><br></div><div> var MV_SENTINEL = {}</div><div><br></div><div>This can't accidentally be equal to anything else so we can use it to</div><div>unambiguously indicate MV-ness; specifically, we can pass it to</div>
<div>indicate that the succeeding arg is an MV array. A form like:</div><div><br></div><div> (multiple-value-bind (x y) (foo a b)</div><div> ...body...)</div><div><br></div><div>could compile to something like:</div>
<div>
<br></div><div> var values = [];</div><div> x = foo(a, b, MV_SENTINEL, values);</div><div> if (values.length > 0) {</div><div> y = values[0];</div><div> }</div><div><br></div><div>And where the values are returned:</div>
<div><br></div><div> (defun foo (x y)</div><div> (values x y))</div><div><br></div><div>could compile to something like:</div><div><br></div><div> function foo (x, y) {</div><div> var values = (arguments[2] === MV_SENTINEL) ? arguments[3] : undefined;</div>
<div> if (values) {</div><div> values[0] = y;</div><div> }</div><div> return x;</div><div> }</div><div><br></div><div>This is clean and stack-friendly. Callers that don't care about MV</div><div>don't have to deal with it (non-PS functions in particular are </div>
<div>fine); callers that want MV take on implicit arguments to get it.</div><div>It's stateless and seems easy to implement. No try/finally and</div><div>no hacking callee or caller.</div><div><br></div><div>At first I thought this wouldn't work because it would collide with</div>
<div>&REST and &KEY, which already interpret the arguments list. But why</div><div>should it? It's PS that generates the code to bind arguments to &REST</div><div>and &KEY params. For functions that include both a VALUES and a</div>
<div>&REST/&KEY, PS can just generate slightly smarter code that checks for</div><div>MV_SENTINEL and, if it's present, avoids binding it or its successor</div><div>as part of &REST or &KEY.</div><div>
<br></div><div>Moreover, if it worked for MV, the sentinel idea could be used to tag</div><div>anything else we wanted into the call. Seems like that could be pretty</div><div>powerful.</div><div><br></div><div>Where does this break?</div>
<div><br></div><div>Daniel</div><div><br></div><div>p.s. There's also a way to communicate exactly how many return values</div><div>are desired, short-circuiting any computation that might be needed to</div><div>generate the full VALUES list. (I think this point is independent of</div>
<div>the above idea but I'll adapt the same examples.) Suppose we have:</div><div><br></div><div> (defun foo (x y)</div><div> (values x y (blah))</div><div><br></div><div>but a caller doesn't want that third return value:</div>
<div><br></div><div> (multiple-value-bind (x y) (foo a b)</div><div> ...body...)</div><div><br></div><div>The caller could signal how much it wants like this:</div><div><br></div><div> var values = [true]; // fill up to number of values desired, in this case 1</div>
<div> x = foo(a, b, MV_SENTINEL, values);</div><div> if (typeof values[0] !== undefined) {</div><div> y = values[0];</div><div> }</div><div><br></div><div>... and foo could do something like:</div><div><br></div><div>
function foo (x, y) {</div><div> var values = (arguments[2] === MV_SENTINEL) ? arguments[3] : undefined;</div><div> if (values) {</div><div> values[0] = values[0] ? y : undefined;</div><div> values[1] = values[1] ? blah() : undefined;</div>
<div> } </div><div> return x;</div><div> }</div><div><br></div><div><br></div><div><br></div><br><div class="gmail_quote">On Sat, Sep 1, 2012 at 3:48 PM, Vladimir Sedach <span dir="ltr"><<a href="mailto:vsedach@gmail.com" target="_blank">vsedach@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">> But could the compiled PS instead keep a global<br>
> RETURN_VALUES stack? i.e. a list of MV arrays that callers would<br>
> push/pop as appropriate? I haven't thought about how this might work<br>
> and it feels like it probably wouldn't, but I'd like to know why.<br>
<br>
</div>You're right that it would need to be a stack, hence the prev_mv<br>
variable in the code I posted previously. But you'd still need to<br>
associate the values with the function that returned them, and if you<br>
can do that by setting a property on the function object, why bother<br>
with global variables and tables that hold stacks? The former approach<br>
is less code.<br>
<div class="im"><br>
> I like the array-passing idea and agree that it probably needs to be<br>
> passed out of band - but can we state explicitly why? For example, why<br>
> can't we make it a hidden first argument (it couldn't very well go<br>
> anywhere else because of things like &REST) and make Parenscript smart<br>
> enough to add in the correct value for that hidden argument every<br>
> place that function is called (i.e. pass null if the extra return<br>
> values aren't to be bound, and an array to hold them if they are)?<br>
><br>
> One obvious drawback is that non-PS functions wouldn't be able to call<br>
> such a function normally; they'd have to know about the extra arg.<br>
> What other drawbacks are there?<br>
<br>
</div>You wouldn't be able to have calls to these functions before they're<br>
defined in your code.<br>
<div class="im"><br>
> I like this idea, because everyone in the JS world is so adamant that<br>
> one shouldn't mess with arguments.metablah (though arguments.callee<br>
> has got to be better than arguments.callee.caller). But how would it<br>
> work for lambdas?<br>
<br>
</div>I tried it out in FF and CL-JS and arguments.callee always seems to be<br>
the function object, even for lambdas.<br>
<div class="im"><br>
> Right. I don't follow your example here, though, so I wonder if you<br>
> can spell it out a bit further.<br>
<br>
</div>foo is a function that returns either one value or multiple values. We<br>
call foo expecting to receive multiple values. Now <a href="http://foo.mv" target="_blank">foo.mv</a> is set to<br>
the multiple value array. In the course of computation, foo calls bar,<br>
which does not care about multiple values. In this second call to foo,<br>
<a href="http://foo.mv" target="_blank">foo.mv</a> is still the same multiple value array. The second call to foo<br>
returns multiple values, so the multiple value array gets filled up.<br>
However, the first call to foo returns only one value. But because the<br>
multiple value array has been filled up, we get bogus multiple values.<br>
<span class="HOEnZb"><font color="#888888"><br>
Vladimir<br>
</font></span><div class="HOEnZb"><div class="h5"><br></div></div></blockquote></div></div>