Br's,
Marius
On Dec 17, 8:58 am, Naftoli Gugenheim <naftoli...@gmail.com> wrote:
> I'm thinking of an approach to writing a DSL with a much cleaner syntax. I'll try to put something together.
>
> -------------------------------------
>
-------------------------------------
val jsFunc: JSFunc = Function("myFunc")("param1", "param2") {case param1 :: param2 :: Nil =>
Var("someArray") := Array(1, 2, 3, 4, 5)
If(param1 < 30) {
val x = Var("x") // now we can use either x or 'x
x := (234 - 3) / 2 // calculation happens in scala
Var("y") := (2:Expr) * x * 2 // calculation happens in javascript
'jsFunc(1, 2, "do it", 'y)
val $ = JSIdent("$")
$("#myID") >> 'attr("value", "123")
} Else {
'console >> 'log(">=30")
}
ForEach(Var("i") In 'someArray) {
'console >> 'log("Hi there " & 'i)
}
Function()("arg1", "arg2") { case arg1 :: arg2 :: Nil =>
'alert("Anonymous function (" & arg1 & ", " & arg2 & ")")
}(1,2)
}
println(jsFunc.toCode)
function myFunc(param1, param2) {
var someArray
someArray = [1.0, 2.0, 3.0, 4.0, 5.0]
if((param1 < 30.0)) {
var x
x = 115.0
var y
y = ((2.0 * x) * 2.0)
jsFunc(1.0, 2.0, "do it", y)
($("#myID")).attr("value", "123")
} else {
(console).log(">=30")
}
var i
for(i in someArray) {
(console).log(("Hi there " + i))
}
function (arg1, arg2) {
alert((((("Anonymous function (" + arg1) + ", ") & arg2) + ")"))
}(1.0, 2.0)
}
<DSL.scala>
Syntactically it doesn't seem to me that there are much differences
between this and the initial proposal. Probably the most noticeable
diffs are in algebraic expressions like
Var("y") := (2:Expr) * x * 2
which probably looks more appealing than
Var("y") := 2 __* x __* 2
The other thing is that you don't end JS statements with ; ... I
don't think this is a good JS practice. I added `;` function to allow
user to specify this terminator when needed.
I'm also not at all in favor of function names starting with capital
letter.
I was also running into a Scala compiler crash when using constructs
like: case class Fnc(name: String)(params: String*)(body : => String)
{} :D
I'm not sure why in things like: def Function()(argNames: String*)
(body: PartialFunction[List[JSIdent], Unit]): JSAnonFunc you used
PartialFunctions ... you are callin gthe PF without checking if the
function is defined for its parameter which could lead to MachError.
I see you took a different approach of building JS code in a more
imperative manner where generated code is kept in the ThreadGlobal
state. My initial approach and actually my design intent was to use
functional composition to write the code which tremendously simplifies
the library code.
I made some adjustments to my initial approach and something like:
val js = JsFunc('myFunc, 'param1, 'param2) {
JsIf('param1 < 30) {
Var ('home) := (234: Js) + 3 / 3 `;`
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) `;`
}
println(js.toJs)
generates
function myFunc( param1, param2 ) {
if (param1 < 30) {
var home = 234 + 3 / 3;
var someArray = [ 1, 2, 3, 4, 5 ];
myFunc(1, 2, "do it", home);
$("#myID").attr("value", "123");
}
for (var i in someArray) {
console.log("Hi there 'i");
}
function ( arg1, arg2 ) {
alert("Anonymous function 'arg1'arg2")
}(1, 2);
}
I guess in many respects these things are subjective. Personally so
far I am linking better my approach with the changes for expression
building (no more __ prefixed functions).
Br's,
Marius
> 2009/12/17 Naftoli Gugenheim <naftoli...@gmail.com>
>
> > Current state attached.
>
> > 2009/12/17 Marius <marius.dan...@gmail.com>
> >> liftweb+u...@googlegroups.com<liftweb%2Bunsu...@googlegroups.com>
> >> .
> >> > For more options, visit this group athttp://
> >> 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<liftweb%2Bunsu...@googlegroups.com>
> >> .
> >> For more options, visit this group at
> >>http://groups.google.com/group/liftweb?hl=en.
>
>
>
> DSL.scala
> 9KViewDownload
If I may a few notes:
Syntactically it doesn't seem to me that there are much differences
between this and the initial proposal. Probably the most noticeable
diffs are in algebraic expressions like
which probably looks more appealing than
Var("y") := (2:Expr) * x * 2
Var("y") := 2 __* x __* 2
The other thing is that you don't end JS statements with ; ... I
don't think this is a good JS practice. I added `;` function to allow
user to specify this terminator when needed.
I'm also not at all in favor of function names starting with capital
letter.
I was also running into a Scala compiler crash when using constructs
like: case class Fnc(name: String)(params: String*)(body : => String)
{} :D
I'm not sure why in things like: def Function()(argNames: String*)
(body: PartialFunction[List[JSIdent], Unit]): JSAnonFunc you used
PartialFunctions ... you are callin gthe PF without checking if the
function is defined for its parameter which could lead to MachError.
I see you took a different approach of building JS code in a more
imperative manner where generated code is kept in the ThreadGlobal
state. My initial approach and actually my design intent was to use
functional composition to write the code which tremendously simplifies
the library code.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.