Hello,
A new version of Parenscript has been released. This release comes with partial support for LOOP and DESTRUCTURING-BIND Common Lisp facilities (thanks to the efforts of Daniel Gackle and Scott Bell), much faster compilation speed, many bugfixes, real and efficient lexical scoping for all special forms that introduce bindings, as well as the ability to direct compiler output directly to a stream. One thing that has been removed is support for the dot symbol notation (ie - 'object.property' would be special cased into (slot-value object 'property) by the compiler) - this has been done to allow Parenscript code to be a useful target for code walkers designed for regular Lisp code. The consequence is that any code that relies on the dot notation will need to be changed to use non-opaque object slot access.
Thank you, Vladimir
Hi Vladimir,
It seems that the new parenscript horribly breaks tpd2.
The awful part of the business is changing from using elements.push etc. methods.
You seem to recommend to rewrite them as ((slot-value elements 'push) new-thing).
This is completely not at all related to Common Lisp syntax, which was supposedly the aim of this change, so I guess I am barking up the wrong end of the stick.
Should I wait for the reader macros before making the update?
Thanks for working on parenscript, it's good to see that it's improving.
And it's good to see that people are complaining about the new version not working with tpd2 as it shows that there are some users out there :-)
[...]
John Fremlin john@fremlin.org writes:
Hi Vladimir,
It seems that the new parenscript horribly breaks tpd2.
The awful part of the business is changing from using elements.push etc. methods.
You seem to recommend to rewrite them as ((slot-value elements 'push) new-thing).
This is completely not at all related to Common Lisp syntax, which was supposedly the aim of this change, so I guess I am barking up the wrong end of the stick.
Should I wait for the reader macros before making the update?
I've been tasked with re-adding the shorthand syntax to parenscript [0] in the symbol-syntax if you need these features. Right now it only does (.method ...) syntax, but sometime today or tomorrow I'll have (foo.bar.baz) expanding to ((slot-value foo 'bar) 'baz). I'm not sure whether it is worthwhile keeping foo[bar] syntax; (aref foo bar) is not particularly less convenient.
If upstream will not accept the changes this will be maintained as part of UCW again (probably renamed to avoid conflicts; since ps no longer uses the js package we'll move back there). I'll try to keep up with merges from upstream and whatnot as well.
[0] http://git.hcoop.net/?p=clinton/parenscript.git;a=summary
I use a syntax like this:
(methcall 't-string object param1 parm2 param3)
=> object.tString(param1, param2, param3).
It's basically a shortcut for ((slot-object ...) param1 ...) but I have found it to be more readable.
When I need a long string of dot-separated identifiers (e.g. foo.bar.viz) I use (slot-value foo 'bar 'viz) => foo.bar.viz
What other syntax do people use to deal with dotted objects in Parenscript? I try to avoid them if possible, perhaps because the current syntax is verbose.
Red
On Tue, Oct 6, 2009 at 9:42 AM, Clinton Ebadi clinton@unknownlamer.orgwrote:
John Fremlin john@fremlin.org writes:
Hi Vladimir,
It seems that the new parenscript horribly breaks tpd2.
The awful part of the business is changing from using elements.push etc. methods.
You seem to recommend to rewrite them as ((slot-value elements 'push) new-thing).
This is completely not at all related to Common Lisp syntax, which was supposedly the aim of this change, so I guess I am barking up the wrong end of the stick.
Should I wait for the reader macros before making the update?
I've been tasked with re-adding the shorthand syntax to parenscript [0] in the symbol-syntax if you need these features. Right now it only does (.method ...) syntax, but sometime today or tomorrow I'll have (foo.bar.baz) expanding to ((slot-value foo 'bar) 'baz). I'm not sure whether it is worthwhile keeping foo[bar] syntax; (aref foo bar) is not particularly less convenient.
If upstream will not accept the changes this will be maintained as part of UCW again (probably renamed to avoid conflicts; since ps no longer uses the js package we'll move back there). I'll try to keep up with merges from upstream and whatnot as well.
[0] http://git.hcoop.net/?p=clinton/parenscript.git;a=summary
<captain_krunk> ntk is currently using "telnet fyodor 25" to send email
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
Red Daly reddaly@gmail.com writes:
(methcall 't-string object param1 parm2 param3)
=> object.tString(param1, param2, param3).
It's basically a shortcut for ((slot-object ...) param1 ...) but I have found it to be more readable.
This makes sense.
How about a version that doesn't evaluate the method argument? So (meth t-string object param1 parm2 param3) => object.tString(param1, param2, param3)
When I need a long string of dot-separated identifiers (e.g. foo.bar.viz) I use (slot-value foo 'bar 'viz) => foo.bar.viz
This is obviously an abuse of slot-value . . . how about something similar but which doesn't evaluate its arguments (sv foo bar viz) => foo.bar.viz
[...]
Not to pick on anybody but Common Lisp is not scheme!
((slot-value list 'push) new-element) is not Common Lisp. If anything it should be (funcall (slot-value list 'push) new-element)
I'm not sure that (slot-value ...) is even a good idea, because JavaScript's objects can have new slots added willy nilly.
How about two new forms? One for the current use of slot-value, and one for method calls?
How about (object-path a b c d) for a.b.c.d?
Of course, don't call it object-path but something really short, like 'o'. Then we wouldn't need a reader macro :-)
Someone suggested using @ for method calls. Is that available already?
[...]
I've been tasked with re-adding the shorthand syntax to parenscript [0] in the symbol-syntax if you need these features. Right now it only does (.method ...) syntax, but sometime today or tomorrow I'll have (foo.bar.baz) expanding to ((slot-value foo 'bar) 'baz). I'm not sure whether it is worthwhile keeping foo[bar] syntax; (aref foo bar) is not particularly less convenient.
foo.bar.baz expanding to (slot-value (slot-value foo 'bar) 'baz) is a bit weird. These are not really slots, as the aref example suggests . . . maybe gethash?
On the other hand, slot-value is a good idiomatic conversion, so perhaps it's better to let this sleeping dog lie
[...]
((slot-value list 'push) new-element) is not Common Lisp. If anything it should be (funcall (slot-value list 'push) new-element)
Funcall is already there; I'm going to take this as a vote to remove the Scheme-like function calling convention (I also think it's a good idea).
I'm not sure that (slot-value ...) is even a good idea, because JavaScript's objects can have new slots added willy nilly.
How about two new forms? One for the current use of slot-value, and one for method calls?
Something like slot-value is needed (see below about @), but why is everyone obsessing about special syntax for method calls? JavaScript does not have any special syntax for method calls aside from the arglist curly braces (which is just the JS equivalent of funcall).
How about (object-path a b c d) for a.b.c.d?
Of course, don't call it object-path but something really short, like 'o'. Then we wouldn't need a reader macro :-)
Someone suggested using @ for method calls. Is that available already?
Yes. I'm going to interpret this as a vote to remove 'slot-value' and keep just the '@' because 'slot-value' does not behave anything like its CL equivalent. I think this idea has some merit.
I think the problem you are expressing John is that people have too many ways to do things in Parenscript which basically wind up as syntactic sugar. I like the sentiment and I'm going to put it into practice.
Vladimir
[...]
I've been tasked with re-adding the shorthand syntax to parenscript [0] in the symbol-syntax if you need these features. Right now it only does (.method ...) syntax, but sometime today or tomorrow I'll have (foo.bar.baz) expanding to ((slot-value foo 'bar) 'baz). I'm not sure whether it is worthwhile keeping foo[bar] syntax; (aref foo bar) is not particularly less convenient.
foo.bar.baz expanding to (slot-value (slot-value foo 'bar) 'baz) is a bit weird. These are not really slots, as the aref example suggests . . . maybe gethash?
On the other hand, slot-value is a good idiomatic conversion, so perhaps it's better to let this sleeping dog lie
[...]
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
Vladimir Sedach vsedach@gmail.com writes: [...]
How about two new forms? One for the current use of slot-value, and one for method calls?
Something like slot-value is needed (see below about @), but why is everyone obsessing about special syntax for method calls? JavaScript does not have any special syntax for method calls aside from the arglist curly braces (which is just the JS equivalent of funcall).
The reason is that method calls are often used and funcall is rather long-winded. I use ! for a method call, e.g. (dolist (script (! (element get-elements-by-tag-name) "script")) (eval (~ script inner-h-t-m-l)))
Here's the mess
(ps:defpsmacro ~ (&rest object-paths) (let ((slot (first (last object-paths))) (object-paths (butlast object-paths))) (cond ((not object-paths) slot) (t `(slot-value ,(if (rest object-paths) `(~ ,@object-paths) (first object-paths)) ',slot)))))
(ps:defpsmacro ! ((&rest object-paths) &rest args ) `(funcall (~ ,@object-paths) ,@args))
Though I note that ~ is actually just a worse way of doing @, which is already in parenscript.
[...]
Yes. I'm going to interpret this as a vote to remove 'slot-value' and keep just the '@' because 'slot-value' does not behave anything like its CL equivalent. I think this idea has some merit.
I'm not sure there's a need to remove it . . . maybe deprecate it?
It's a bit annoying to have to keep rewriting all one's parenscript code :-)
I think the problem you are expressing John is that people have too many ways to do things in Parenscript which basically wind up as syntactic sugar. I like the sentiment and I'm going to put it into practice.
My idea is that if you are going to push to make parenscript be more common lispy, then you should decide carefully on the proper way to do it, because if you have to change it later everybody's parenscript code has to be redone (again).
PS. I've updated teepeedee2 to the new parenscript. Any chance of getting a link in the frameworks section of the parenscript webpage? (I wish to persuade people to take the tpd2 webapp framework stuff a bit more seriously rather than assuming it's just a webserver :-)
[...]
Hi Clinton,
As I posted previously, I'm strongly opposed to the presence of dot syntax in Parenscript. If UCW really needs the dot syntax (I don't see any reason for that, but that's a UCW issue), you are better off writing a code-walker that would do the dot transformation on the symbols it encounters, rather than forking Parenscript.
Vladimir
On Tue, Oct 6, 2009 at 10:42 AM, Clinton Ebadi clinton@unknownlamer.org wrote:
John Fremlin john@fremlin.org writes:
Hi Vladimir,
It seems that the new parenscript horribly breaks tpd2.
The awful part of the business is changing from using elements.push etc. methods.
You seem to recommend to rewrite them as ((slot-value elements 'push) new-thing).
This is completely not at all related to Common Lisp syntax, which was supposedly the aim of this change, so I guess I am barking up the wrong end of the stick.
Should I wait for the reader macros before making the update?
I've been tasked with re-adding the shorthand syntax to parenscript [0] in the symbol-syntax if you need these features. Right now it only does (.method ...) syntax, but sometime today or tomorrow I'll have (foo.bar.baz) expanding to ((slot-value foo 'bar) 'baz). I'm not sure whether it is worthwhile keeping foo[bar] syntax; (aref foo bar) is not particularly less convenient.
If upstream will not accept the changes this will be maintained as part of UCW again (probably renamed to avoid conflicts; since ps no longer uses the js package we'll move back there). I'll try to keep up with merges from upstream and whatnot as well.
[0] http://git.hcoop.net/?p=clinton/parenscript.git;a=summary
<captain_krunk> ntk is currently using "telnet fyodor 25" to send email
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
Vladimir Sedach vsedach@gmail.com writes:
Hi Clinton,
As I posted previously, I'm strongly opposed to the presence of dot syntax in Parenscript. If UCW really needs the dot syntax (I don't see any reason for that, but that's a UCW issue), you are better off writing a code-walker that would do the dot transformation on the symbols it encounters, rather than forking Parenscript.
Your changes break all extant parenscript code. Parenscript has been around for four years and been stable for almost as long; it is not ok to break compatibility in mature libraries without either a new major version or name.
And even then things should only be changed if they provide a net benefit; removing dot-syntax from parenscript makes one of the most common javascript idioms cumbersome and verbose. Parenscript is /not/ Common Lisp -- it is entirely acceptable for it to have slightly different syntax.
What if there were a special form to explicitly allow a Lisp symbol through unmodified? This would be a bit different than the current |:foo| syntax (the :-escape applies to whatever portion of the split symbol it prefixes e.g. |:foo.Bar.:baaZ| -> foo.bar.baaZ).
((slot-value list 'push) new-element) is not Common Lisp. If anything it should be (funcall (slot-value list 'push) new-element)
Funcall is already there; I'm going to take this as a vote to remove the Scheme-like function calling convention (I also think it's a good idea).
Why? Javascript has more in common with Scheme than Common Lisp and the ((...) ...) syntax maps onto js syntax that is perfectly acceptable. A (contrived) example:
(defun make-adder (x) (return (lambda (y) (return (+ x y))))) ((make-adder 3) 5)
Requiring `funcall' would artificially restrict parenscript syntax. If anything having `funcall' at all is harmful; Javascript has a unified variable and function namespace so it serves no purpose.
I'm not sure that (slot-value ...) is even a good idea, because JavaScript's objects can have new slots added willy nilly.
How about two new forms? One for the current use of slot-value, and one for method calls?
Something like slot-value is needed (see below about @), but why is everyone obsessing about special syntax for method calls? JavaScript does not have any special syntax for method calls aside from the arglist curly braces (which is just the JS equivalent of funcall).
@ would be an acceptable special form for method calling, but I think the `chain' macro is closer to what it should do (I don't see much of an advantage to merging foo.bar/foo[bar] syntax; breakout to an explicit (slot-value ...) or (aref ...) when foo[bar] is desired is not an onerous burden when weighed against making all chained method calls more awkward).
Prefix syntax makes method calling a bit awkward and (.method ...) syntax makes method calls a bit more CLOSish in appearance. I am neutral on its value, but since parenscript has supported this for years and a lot of code is relying on it the cost of removing it is high.
Someone suggested using @ for method calls. Is that available already?
Yes. I'm going to interpret this as a vote to remove 'slot-value' and keep just the '@' because 'slot-value' does not behave anything like its CL equivalent. I think this idea has some merit.
Parenscriot `slot-value' performs more or less identically to Lisp `slot-value' -- if CLOS were prototype based. Javascript objects are not Lisp objects and people writing parenscript should know that. Personally I'd rename `slot-value' to `slot-ref', but this is just an aesthetic issue (breaking compatibility being undesirable as I mentioned before).
And even then things should only be changed if they provide a net benefit; removing dot-syntax from parenscript makes one of the most common javascript idioms cumbersome and verbose. Parenscript is /not/ Common Lisp -- it is entirely acceptable for it to have slightly different syntax.
PS is a translator from Common Lisp to JavaScript. The project stopped being an s-expression syntax for JS quite a while ago.
What if there were a special form to explicitly allow a Lisp symbol through unmodified? This would be a bit different than the current |:foo| syntax (the :-escape applies to whatever portion of the split symbol it prefixes e.g. |:foo.Bar.:baaZ| -> foo.bar.baaZ).
This isn't the issue with foo.bar syntax. The problem is that putting foo.bar in Parenscript (as opposed to outside the PS compiler) fails in the presence of symbol macros for either foo or bar. Even ignoring other possible undesirable consequences, this makes it a big pain to implement 'let' with real lexical scoping efficiently or readably, and makes code inspection by conventional tools impossible. The whole issue is centered around symbol identity and the abuse of symbol names.
Prefix syntax makes method calling a bit awkward and (.method ...) syntax makes method calls a bit more CLOSish in appearance. I am neutral on its value, but since parenscript has supported this for years and a lot of code is relying on it the cost of removing it is high.
The dot syntax is a design mistake that makes what should be trivial code transformation hard. This has consequences for both the PS compiler (keeping it would make it more complicated than it needs to be) and just as importantly as for the code being compiled. If someone wants to upgrade their project to use the latest version of Parenscript, I think it's ok to ask them to fix what are essentially bugs in their code. The only regrettable thing is that these bugs were encouraged by previous versions of Parenscript as desirable programming style.
Vladimir
Vladimir Sedach wrote:
PS is a translator from Common Lisp to JavaScript. The project stopped being an s-expression syntax for JS quite a while ago.
That, for me atleast, is great news. I had been wondering for sometime which direction Parenscript was headed in, and have had a CL->JS compiler high on my wishlist.
Do you plan to make it a complete ANSI CL to JS compiler? (Complete being whatever's allowed within the limits of the browser's security model e.g. file and socket operations might not work)
Does PS aim to become for CL like gwt is for Java? e.g. generating JS which works correctly across all the major browsers.
These are a few questions I have had for sometime -- I would really like to see something akin to gwt for CL.
Chaitanya
What if there were a special form to explicitly allow a Lisp symbol through unmodified? This would be a bit different than the current |:foo| syntax (the :-escape applies to whatever portion of the split symbol it prefixes e.g. |:foo.Bar.:baaZ| -> foo.bar.baaZ).
This isn't the issue with foo.bar syntax. The problem is that putting foo.bar in Parenscript (as opposed to outside the PS compiler) fails in the presence of symbol macros for either foo or bar. Even ignoring other possible undesirable consequences, this makes it a big pain to implement 'let' with real lexical scoping efficiently or readably, and makes code inspection by conventional tools impossible. The whole issue is centered around symbol identity and the abuse of symbol names.
Prefix syntax makes method calling a bit awkward and (.method ...) syntax makes method calls a bit more CLOSish in appearance. I am neutral on its value, but since parenscript has supported this for years and a lot of code is relying on it the cost of removing it is high.
The dot syntax is a design mistake that makes what should be trivial code transformation hard. This has consequences for both the PS compiler (keeping it would make it more complicated than it needs to be) and just as importantly as for the code being compiled. If someone wants to upgrade their project to use the latest version of Parenscript, I think it's ok to ask them to fix what are essentially bugs in their code. The only regrettable thing is that these bugs were encouraged by previous versions of Parenscript as desirable programming style.
Vladimir
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
It would be hard to make PS a complete CL without giving up on producing efficient and readable JS, which is what makes PS so suitable for production systems.
You can get close, though. We write most of our app in a subset of CL that compiles to PS using a bunch of macros we wrote. I've been toying with the idea of open-sourcing these. The problem is that, while they work great for us, they're not perfect for the general case, which is what PS really needs to address.
An example of the impedance mismatch is how to implement car, cdr, etc. You could roll your own lists, but these would be slow and hard to debug. So we map CL lists to JS arrays, using slice for cdr and so on. But JS arrays aren't lists, so this is far from a perfect mapping. It's not really suitable for a general Lisp.
Speaking of efficient/readable JS, a few months ago I partially objected to the implementation of lexical scoping on the grounds that attaching a gensym suffix to every lexical variable inhibited readability. It's worth mentioning that Vladimir completely fixed this by (if I understand correctly) making PS put suffixes only on variables where necessary to disambiguate them. As a result, a powerful feature was added without compromising the quality of the generated code. A particularly impressive piece of work.
Daniel
On Thu, Oct 8, 2009 at 5:42 AM, Chaitanya Gupta mail@chaitanyagupta.comwrote:
Vladimir Sedach wrote:
PS is a translator from Common Lisp to JavaScript. The project stopped being an s-expression syntax for JS quite a while ago.
That, for me atleast, is great news. I had been wondering for sometime which direction Parenscript was headed in, and have had a CL->JS compiler high on my wishlist.
Do you plan to make it a complete ANSI CL to JS compiler? (Complete being whatever's allowed within the limits of the browser's security model e.g. file and socket operations might not work)
Does PS aim to become for CL like gwt is for Java? e.g. generating JS which works correctly across all the major browsers.
These are a few questions I have had for sometime -- I would really like to see something akin to gwt for CL.
Chaitanya
What if there were a special form to explicitly allow a Lisp symbol through unmodified? This would be a bit different than the current |:foo| syntax (the :-escape applies to whatever portion of the split symbol it prefixes e.g. |:foo.Bar.:baaZ| -> foo.bar.baaZ).
This isn't the issue with foo.bar syntax. The problem is that putting foo.bar in Parenscript (as opposed to outside the PS compiler) fails in the presence of symbol macros for either foo or bar. Even ignoring other possible undesirable consequences, this makes it a big pain to implement 'let' with real lexical scoping efficiently or readably, and makes code inspection by conventional tools impossible. The whole issue is centered around symbol identity and the abuse of symbol names.
Prefix syntax makes method calling a bit awkward and (.method ...) syntax makes method calls a bit more CLOSish in appearance. I am neutral on its value, but since parenscript has supported this for years and a lot of code is relying on it the cost of removing it is high.
The dot syntax is a design mistake that makes what should be trivial code transformation hard. This has consequences for both the PS compiler (keeping it would make it more complicated than it needs to be) and just as importantly as for the code being compiled. If someone wants to upgrade their project to use the latest version of Parenscript, I think it's ok to ask them to fix what are essentially bugs in their code. The only regrettable thing is that these bugs were encouraged by previous versions of Parenscript as desirable programming style.
Vladimir
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
-- http://chaitanyagupta.com/blog/
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
Do you plan to make it a complete ANSI CL to JS compiler? (Complete being whatever's allowed within the limits of the browser's security model e.g. file and socket operations might not work)
There are a lot of things in CL that don't make much sense in JS. Most of it has to do with data structures and types. For example, there's really no point in implementing linked lists in JavaScript since all the other JS code uses arrays. Parenscript 'dolist' and 'loop' work on JS arrays, and for most use cases have the same semantics as the CL 'dolist' and 'loop'.
The goal of Parenscript is to cover the common case semantic overlaps that exist between native or idiomatic/human-readable JavaScript code and the CL "equivalent."
Not being based around native JS datatypes is where GWT and most (all?) other *-to-JS compilers fail. As soon as you require weird datatypes or boxed object you lose readability and compatibility with other JS code. Luckily Common Lisp is rich enough where you don't need to express everything in terms of a small set of orthogonal concepts like recursion and pattern-matching, which pretty much condemns things like SMLtoJs to generating weird JavaScript code.
Does PS aim to become for CL like gwt is for Java? e.g. generating JS which works correctly across all the major browsers.
GWT's cross-browser support is fundamentally broken because it is based on browser detection. The GWT developers are selling snake-oil when they claim cross browser compatibility: http://carcaddar.blogspot.com/2009/02/gwt-and-deferred-binding.html
GWT does not support older browsers, most mobile browsers, and is unlikely to work correctly on future browsers.
Parenscript actually doesn't come with anything specific to the browser or DOM - by default it only generates JavaScript 1.3 code. How you deal with DOM differences is up to you. There are projects using Parenscript that do browser detection, there are projects that do feature detection. I try to design my applications to only use the subset of the DOM that works identically in all browsers.
These are a few questions I have had for sometime -- I would really like to see something akin to gwt for CL.
The only other thing that gwt does besides compiling Java to JS is to provide a library of UI widgets. I don't really see the value in doing that. I recently had this opinion confirmed by the PhoneGap (http://phonegap.com/) guys - Brian LeRoux was highly critical of widget UI libraries at a talk he gave at the Mobile Portland user's group in August. So I'm not the only person holding this opinion. There's nothing stopping you from using jQuery UI or ExtJS or any other UI library if you want to (this is not the case with GWT, which requires you to write wrappers for any JavaScript library you want to use).
Vladimir
Chaitanya
What if there were a special form to explicitly allow a Lisp symbol through unmodified? This would be a bit different than the current |:foo| syntax (the :-escape applies to whatever portion of the split symbol it prefixes e.g. |:foo.Bar.:baaZ| -> foo.bar.baaZ).
This isn't the issue with foo.bar syntax. The problem is that putting foo.bar in Parenscript (as opposed to outside the PS compiler) fails in the presence of symbol macros for either foo or bar. Even ignoring other possible undesirable consequences, this makes it a big pain to implement 'let' with real lexical scoping efficiently or readably, and makes code inspection by conventional tools impossible. The whole issue is centered around symbol identity and the abuse of symbol names.
Prefix syntax makes method calling a bit awkward and (.method ...) syntax makes method calls a bit more CLOSish in appearance. I am neutral on its value, but since parenscript has supported this for years and a lot of code is relying on it the cost of removing it is high.
The dot syntax is a design mistake that makes what should be trivial code transformation hard. This has consequences for both the PS compiler (keeping it would make it more complicated than it needs to be) and just as importantly as for the code being compiled. If someone wants to upgrade their project to use the latest version of Parenscript, I think it's ok to ask them to fix what are essentially bugs in their code. The only regrettable thing is that these bugs were encouraged by previous versions of Parenscript as desirable programming style.
Vladimir
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
-- http://chaitanyagupta.com/blog/
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
Thanks for the replies -- Vladimir and Daniel. I take it that generating readable Javascript code remains one of the big goals of PS.
And thanks for the inputs on gwt too -- there's some food for thought there for sure.
A few more questions/suggestions:
- Is it a Lisp-1 or Lisp-2? I see that FUNCALL seems to do the right thing in PS, but then again, the generated JS code doesn't have separate namespaces for variables and functions. Will PS remain a Lisp-1 going forward?
- What about CLOS? I've noticed PSOS, which is part of the Suave project (though I haven't been able to try it out yet). Is there any plan to bring CLOS support into Parenscript?
- One specific issue I have noticed with the little bit of PS hacking that I have done is that I have to explicitly RETURN values from functions -- and this is something I keep tripping over frequently. An implicit return would be more Lispish and much better, IMO.
Chaitanya
Vladimir Sedach wrote:
Do you plan to make it a complete ANSI CL to JS compiler? (Complete being whatever's allowed within the limits of the browser's security model e.g. file and socket operations might not work)
There are a lot of things in CL that don't make much sense in JS. Most of it has to do with data structures and types. For example, there's really no point in implementing linked lists in JavaScript since all the other JS code uses arrays. Parenscript 'dolist' and 'loop' work on JS arrays, and for most use cases have the same semantics as the CL 'dolist' and 'loop'.
The goal of Parenscript is to cover the common case semantic overlaps that exist between native or idiomatic/human-readable JavaScript code and the CL "equivalent."
Not being based around native JS datatypes is where GWT and most (all?) other *-to-JS compilers fail. As soon as you require weird datatypes or boxed object you lose readability and compatibility with other JS code. Luckily Common Lisp is rich enough where you don't need to express everything in terms of a small set of orthogonal concepts like recursion and pattern-matching, which pretty much condemns things like SMLtoJs to generating weird JavaScript code.
Does PS aim to become for CL like gwt is for Java? e.g. generating JS which works correctly across all the major browsers.
GWT's cross-browser support is fundamentally broken because it is based on browser detection. The GWT developers are selling snake-oil when they claim cross browser compatibility: http://carcaddar.blogspot.com/2009/02/gwt-and-deferred-binding.html
GWT does not support older browsers, most mobile browsers, and is unlikely to work correctly on future browsers.
Parenscript actually doesn't come with anything specific to the browser or DOM - by default it only generates JavaScript 1.3 code. How you deal with DOM differences is up to you. There are projects using Parenscript that do browser detection, there are projects that do feature detection. I try to design my applications to only use the subset of the DOM that works identically in all browsers.
These are a few questions I have had for sometime -- I would really like to see something akin to gwt for CL.
The only other thing that gwt does besides compiling Java to JS is to provide a library of UI widgets. I don't really see the value in doing that. I recently had this opinion confirmed by the PhoneGap (http://phonegap.com/) guys - Brian LeRoux was highly critical of widget UI libraries at a talk he gave at the Mobile Portland user's group in August. So I'm not the only person holding this opinion. There's nothing stopping you from using jQuery UI or ExtJS or any other UI library if you want to (this is not the case with GWT, which requires you to write wrappers for any JavaScript library you want to use).
Vladimir
Chaitanya
What if there were a special form to explicitly allow a Lisp symbol through unmodified? This would be a bit different than the current |:foo| syntax (the :-escape applies to whatever portion of the split symbol it prefixes e.g. |:foo.Bar.:baaZ| -> foo.bar.baaZ).
This isn't the issue with foo.bar syntax. The problem is that putting foo.bar in Parenscript (as opposed to outside the PS compiler) fails in the presence of symbol macros for either foo or bar. Even ignoring other possible undesirable consequences, this makes it a big pain to implement 'let' with real lexical scoping efficiently or readably, and makes code inspection by conventional tools impossible. The whole issue is centered around symbol identity and the abuse of symbol names.
Prefix syntax makes method calling a bit awkward and (.method ...) syntax makes method calls a bit more CLOSish in appearance. I am neutral on its value, but since parenscript has supported this for years and a lot of code is relying on it the cost of removing it is high.
The dot syntax is a design mistake that makes what should be trivial code transformation hard. This has consequences for both the PS compiler (keeping it would make it more complicated than it needs to be) and just as importantly as for the code being compiled. If someone wants to upgrade their project to use the latest version of Parenscript, I think it's ok to ask them to fix what are essentially bugs in their code. The only regrettable thing is that these bugs were encouraged by previous versions of Parenscript as desirable programming style.
Vladimir
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
-- http://chaitanyagupta.com/blog/
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
< Is it a Lisp-1 or Lisp-2? >
PS isn't a Lisp, as per our discussion. The semantics here are JS's, and JS is always a JS-1.
< explicitly RETURN values from functions -- and this is something I keep tripping over frequently >
This is a pain. We have an ugly RETURN% macro that does nothing in Lisp and expands to RETURN in PS. One of our goals is to figure out how to put these in automatically.
Vladimir, have you ever thought of or tried to get RETURN out of PS? What are the main challenges?
On Fri, Oct 9, 2009 at 6:25 AM, Chaitanya Gupta mail@chaitanyagupta.comwrote:
Thanks for the replies -- Vladimir and Daniel. I take it that generating readable Javascript code remains one of the big goals of PS.
And thanks for the inputs on gwt too -- there's some food for thought there for sure.
A few more questions/suggestions:
- Is it a Lisp-1 or Lisp-2? I see that FUNCALL seems to do the right
thing in PS, but then again, the generated JS code doesn't have separate namespaces for variables and functions. Will PS remain a Lisp-1 going forward?
- What about CLOS? I've noticed PSOS, which is part of the Suave project
(though I haven't been able to try it out yet). Is there any plan to bring CLOS support into Parenscript?
- One specific issue I have noticed with the little bit of PS hacking
that I have done is that I have to explicitly RETURN values from functions -- and this is something I keep tripping over frequently. An implicit return would be more Lispish and much better, IMO.
Chaitanya
Vladimir Sedach wrote:
Do you plan to make it a complete ANSI CL to JS compiler? (Complete being whatever's allowed within the limits of the browser's security model e.g. file and socket operations might not work)
There are a lot of things in CL that don't make much sense in JS. Most of it has to do with data structures and types. For example, there's really no point in implementing linked lists in JavaScript since all the other JS code uses arrays. Parenscript 'dolist' and 'loop' work on JS arrays, and for most use cases have the same semantics as the CL 'dolist' and 'loop'.
The goal of Parenscript is to cover the common case semantic overlaps that exist between native or idiomatic/human-readable JavaScript code and the CL "equivalent."
Not being based around native JS datatypes is where GWT and most (all?) other *-to-JS compilers fail. As soon as you require weird datatypes or boxed object you lose readability and compatibility with other JS code. Luckily Common Lisp is rich enough where you don't need to express everything in terms of a small set of orthogonal concepts like recursion and pattern-matching, which pretty much condemns things like SMLtoJs to generating weird JavaScript code.
Does PS aim to become for CL like gwt is for Java? e.g. generating JS which works correctly across all the major browsers.
GWT's cross-browser support is fundamentally broken because it is based on browser detection. The GWT developers are selling snake-oil when they claim cross browser compatibility: http://carcaddar.blogspot.com/2009/02/gwt-and-deferred-binding.html
GWT does not support older browsers, most mobile browsers, and is unlikely to work correctly on future browsers.
Parenscript actually doesn't come with anything specific to the browser or DOM - by default it only generates JavaScript 1.3 code. How you deal with DOM differences is up to you. There are projects using Parenscript that do browser detection, there are projects that do feature detection. I try to design my applications to only use the subset of the DOM that works identically in all browsers.
These are a few questions I have had for sometime -- I would really like to see something akin to gwt for CL.
The only other thing that gwt does besides compiling Java to JS is to provide a library of UI widgets. I don't really see the value in doing that. I recently had this opinion confirmed by the PhoneGap (http://phonegap.com/) guys - Brian LeRoux was highly critical of widget UI libraries at a talk he gave at the Mobile Portland user's group in August. So I'm not the only person holding this opinion. There's nothing stopping you from using jQuery UI or ExtJS or any other UI library if you want to (this is not the case with GWT, which requires you to write wrappers for any JavaScript library you want to use).
Vladimir
Chaitanya
What if there were a special form to explicitly allow a Lisp symbol through unmodified? This would be a bit different than the current |:foo| syntax (the :-escape applies to whatever portion of the split symbol it prefixes e.g. |:foo.Bar.:baaZ| -> foo.bar.baaZ).
This isn't the issue with foo.bar syntax. The problem is that putting foo.bar in Parenscript (as opposed to outside the PS compiler) fails in the presence of symbol macros for either foo or bar. Even ignoring other possible undesirable consequences, this makes it a big pain to implement 'let' with real lexical scoping efficiently or readably, and makes code inspection by conventional tools impossible. The whole issue is centered around symbol identity and the abuse of symbol names.
Prefix syntax makes method calling a bit awkward and (.method ...) syntax makes method calls a bit more CLOSish in appearance. I am
neutral
on its value, but since parenscript has supported this for years and a lot of code is relying on it the cost of removing it is high.
The dot syntax is a design mistake that makes what should be trivial code transformation hard. This has consequences for both the PS compiler (keeping it would make it more complicated than it needs to be) and just as importantly as for the code being compiled. If someone wants to upgrade their project to use the latest version of Parenscript, I think it's ok to ask them to fix what are essentially bugs in their code. The only regrettable thing is that these bugs were encouraged by previous versions of Parenscript as desirable programming style.
Vladimir
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
-- http://chaitanyagupta.com/blog/
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
-- http://chaitanyagupta.com/blog/
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
Daniel Gackle danielgackle@gmail.com writes: [...]
Vladimir, have you ever thought of or tried to get RETURN out of PS? What are the main challenges?
The lack of implicit return is something that always trips me up writing parenscript. I think it would be a good idea. (Though maybe there should be a policy for these incompatible changes :-)
It is a bit of effort to implement completely (i.e. marking the last form in a defun or lambda to be a returning form, and transforming it to use return if it doesn't already), because you would have to figure out how to push a return through each special form (e.g. if).
But it sounds feasible . . .
Related to the impedance mismatch between Lisp's view of expressions and statements as the same thing and JavaScript's balkanisation of the concepts.
[...]
It sounds like other people want this too. Perhaps its time has come!
Failing to add return is a bug that bites us often, and sometimes takes a while to track down, since the problem can show up in a different part of the program as "foo is undefined" (where foo was supposed to be the return value of some function).
We have many thousands of lines of generated JS with lots of returns in it, which makes for a good regression test for whether a major change like this has worked or not. The JS shouldn't change much, if at all. If other people would also do before-and-after diffs on their codebases, that would be a good way to verify whether implicit return is actually working.
< Though maybe there should be a policy for these incompatible changes >
Yes, there probably should. Personally I'd be fine with a special variable to turn something like this on or off. A compromise might be to support both modes for a couple of major releases and then phase out the old way. I'm just thinking out loud here.
On Sat, Oct 10, 2009 at 5:39 AM, John Fremlin not@just.any.name wrote:
Daniel Gackle danielgackle@gmail.com writes: [...]
Vladimir, have you ever thought of or tried to get RETURN out of PS? What
are
the main challenges?
The lack of implicit return is something that always trips me up writing parenscript. I think it would be a good idea. (Though maybe there should be a policy for these incompatible changes :-)
It is a bit of effort to implement completely (i.e. marking the last form in a defun or lambda to be a returning form, and transforming it to use return if it doesn't already), because you would have to figure out how to push a return through each special form (e.g. if).
But it sounds feasible . . .
Related to the impedance mismatch between Lisp's view of expressions and statements as the same thing and JavaScript's balkanisation of the concepts.
[...]
On Sat, Oct 10, 2009 at 9:25 AM, Daniel Gackle danielgackle@gmail.comwrote:
It sounds like other people want this too. Perhaps its time has come!
Hear, hear.
-Red
Failing to add return is a bug that bites us often, and sometimes takes a while to track down, since the problem can show up in a different part of the program as "foo is undefined" (where foo was supposed to be the return value of some function).
We have many thousands of lines of generated JS with lots of returns in it, which makes for a good regression test for whether a major change like this has worked or not. The JS shouldn't change much, if at all. If other people would also do before-and-after diffs on their codebases, that would be a good way to verify whether implicit return is actually working.
< Though maybe there should be a policy for these incompatible changes >
Yes, there probably should. Personally I'd be fine with a special variable to turn something like this on or off. A compromise might be to support both modes for a couple of major releases and then phase out the old way. I'm just thinking out loud here.
On Sat, Oct 10, 2009 at 5:39 AM, John Fremlin not@just.any.name wrote:
Daniel Gackle danielgackle@gmail.com writes: [...]
Vladimir, have you ever thought of or tried to get RETURN out of PS?
What are
the main challenges?
The lack of implicit return is something that always trips me up writing parenscript. I think it would be a good idea. (Though maybe there should be a policy for these incompatible changes :-)
It is a bit of effort to implement completely (i.e. marking the last form in a defun or lambda to be a returning form, and transforming it to use return if it doesn't already), because you would have to figure out how to push a return through each special form (e.g. if).
But it sounds feasible . . .
Related to the impedance mismatch between Lisp's view of expressions and statements as the same thing and JavaScript's balkanisation of the concepts.
[...]
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
I've recently decided to port an existing web app I have lying around to tpd2, so I think the best course of action is to wait for a tpd2 patch from me.
Vladimir
On Tue, Oct 6, 2009 at 5:07 AM, John Fremlin john@fremlin.org wrote:
Hi Vladimir,
It seems that the new parenscript horribly breaks tpd2.
The awful part of the business is changing from using elements.push etc. methods.
You seem to recommend to rewrite them as ((slot-value elements 'push) new-thing).
This is completely not at all related to Common Lisp syntax, which was supposedly the aim of this change, so I guess I am barking up the wrong end of the stick.
Should I wait for the reader macros before making the update?
Thanks for working on parenscript, it's good to see that it's improving.
And it's good to see that people are complaining about the new version not working with tpd2 as it shows that there are some users out there :-)
[...]
parenscript-devel@common-lisp.net