On Sun, Jul 26, 2009 at 2:25 PM, Daniel Gackle
<danielgackle@gmail.com> wrote:
As I've posted here before, we depend on having a facility in PS for symbols that do *not* get translated to the JS identifier rules.
Could you please post an explicit example of why you need symbols that do not get translated according to normal symbol translation rules? I am in a different boat where my current libraries all expect keywords to translate with hypenated-to-camelcase rules. e.g.
(methcall :to-upper-case object)
Forms like that are all over my code (see
http://common-lisp.net/project/suave/ for a list of Parenscript projects). I do not use a quoted symbol in the current package because I require that the symbols be translated without a package prefix, since they keywords correspond to Javascript-native identifiers. This is my use case. What is yours?
The current compromise in PS -- treat keywords differently from non-keyword symbols -- seems like a reasonable tradeoff. If the inconsistency of keywords in slot-value is an issue, I'd rather see slot-value itself modified to preserve the difference between keywords and other symbols. (That would produce syntax errors in the case of keywords with hyphens in them, but there's a fix ready at hand, namely use a non-keyword symbol.)
I believe something like (slot-value object :key-with-hyphens) would properly translate to object['key-with-hyphens'], so there should not be any syntax errors for slot-value forms. For identifiers named by hyphenated keywords, you are correct.
The last time this subject came up, I promised to try replacing all of our symbols like '+ with keywords like :+ and see how it turned out. I meant to report back about this, but I don't think I did. We made the change, and it works fine. This allowed us to run against the latest PS. Unless I'm missing something, it looks like the proposed patch will break that.
The fundamental issue here is that the symbols in CL correspond to both identifiers and strings in JS. That means either we go with a one-to-many mapping (translating symbols to JS in more than one way) or translate all PS symbols to conform to the identifier rules. The latter is simpler but deprives PS of some expressiveness that we rely on. If we're going to have two different kinds of symbols in PS, the keyword/non-keyword distinction seems like the obvious choice, since that's CL's way of having two different kinds of symbols.
The fundamental issue is there is no ideal translation of a Parenscript symbol into a Javascript equivalent; we are dealing with a language mismatch. One solution is to translate symbols not to strings but to some other form that is more useful. The symbol :to-upper-case, for example, could be translated into:
intern('toUpperCase', 'to-upper-case', 'keyword');
function intern(jsstring, lispName, package) {
if (lookup symbol in table)
return looked up symbol;
else
return new PSSymbol(jsstring, lispName, package);
}
function PSSymbol(jsstring, lispName, package) {
this.jsstring = jsstring;
this.lispName = lispName;
this.package = package;
storeSymbol(this);
this.toString = function() { return this.jsstring; }
return this;
}
This avoids the one-to-many headache and preserves consistency of how to reference symbols (the toString() method is used to serialize a value for slot store, e.g. (slot-value object (intern 'toUpperCase' ...)) == (slot-value object 'toUpperCase')). Unfortunately this makes Parenscript more complex on the runtime end.
If we do not adopt this fancy, semantically superior translation scheme, I think we should stick to a consistent translator across all packages.
Best,
Red