<div class="gmail_quote">On Sun, Apr 26, 2009 at 8:03 AM, Vladimir Sedach <span dir="ltr"><<a href="mailto:vsedach@gmail.com">vsedach@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Hi Red,<br>
<div class="im"><br>
> I have modified the behavior of keywords found in Parenscript source to be<br>
> parsed into (PS-QUOTE keyword) instead of (JS-VARIABLE keyword).<br>
<br>
</div>The current behavior is (ps::compile-parenscript-form :baz) => :baz<br>
(there's no quoting involved). The printer then outputs keyword<br>
symbols as strings, since this is the closest analogue (a<br>
self-evaluating object) to keywords among the native JavaScript<br>
objects.</blockquote><div class="im"><br>It appears that I had an old version.  I was using the darcs repo instead of the git repo.  There must have been a lot of changes as of August! (ps:ps :foo) used to output a variable reference to foo.<br>
<br>Nonetheless, here is a bug with the current implementation:<br><br>CL-USER> <br>(setf (ps:PS-PACKAGE-PREFIX :cl-user) "CL_USER_")<br>CL-USER> (ps:ps                                                                                                                                                                                                    <br>
           (let* ((some-prop 'foo-sym)                                                                                               <br>                  (my-object (ps:create 'foo-sym "value!")))                                                                                    <br>
             (slot-value my-object 'foo-sym)))                                                                                            <br>             <br>"var CL_USER_someProp = 'foo-sym';                                                                                                            <br>
var CL_USER_myObject = { 'foo-sym' : 'value!' };                                                                                  <br>CL_USER_myObject.CL_USER_fooSym;" <br><br>The expected behavior would be for the (create ...) form to reference the same value as the (slot-value ...) form.<br>
<br>If there were any sort of Parenscript runtime, it would be easy to make a data structure for symbols.  For example, the above code could translate to something like...<br><br>function Symbol(string, prefix) {<br>  this.string = string;<br>
  this.prefix = prefix;<br>  // .. add to symbol table, etc.<br>}<br>Symbol.prototype.toString = function() { if (this.prefix) return this.prefix + "::" + this.string; else return this.string; }<br>var someProp_symbol = new Symbol("someProp", "CL_USER");<br>
<br>var CL_USER_someProp = someProp_symbol;                                                                                                           
<br>
var CL_USER_myObject = { someProp_symbol : 'value!'
};                                                                                 
<br>
CL_USER_myObject[someProp_symbol];<br><br>This would differentiate symbols and strings, and it would result in pointer comparisons between symbols, just as in lisp.<br><br>I understand the current approach is to avoid any runtime, but the runtime solution does seem like less of a hack in the end.<br>
<br>
> This seems<br>
> to make more sense because in Lisp, evaluating a keyword yields the keyword<br>
> itself rather than the value bound to it.  As a result, the ability to paass<br>
> keyword arguments to functions is now restored.<br>
><br>
> CL-USER> (ps:ps (foo "bar" :quix "quo" :etc "etc..."))<br>
> "foo('bar', { quix : 'quo', etc : 'etc...' });"<br>
><br>
> Whereas this used to yield foo('bar', quix, 'quo', etc, 'etc...')<br>
<br>
</div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">This is actually a fix to keyword argument handling: previously the PS<br>
lambda-list handling code assumed that whenever it encountered a<br>
keyword in the arglist of a function, it was the beginning of the<br>
keyword portion of the lambda list, and started making the object at<br>
that point. This of course may not be the case if you are trying to<br>
use keywords as arguments to a function. With keywords compiled to<br>
strings, you get self-evaluating objects and can do keyword handling<br>
in the function body at runtime (which is what the current code does).</blockquote><div><br>I see the latest implementation now processes keyword arguments differently, eliminating the old hash table approach.  This seems like an okay solution, but I suspect it adds a a little overhead for each call to a function with keyword arguments.<br>
<br>I also noticed a bug that resulted in improper handling of the following case:<br>(ps:ps                                                                                                                                                                                                    <br>
           (defun hello-world (&key ((my-name-key my-name)))                                                     <br>             (print "hello, " + my-name))                                                                               <br>
           (hello-world 'my-name-key "fred"))<br>                                                                                                                                                       <br>"function CL_USER_helloWorld() {                                                                                                                                                                                   <br>
    var CL_USER_myName;                                                                                                                                              <br>    var _js54 = arguments.length;                                                                                                                            <br>
    for (var n52 = 0; n52 < _js54; n52 += 2) {                                                                                <br>        switch (arguments[n52]) {                                                                                   <br>
        case CL_USER_myNameKey:                                                                                                        <br>            {                                                                                                                              <br>
                CL_USER_myName = arguments[n52 + 1];                                                                             <br>            };                                                                                                                                                                                                     <br>
        };                                                                                                                                                                                                         <br>    };                                                                                                                                                                                                             <br>
    if (CL_USER_myName === undefined) {                                                                                                      <br>        CL_USER_myName = null;                                                                                                     <br>
    };                                                                                                              <br>    print('hello, ', plus, CL_USER_myName);                                                                                                                                                                        <br>
};                                                                                                                                                                                                                 <br>CL_USER_helloWorld('my-name-key', 'fred');"<br>
<br>the javascript should really use the following case:   case 'myNameKey' instead of case CL_USER_myNameKey.  a patch is attached<br><br><br>All the best,<br>Red<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
<br>
Thanks,<br>
<font color="#888888">Vladimir<br>
</font><div class="im"><br>
> In general, symbols occupy a strange place in Parenscript.  Javascript has<br>
> no analogue of Lisp symbols, so there is no sensible translation of symbols<br>
> that works for everyone.  Nonetheless, quoted symbols are used in many<br>
> Parenscript macros to fake having real symbols in javascript.  We could<br>
> build in the ability to translate symbols to some javascript form, e.g.<br>
><br>
> (ps:ps (make-instance 'animal)) =>  makeInstance( symbolTable["ANIMAL"] )<br>
><br>
> The latter part of this post is just food for thought.  I will go ahead and<br>
> commit the patch for the former part of this post unless someone objects.<br>
><br>
> Red<br>
><br>
</div><div><div></div><div class="h5">> _______________________________________________<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>
><br>
<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>
</div></div></blockquote></div><br>