< <meta charset="utf-8"><span class="Apple-style-span" style="font-family: arial, sans-serif; font-size: 13px; border-collapse: collapse; ">why not just use an object as the only parameter ></span><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"><br>
</span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">That was the first way we did it, and we changed it for a good reason,</span></font></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">but my recollection of why is fuzzy. Does anybody remember?</span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">The archives of this list may be helpful here.</span></font></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"><br></span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">I believe the reason may have been that it places an undue burden</span></font></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">on the caller. If I want to write something like this...</span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"><br>
</span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"> (member item arr :key foo :test bar)</span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"><br>
</span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">... who is going to figure out that the last 4 arguments are really two</span></font></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">keyword params and bundle them into </span></font><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">{ key : foo, test : bar }?</span></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"><br></span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">You could make the caller do it:</span></font></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"><br></span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"> (member item arr (create :key foo :test bar))</span></font></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"><br></span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">... but then you lose interoperability with CL, and arguably dilute the</span></font></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">feature to the point where you might as well not have it, since it's</span></font></div><div>
<font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">easy enough to define a function that takes a js object as its last</span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">parameter and picks out the keys.</span></font></div>
<div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; "><br></span></div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">On the other hand, you could make PS do it by decreeing</span><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; "> that</span></div>
<div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">keywords in an arglist *always* identify keyword </span><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">params, but </span></div>
<div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">that breaks this:</span></div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; "><br>
</span></div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; "> (member :blah arr :key foo :test bar)</span></div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; "><br>
</span></div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">... which now generates member({blah : arr, key : foo, test : bar})</span></div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">instead of the desired member("blah", arr, {k</span><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">ey : foo, test : bar}).</span></div>
<div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">In other words, this option m</span><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">akes the semantics of keywords </span></div>
<div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">inconsistent in PS.</span></div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; "><br>
</span></div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">Another option is to make the PS compiler consider the signature</span></div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">of the function being called before it generates the code for the call.</span></div>
<div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">That complicates the compiler and IIRC is hard to get working in</span></div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">the general case (Vladimir can comment here).</span></div>
<div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; "><br></span></div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">So my recollection is that we settled on the existing method as the</span></div>
<div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">one that places no burden on either the caller or the callee (at the source</span></div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">level... obviously the JS that's generated for the callee is what does</span></div>
<div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">all the extra work), preserves the semantics of keywords, is closest</span></div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; ">to how CL does keyword args, and keeps the compiler simple.</span></div>
<div><span class="Apple-style-span" style="font-family: arial, sans-serif; border-collapse: collapse; "><br></span></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"><br>
</span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"><br></span></font></div><div><br><div class="gmail_quote">On Thu, Aug 5, 2010 at 2:47 PM, Nick Fitzgerald <span dir="ltr"><<a href="mailto:fitzgen@gmail.com">fitzgen@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">Ok, I just realized that I completely misread your original post. I thought you were proposing the removal of defaulting to null rather than leaving the value undefined.<div>
<br></div><div>Have you done any profiling to see if there is a reasonable difference between</div>
<div><br></div><div><div class="im"><div>"function foo() {</div><div> var a;</div><div> // ... pick out and assign keyword args ...</div><div> if (a === undefined) {</div><div> a = null;</div><div> };</div>
<div> return bar(a);</div>
<div>};"</div><div><br></div></div><div>and </div><div class="im"><div><br></div><div><div>"function foo() {</div><div> var a = null;</div><div> // ... pick out and assign keyword args ...</div><div> return bar(a);</div>
<div>
};"</div></div><div><br></div></div>?</div><div><br></div><div>I just ran this very naive test in Chromium:</div><div><br></div><div><font face="'courier new', monospace">var then = +new Date;</font></div>
<div><font face="'courier new', monospace">var i = 20000;</font></div><div><font face="'courier new', monospace">while (i--) {</font></div><div><font face="'courier new', monospace"> (function () {</font></div>
<div><font face="'courier new', monospace"> var a;</font></div><div class="im"><div><font face="'courier new', monospace"> if (a === undefined) a = null;</font></div>
</div><div><font face="'courier new', monospace"> }())</font></div><div><font face="'courier new', monospace">};</font></div><div><font face="'courier new', monospace">console.log(+new Date - then);</font></div>
<div><font face="'courier new', monospace"><br><font face="arial">Which logs 70 ms.</font></font></div><div><font face="'courier new', monospace"><br>
var then = +new Date;</font></div><div><font face="'courier new', monospace">var i = 20000;</font></div><div><font face="'courier new', monospace">while (i--) {</font></div>
<div><font face="'courier new', monospace"> (function () {</font></div><div><font face="'courier new', monospace"> var a = null;</font></div><div><font face="'courier new', monospace"> }())</font></div>
<div><font face="'courier new', monospace">};</font></div><div><font face="'courier new', monospace">console.log(+new Date - then);<br><br></font><div><br>
</div><div>This one logs 71 ms.</div><div><br></div><div>This has to have come up before, but why not just use an object as the only parameter and use it's keys as the keyword arguments? I just ran the same test for that, and when the keyword was missing I got 82 ms, but when it was available, I got 56.</div>
<div><br></div><div>I think using objects would make the generated code much more readable, which trumps speed in this case IMO given that the difference is so small and the high number of iterations being performed.</div>
<div><br></div><font color="#888888">_Nick_</font><div><div></div><div class="h5"><br><br>
<br><br><div class="gmail_quote">On Thu, Aug 5, 2010 at 1:24 PM, Daniel Gackle <span dir="ltr"><<a href="mailto:danielgackle@gmail.com" target="_blank">danielgackle@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Good point. I kept the null assignment for consistency with how PS does &optional<div>arguments. But this begs the question: why do we care about &optional</div><div>and &key arguments being set to null, as opposed to just leaving them undefined?</div>
<div>I'm trying to remember the reason... anybody?</div><div><br></div><div>Our experience has been that PS code works best if one treats null and undefined </div><div>as interchangeable. But that may be an artifact of running some of the same code</div>
<div>in CL as well, where there is no such distinction.</div><div><div></div><div><div><br></div><div><br><div class="gmail_quote">On Thu, Aug 5, 2010 at 1:51 PM, Nick Fitzgerald <span dir="ltr"><<a href="mailto:fitzgen@gmail.com" target="_blank">fitzgen@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">+1 from me but that doesn't mean too much.<div><br></div><div>No need to explicitly set them as `null`, because JS already has (the more semantic in this case) `undefined`.<br clear="all">
<br>_Nick_<br><br>
<br><br><div class="gmail_quote"><div><div></div><div>On Wed, Aug 4, 2010 at 12:30 PM, Daniel Gackle <span dir="ltr"><<a href="mailto:danielgackle@gmail.com" target="_blank">danielgackle@gmail.com</a>></span> wrote:<br>
</div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div></div><div>
The code that's generated for a keyword argument goes like this:<div><div><br></div><div><div>(ps (defun foo (&key a) (bar a))) => </div><div><br></div><div>(abbreviated for clarity):</div><div><br></div><div>
"function foo() {</div>
<div> var a;</div><div> // ... pick out and assign keyword args ...</div><div> if (a === undefined) {</div><div> a = null;</div><div> };</div><div> return bar(a);</div><div>};"</div></div></div>
<div>
<br></div><div>It seems to me that this could be made tighter as follows:</div><div><br></div><div><div>"function foo() {</div><div> var a = null;</div><div> // ... pick out and assign keyword args ...</div><div>
return bar(a);</div><div>};"</div></div><div><br></div><div>The only difference I can think of is when someone explicitly passes undefined</div><div>as a value for the argument, but that's an oxymoronic thing to do.</div>
<div><br></div><div>Can anyone think of a reason not to make this change? I like PS's keyword</div><div>arguments a lot, but the generated JS is bloated enough to make me wince.</div>
<br></div></div>_______________________________________________<br>
parenscript-devel mailing list<br>
<a href="mailto:parenscript-devel@common-lisp.net" target="_blank">parenscript-devel@common-lisp.net</a><br>
<a href="http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel" target="_blank">http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel</a><br>
<br></blockquote></div><br></div>
<br>_______________________________________________<br>
parenscript-devel mailing list<br>
<a href="mailto:parenscript-devel@common-lisp.net" target="_blank">parenscript-devel@common-lisp.net</a><br>
<a href="http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel" target="_blank">http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel</a><br>
<br></blockquote></div><br></div>
</div></div><br>_______________________________________________<br>
parenscript-devel mailing list<br>
<a href="mailto:parenscript-devel@common-lisp.net" target="_blank">parenscript-devel@common-lisp.net</a><br>
<a href="http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel" target="_blank">http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel</a><br>
<br></blockquote></div><br></div></div></div>
<br>_______________________________________________<br>
parenscript-devel mailing list<br>
<a href="mailto:parenscript-devel@common-lisp.net">parenscript-devel@common-lisp.net</a><br>
<a href="http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel" target="_blank">http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel</a><br>
<br></blockquote></div><br></div>