val test = j_var ("test") := j_trueval test2 = j_var ('test2) := j_false1 j_< 2JsVar("k") j_<= 10val a: JsVar = 'aa++val clause1 = j_if (j_true) {j_return (j_false)} j_else {j_return (j_true)}val clause2 = j_if (j_true) {j_return()} j_else {j_return (j_true)}val k: JsVar = 'kval console_log = JsVar("console", "log")val c = j_for (j_var (k) := 0, k j_< JsVar("arguments", "length"), k++) {console_log(k)}
Very cool Pete.I was just looking at phantomjs today as well.
--To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/Ax1r-rdEML4J.
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
There was a discussion about a javascript dsl a long time ago on the list. Marius had one version, and I posted a different DSL. Don't have a link, you can search for it.I would be very interested in a proper discussion of pros and cons of various approaches.
On Wed, Jun 15, 2011 at 8:40 PM, TylerWeir <tyler...@gmail.com> wrote:Very cool Pete.I was just looking at phantomjs today as well.--To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/Ax1r-rdEML4J.
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/NadSUJYoWpMJ.
One way of going about it would be to have the CSS selectors actually delegate their functionality to another class via implicits, so that you could drop in your own behavior with an import.A simpler way would be to just have a separate DSL with the same syntax.But what's really the point? Is it just to have a nice DSL for jQuery transformations?
JsFunc('myFunc, 'param1, 'param2) {JsIf('param1 __< 30) {Var('home) := Wrap(234 __- 3) __/ 2 `;`Var('someArray) := JsArray(1, 2, 3, 4, 5) `;`'myFunc(1, 2, "do it", 'home) `;`$("#myID") >> 'attr("value", "123") `;`} ~JsForEach(Var('i) in 'someArray) {'console >> 'log("Hi there " __+ 'i) `;`} ~JsAnonFunc('arg1, 'arg2) {'alert("Anonymous function " __+ 'arg1 __+ 'arg2)}(1, 2) `;`}
For(JsEq(JsVar("k"), Num(1)), JsVar("k") < Num(10), JsVar("k") ++) {Call("console.log", JsVar("k"))}
j_for (j_var (k) := 0, k j_< JsVar("arguments", "length"), k++) {console_log(k)}
Thanks, David, glad you like it. And I know I do tend to throw out things and not follow them up. Let's make this an exception! =) I will ping Daniel, Marius and other to check out this thread so that we can get some sort of DSL into Lift once and for all.First, while I have everyone's attention, can anyone tell me why we have JsCmd and JsExp?
They both seem to start from the same place (extends HtmlFixer with ToJsCmd, to be exact), but JsCmd has nothing beyond that but a & method to chain calls.
JsExp, on the other hand, has a lot of additional methods. It'd be a breaking changing, but might it be a nice change to drop JsCmd and just have JsExp as the base Javascript type?
Ok, moving to Javascript DSLs. All examples can also be seen at https://gist.github.com/1032634, including some additional notes. The first one proposed that I know of was by Marius in December 2009. Here's his example:JsFunc('myFunc, 'param1, 'param2) {JsIf('param1 __< 30) {Var('home) := Wrap(234 __- 3) __/ 2 `;`Var('someArray) := JsArray(1, 2, 3, 4, 5) `;`'myFunc(1, 2, "do it", 'home) `;`$("#myID") >> 'attr("value", "123") `;`} ~JsForEach(Var('i) in 'someArray) {'console >> 'log("Hi there " __+ 'i) `;`} ~JsAnonFunc('arg1, 'arg2) {'alert("Anonymous function " __+ 'arg1 __+ 'arg2)}(1, 2) `;`}
It's quite concise and it's slick how semi-colons are used to chain commands, though you do need to remember the ticks each time so it doesn't get treated as a Scala semicolon. You can read the discussion around his proposal at https://groups.google.com/d/topic/liftweb/Xdql2etoQlc/discussion and https://groups.google.com/d/topic/liftweb/tj52BFcJYmU/discussion.
Exactly a year ago, not knowing Marius' proposal, I put forward my own attempt:For(JsEq(JsVar("k"), Num(1)), JsVar("k") < Num(10), JsVar("k") ++) {Call("console.log", JsVar("k"))}I think it's a decent attempt. The discussion can been seen here: https://groups.google.com/d/topic/liftweb/JMcVtSvrjYE/discussionFinally, you have my most recent proposal, again done in a vacuum but perhaps subconsciously picking up on the two previous proposals:j_for (j_var (k) := 0, k j_< JsVar("arguments", "length"), k++) {console_log(k)}
So, what'll it be? Of course, we can and should combine the best elements of all of them. Just off the top of my head and looking at the previous examples and the JsExp source code, we could easily get to something like:For (Var ('k) := 0, 'k < 'arguments->'length, 'k++) {'console->'log('k)}So, suggestions? Does anyone have any specific complicated pieces of Lift Js code that they'd be willing to share, both to discuss what they don't like about the current syntax and to try implementing it in the different proposals to see which one looks nicest.Thanks,Peter
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/eKSZTHqaYOsJ.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
j_for (j_var (k) := 0, k j_< JsVar("arguments", "length"), k++) {console_log(k)}
object j_for {def apply(initialExp: JsExp, condition: JsExp, incrementExp: JsExp)(body: JsExp) = JsFor(initialExp, condition, incrementExp, body)}
case class j_var(name: String, right: Box[JsExp] = Empty) extends JsExp {def toJsCmd = if (right.isDefined) {"var " + name + " = " + right.open_!.toJsCmd} else {"var " + name}def :=(in: JsExp) = this.copy(right = Full(in))}object j_var {def apply(name: Symbol) = new j_var(name.name)def apply(name: JsVar) = new j_var(name.varName)}
class RichJsVar(left: JsVar) {def ++ = JE.JsRaw(left.toJsCmd + "++")def -- = JE.JsRaw(left.toJsCmd + "--")def +=(right: JsExp) = JE.JsRaw(left.toJsCmd + " += " + right.toJsCmd)def -=(right: JsExp) = JE.JsRaw(left.toJsCmd + " -= " + right.toJsCmd)def apply(params: JsExp*) = Call(left.toJsCmd, params :_*)}
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/eKSZTHqaYOsJ.
Peter--
You received this message because you are subscribed to the Google Groups "Lift" group.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/uVXTCuF7MTIJ.
Peter--
You received this message because you are subscribed to the Google Groups "Lift" group.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/uVXTCuF7MTIJ.
Just to add to the mix, if I understood correctly, Grzegorz Kossakowski who interned at Google for the Scala->GWT work will be working with the EPFL team during the northern hemisphere summer to produce an initial prototype of a Scala-to-Javascript system of some kind. May be compiler-like, might be DSL... I think it's early days yet. I couldn't find any more info about it. It was mentioned in the Scala Exchange keynote on Wednesday.
Well, I think the comparisons I've been up already are decent given the major differences are ones of style (all compile and work as expected). What would you like to still see compared?
Peter--
You received this message because you are subscribed to the Google Groups "Lift" group.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/jbEBEPFRxd4J.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Well, I think the comparisons I've been up already are decent given the major differences are ones of style (all compile and work as expected). What would you like to still see compared?
Peter--
You received this message because you are subscribed to the Google Groups "Lift" group.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/jbEBEPFRxd4J.
An unrelated point: For the benefit of the hopefully-coming-soon reactive-web feature allowing pure-javascript event streams and signals, I would prefer if the DSL would be typed, having the type relationships such as the following:
[ ... ]
The reason why this would be very beneficial is because then you could write something likespan.contents <<: field.value.map {s: JsExp[JsString] =>Str("$") + s}and it could generatefunction(arg0) { return "$" + s; }simply by calling the Scala function with a JsVar.Not sure how good of an explanation that was, but the goal is a pure Scala alternative to GWT, including client-side logic.
Are you responding to my comment out a more comprehensive comparison? (It's hard to tell without any quoted text. ;) )What I meant is that I think my snippet illustrates the DSL's syntax for much more language features than the other code samples.Obviously, this is not a contest where there's one winner; the goal is to mix and match to get every part the best way. So it would be helpful if you would be willing and have the time to make a language-feature-for-language-feature comparison (possibly just by converting my snippet to the other DSLs, leaving out whichever parts are not implemented).
My third consecutive post on this thread... (each is somewhat of a separate topic)What is the ideal level of type safety for a javascript DSL?One could argue, why not get all scalac has to offer, and make the DSL fully type safe. If you specifically want to write code that isn't 100% type safe, don't write it solely via the DSL.One the other hand, javascript is designed not to be type safe. For example, the condition part of an if statement can be a boolean expression in which case it must be true, or of another type in which case it checks that it's defined and not null.Personally I think that ideally it should be fully type safe, using typed scala identifiers and not just 'symbols --- but there should be ways to explicitly force the DSL to accept something of the wrong type.
Peter--
You received this message because you are subscribed to the Google Groups "Lift" group.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/9HxYbfyb1ecJ.
Hi all,Sorry I'm only responding now. To answer David's, and later Naftoli's, question about what the goals are for a Javascript DSL, here are mine:
- Concise Javascript coding in a fashion that looks, in Scala, as much like real Javascript as possible/reasonable
- Type safe Javascript coding
Late binding is something I hadn't thought much about but would be very cool. I'm not sure how to do that, so David or someone else would need to help me or whoever is coding the DSL. As for integration with jQuery, I would prefer to continue on the route Lift has already taken: there are the base constructs in net.liftweb.http.js, and then there is library specific code in net.liftweb.http.js.jquery and the like. This relates somewhat tangentially to the Javascript module system I proposed a long time ago...I think that even if we only do the two points I highlighted we will have something that is quite useful and powerful, so much so that I can easily see non-Lift projects using it.As for syntax, given my preference for approximating Javascript but the frequent keyword overlap between Javascript and Scala, my inclination now is to just capitalize the conflicting keyword (i.e. rather than the j_keyword syntax I used most recently). This gives a quite natural syntax but is possible without any compiler gyrations. Given that Scala doesn't have any sort of method_missing functionality, 'object.property' sytax is not possible. I like 'object->property', especially considering that some other languages use it instead of the dot notation.
How to get there?I think there's one core philosophical question to answer, whether we want this DSL to be a layer on top of the existing Javascript code or should return to first principles. If the latter, Naftoli has suggested two interesting options: 1) to base the data types off of lift-json or 2) to develop a new, complete system of Javascript types with logical hierarchies. I like both ideas and am particularly intrigued by the second approach, having already done something similar with typed.js (https://github.com/pr1001/typed.js).However, I actually prefer the pragmatic approach. I think we've got enough code present that not only is it enough to build an interesting DSL, but also a third Javascript-related system (say, net.liftweb.javascript vs net.liftweb.http.js and net.liftweb.json) would be too much. Likewise, I don't think we can or should just throw out net.liftweb.http.js: it's been around, it works, and much of both Lift's internal code and other people's code reply upon it.
So, should we extend existing objects or provide complementary ones? In the two versions I've mocked up I've taking the second approach, as I didn't want to touch Lift. However, it leads to a lot of implicit conversions and I think most, if not all, of the existing things can be safely extended, especially since it would just consist of some methods and alternate apply's. Plus, it wouldn't take too long to develop.So, that's my preferred approach. Thoughts?
On Wed, Jun 15, 2011 at 9:25 PM, Naftoli Gugenheim <nafto...@gmail.com> wrote:There was a discussion about a javascript dsl a long time ago on the list. Marius had one version, and I posted a different DSL. Don't have a link, you can search for it.I would be very interested in a proper discussion of pros and cons of various approaches.
I really like the stuff Peter put together in this thread, but I agree that a full discussion should be had about an improved DSL... and perhaps Daniel Spiewak can join the discussion given the about of JavaScript he's done for Vibe.
But most importantly, I'd like to discussion to reach a conclusion and an implementation to roll into Lift. So, Peter, because you started this discussion, can you lead the discussion and take responsibility for getting an implementation into Lift?
Thanks,
a very excited David
On Wed, Jun 15, 2011 at 8:40 PM, TylerWeir <tyler...@gmail.com> wrote:Very cool Pete.I was just looking at phantomjs today as well.
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/Ax1r-rdEML4J.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
I like the idea of concision in the case of JS, but what's the reason to have the DSL look like JS?I'd prefer to have it look as much like Scala as possible, but I'd like to hear arguments.
On goal one, I think the gain is you don't have big blocks of JsRaw("..."). Likewise, you can reuse variable components and know you're referring to the same thing, like in my for loop example.
On goal two, I think the question is whether we want to match or improve on Javascript. ;-) Javascript does all sort of type casting and type conversions behind the scenes: do we want to know about that? Even model it? I think at least initially that's a bridge too far. Maybe I've missed what you've already done (it looks very nice!) and have already addressed some of those issues.
As for whether taking our time to get it right or just going with what's quick, I'm inclined right now to take the quick route. This is something we've been talking about for a long time and it hasn't happened yet. I think the best test of things will be to get it into Lift and then see how (or even if) people use it.
Like you say, the existing JsExp is not typed, so I think adding types would require changing or dropping the existing Javascript objects. I'm not wild about that, though eventually I think type safety would be awesome.Maybe we could have two stages: first a simple wrapper on top of the existing code, second a new, type-safe DSL? The idea would use the same basic syntax ("Var" for variables, ":=" for assignment, "->" for property access, etc?), so switching later would easier for people that have made an investment into the DSL.
val alert = JsIdent[JsString |=> JsVoid]('alert)def render = {Reactions.inServerScope(Page.currentPage) {jses.foreach { v: JsExp[JsString] =>alert.apply("Fired: ".$ + v)}}
I like the idea of concision in the case of JS, but what's the reason to have the DSL look like JS?I'd prefer to have it look as much like Scala as possible, but I'd like to hear arguments.
I like the choice of JQuery, I think if we try to be friendly with all the libs, we won't get anything done, so pick a horse and go with it.
Type safety would be lovely, as would late binding, since I hack around that now.
I'll look at all the places where I use JsRaw and try and provide some use cases.
I think I agree with this. Also, I don't know that others disagree --- when Peter said it should look like real javascript as much as possible, I think he meant as opposed to, for example, the current javascript DSL --- it doesn't look like any language, more like a manually constructed AST; or as opposed to some aspects of some DSL suggestions, which again look like neither.
Sorry, Naftoli, I could have sworn I saw you mention lift-json once. That's why I said you had proposed two approaches. Oops!On goal one, I think the gain is you don't have big blocks of JsRaw("..."). Likewise, you can reuse variable components and know you're referring to the same thing, like in my for loop example.On goal two, I think the question is whether we want to match or improve on Javascript. ;-) Javascript does all sort of type casting and type conversions behind the scenes: do we want to know about that? Even model it? I think at least initially that's a bridge too far. Maybe I've missed what you've already done (it looks very nice!) and have already addressed some of those issues.As for whether taking our time to get it right or just going with what's quick, I'm inclined right now to take the quick route. This is something we've been talking about for a long time and it hasn't happened yet. I think the best test of things will be to get it into Lift and then see how (or even if) people use it.Like you say, the existing JsExp is not typed, so I think adding types would require changing or dropping the existing Javascript objects. I'm not wild about that, though eventually I think type safety would be awesome.Maybe we could have two stages: first a simple wrapper on top of the existing code, second a new, type-safe DSL? The idea would use the same basic syntax ("Var" for variables, ":=" for assignment, "->" for property access, etc?), so switching later would easier for people that have made an investment into the DSL.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/0Kbwj66jD20J.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
(all letters)
|
^
&
< >
= !
:
+ -
* / %
(all other special characters)
Thanks, David. What do you propose instead of ->?
Just to brainstorm, this is the order of operator precedence:(all letters)
|
^
&
< >
= !
:
+ -
* / %
(all other special characters)What do people think about the following syntax: 'console dot 'log ("test")? It's not as good as an actual dot but close. ;-)Also, Naftoli has proposed to me that he just put his DSL into reactive-web instead of Lift. I think that's a reasonable to me but I guess I'm biased. ;-)
Peter
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/J-H0PsADTI8J.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Hi David,So you don't like 'dot'? ;-)
Of the three you propose I like '-&' the best, since it suggests a sort of combination: 'console -& 'log ("test")
Peter--
You received this message because you are subscribed to the Google Groups "Lift" group.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/0H4YCMYuy1YJ.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Thanks for taking this on, just one comment from a user more than a
DSL writer, the === looks more like a compare than an assignment,
while the := is just one character shorter, I have seen it used on sbt
0.10, and I think on other languages, so at first glance my be a
better choice.
The rest looked pretty straight forward, to me at least.
Thanks
Diego
> console_log(k)
> }
> It's obviously not Javascript, but I think you'll agree that the meaning is
> easier to understand at a glance than:
> JsFor(JsRaw("var k = 0"), JsLt(JsVar("k"), JsVar("someArray", "length")),
> JsVar("k") === (JsVar("k") + 1), Call("console.log", JsVar("k")))
>
> This is honestly the best I could come up with without my additions!
> All in all I'm pretty happy with things, though I had to call my new if-else
> construction jIf because it conflicted with the If LocParam and I suspect
> there are lots of people doing wildcard imports that would pull in the two.
> Likewise there's no Null (JsNull is still there, of course) because it'd
> conflict with scala.xml.Null, but I think that's less of a loss.
> I did not end up adding the := Javascript assignment method that has been
> discussed in this thread because I noticed that === is already a method on
> JsExp. It'd only be a 1 character gain. That because said, I did make
> aliases for many of the Js* objects (JsTrue:True, JsFalse:False, etc).
> Finally, I tried to had Scaladocs for every addition I made, so hopefully
> it's pretty easy to follow what I did.
> Please tell me what you think!
> Peter
>
> --
> You received this message because you are subscribed to the Google Groups
> "Lift" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/liftweb/-/2d7Aj52976AJ.
> To post to this group, send email to lif...@googlegroups.com.
> To unsubscribe from this group, send email to
> liftweb+u...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/liftweb?hl=en.
>
--
Diego Medina
Web Developer
(305) 788-4954
di...@fmpwizard.com
http://www.fmpwizard.com
In other words, this adds one more straw to the camel's back that
we call Lift's learning curve. That camel already has a LOT of straw
on it.
I've not been following this DSL discussion in any depth, but I'd
urge you to take the alias back out again.
Byron
> --
> You received this message because you are subscribed to the Google Groups "Lift" group.
> To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/wcfGh-obpkYJ.
> To post to this group, send email to lif...@googlegroups.com.
> To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
---------------------------------------------------------
Byron Weber Becker Voice: 519-888-4567 x34661
School of Computer Science Fax: 519-885-1208
University of Waterloo Office: DC3105
Waterloo, ON N2L 3G1
Advising FAQ: http://www.cs.uwaterloo.ca/current/faq/index.shtml
That being said, try googling for
javascript ===
at least here google seems to just ignores the ===. This will make it
harder to find out what === means. But as you said, it will all come
down to what you guys decide.
Now, thanks for adding the := and hopefully people who write
examples/blogs/anything public will just use :=
my 2 cents
Diego
> --
> You received this message because you are subscribed to the Google Groups
> "Lift" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/liftweb/-/qukvv0uuJDUJ.
> To post to this group, send email to lif...@googlegroups.com.
> To unsubscribe from this group, send email to
> liftweb+u...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/liftweb?hl=en.
>
--
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/qukvv0uuJDUJ.
I think the point here is that they're trying to make that function
you're trying to call type-safe, so that when your model changes, the
function benefits from the compiler too. I certainly would like to have
the compiler help me generate JS-functions which made sense according to
my domain-model.
--
Andreas Joseph Krogh <and...@officenet.no>
Senior Software Developer / CTO
Public key: http://home.officenet.no/~andreak/public_key.asc
------------------------+---------------------------------------------+
OfficeNet AS | The most difficult thing in the world is to |
Rosenholmveien 25 | know how to do a thing and to watch |
1414 Troll�sen | somebody else doing it wrong, without |
NORWAY | comment. |
Org.nr: NO 981 479 076 | |
| |
Tlf: +47 24 15 38 90 | |
Fax: +47 24 15 38 91 | |
Mobile: +47 909 56 963 | |
------------------------+---------------------------------------------+