|
View:
New views
16 Messages
—
Rating Filter:
Alert me
|
|
|
lisp for groovy?Hi,
my proposal may be a little bit odd in the result, but I really think it could be very useful. My proposal consists of 3 Points 1) no top-level statements in lists 2) new Token "°" or something different to make a symbol out of a identifier 3) remove "," from lists or make them optional this enables us to make list like this one: [°select "*" °from table °where foo "=" bar] table, foo and bar are handled as varibales all tokens prefixed with ° are symbols, for this a new class groovy.lang.Symbol will be created, which contains the property name, to get the name of the symbol. Advantages: * easy way to deinfe DSLs Disadvantages: * we are loosing top-level statements in lists (point 3 requires 1) * [ is not ( * ° is not ' (* it is no lisp because there are no makros) * poeple don't like lisp like structures ;) I think the advantages are more important comments? bye blackdrag |
|
|
|
|
|
Re: lisp for groovy?Hi Jochen
Interesting idea, though the syntax seems a bit foreign :-) On the other hand, simply allowing optional colons inside lists could bring us what you're after in that example... as long as you're doing that inside a closure, so that those keywords are retrieved from the englobing closure metaclass. Let's see that more clearly in the same example: dsl.sql{ [ select "*" from bar where foo "=" x ] } It almost looks like the real sql syntax, and the unknown elements would be checked against the closure metaclass which would know how to interpret select or from. Just my 2 euro-cents On 02/01/06, Jochen Theodorou <blackdrag@...> wrote: > Hi, > > my proposal may be a little bit odd in the result, but I really think it > could be very useful. My proposal consists of 3 Points > > 1) no top-level statements in lists > 2) new Token "°" or something different to make a symbol out of a identifier > 3) remove "," from lists or make them optional > > this enables us to make list like this one: > > [°select "*" °from table °where foo "=" bar] > > table, foo and bar are handled as varibales > all tokens prefixed with ° are symbols, for this a new class > groovy.lang.Symbol will be created, which contains the property name, to > get the name of the symbol. > > Advantages: > * easy way to deinfe DSLs > > Disadvantages: > * we are loosing top-level statements in lists (point 3 requires 1) > * [ is not ( > * ° is not ' > (* it is no lisp because there are no makros) > * poeple don't like lisp like structures ;) > > > I think the advantages are more important > comments? > > bye blackdrag > -- Guillaume Laforge Groovy Project Manager http://glaforge.free.fr/blog/groovy |
|
|
Re: lisp for groovy?spullara.1684899@... schrieb:
> I like the idea, but that symbol isn't on US keyboards so I doubt we could > really use it. Maybe use : like in ruby? well we have one of ^%#~, : is not ok because [foo :bar] would be a list and [foo : bar] not. That's to problematic. # is a bit bold, but ok for me. (I always wanted # not to be used for line comments ;)) We can also use 2 characters.. but even then I wouldn't use :: because of maps: [foo ::bar] is a list and [foo:::bar] is a map, but is it verbose enough to see that? bye blackdrag |
|
|
Re: lisp for groovy?I personally prefer the %,& or $ symbols.
On 1/2/06, Jochen Theodorou <blackdrag@...> wrote:
spullara.1684899@... schrieb: |
|
|
Re: lisp for groovy?A cleaner solution might be allowing for an 'escape mode', e.g.
def query = <sql>select: * from: $table where: field = $bar</sql> query.where += "field2 is null" def sql = Sql.newInstance("jdbc:mysql://localhost:3306/mydb", "user", "pswd", "com.mysql.jdbc.Driver") sql.eachRow(query) { println ${it.field} } other examples: def essay = new java.io.File("${path}") def wordcount = <shell>cat: ${essay.canonicalPath} | wc: -w</shell> def gsh = new com.baulsupp.groovy.groosh.Groosh(); gsh.exec(wordcount) { println "${essay.name}: has ${it} words" } Comments? On 1/3/06, Demis Bellot <demis.bellot@...> wrote: I personally prefer the %,& or $ symbols. |
|
|
Re: lisp for groovy?On 2 Jan 2006, at 20:58, Jochen Theodorou wrote: > Hi, > > my proposal may be a little bit odd in the result, but I really > think it could be very useful. My proposal consists of 3 Points > > 1) no top-level statements in lists > 2) new Token "°" or something different to make a symbol out of a > identifier > 3) remove "," from lists or make them optional > > this enables us to make list like this one: > > [°select "*" °from table °where foo "=" bar] > > table, foo and bar are handled as varibales > all tokens prefixed with ° are symbols, for this a new class > groovy.lang.Symbol will be created, which contains the property > name, to get the name of the symbol. > > Advantages: > * easy way to deinfe DSLs > > Disadvantages: > * we are loosing top-level statements in lists (point 3 requires 1) > * [ is not ( > * ° is not ' > (* it is no lisp because there are no makros) > * poeple don't like lisp like structures ;) > > > I think the advantages are more important > comments? I think you can do this without needing to explicitly distinguish symbols from other names: If your construct created a list and an instance of a metaclass then the list could be a list of names, values and tokens. {<select * from table where foo = bar>} This would create a list [new Name("select"), new Token("*"), new Name ("from"), ......] and a metaclass instance capable of resolving names at the point when the list is created (i.e. much like the metaclass for a closure). The DSL looks at each name and can tell if it is a symbol or a variable name (as it knows the spelling of all the symbols it supports). It uses the metaclass to access properties and call methods. Variables which refer to local on stack values are handled in exactly the same way as with closures. John Wilson The Wilson Partnership http://www.wilson.co.uk |
|
|
Re: lisp for groovy?well I was thinking
def query = <sql>select: * from: $table where: field = $bar</sql> query.where += "field2 is null" could be more strongly typed and essentially equivalent to: def query = [select:new SqlSelect("*"),from:new SqlFrom("$table"), where:new SqlWhere("field = $bar")] query.where.add("field2 is null") so 'invalid symbols' could be a compile-time error on a similar note: def wordcount = <shell>cat: ${essay.canonicalPath} | wc: -w</shell> would be equivalent to: def wordcount = [cat:new ShellCat("${essay.canonicalPath}"),pipe:new ShellPipe(),wc:new ShellWc("-w")] but yeah it could always be more builder friendly: def query = sql.{ select(*) from($table) where(field:$bar) } def wordcount = shell.{ cat(essay.canonicalPath) pipe { wc(-w) } } Demis On 1/5/06, John Wilson <tug@...> wrote:
|
|
|
Re: lisp for groovy?def query = sql.{ select "*" from table where field:$bar and field2:"is null" } for free? On 1/5/06, Demis Bellot <demis.bellot@...> wrote: well I was thinking |
|
|
Re: lisp for groovy?A more legal syntax being: def table = "mytable" def bar = "value" def query = sql.{ select "*" from table where [field:bar] // or where[field:bar,field2:"is null",etc] and [field2:"is null"] } On 1/5/06, Demis Bellot <demis.bellot@...> wrote: actually with optional braces (not sure if it works in builders) we might be able to do: |
|
|
Re: lisp for groovy?John Wilson schrieb:
> > On 2 Jan 2006, at 20:58, Jochen Theodorou wrote: > >> Hi, >> >> my proposal may be a little bit odd in the result, but I really think >> it could be very useful. My proposal consists of 3 Points >> >> 1) no top-level statements in lists >> 2) new Token "°" or something different to make a symbol out of a >> identifier >> 3) remove "," from lists or make them optional >> >> this enables us to make list like this one: >> >> [°select "*" °from table °where foo "=" bar] >> >> table, foo and bar are handled as varibales >> all tokens prefixed with ° are symbols, for this a new class >> groovy.lang.Symbol will be created, which contains the property name, >> to get the name of the symbol. >> >> Advantages: >> * easy way to deinfe DSLs >> >> Disadvantages: >> * we are loosing top-level statements in lists (point 3 requires 1) >> * [ is not ( >> * ° is not ' >> (* it is no lisp because there are no makros) >> * poeple don't like lisp like structures ;) >> >> >> I think the advantages are more important >> comments? > > I think you can do this without needing to explicitly distinguish > symbols from other names: I want to do that to avoid naming problems and to be able to build lists through a function or other things. We already have this problem in maps. > If your construct created a list and an instance of a metaclass then > the list could be a list of names, values and tokens. > > {<select * from table where foo = bar>} what is this "<" and ">" here? new syntax? > This would create a list [new Name("select"), new Token("*"), new Name > ("from"), ......] and a metaclass instance capable of resolving names > at the point when the list is created (i.e. much like the metaclass for > a closure). what about local variables? metaclass can't resolve them. And how builds the list? the Compiler?, ok.. but then, why is that better than using symbols? I like Demis idea of "unescaping" the variables much better. > The DSL looks at each name and can tell if it is a symbol or a variable > name (as it knows the spelling of all the symbols it supports). But that doen't solve the problem with local variables > Variables which refer to local on stack values are handled in exactly > the same way as with closures. to do this I have to know "at compile time" what is a variable and what not. This isn't Ruby where I can access the Stackframe. Basically you have here the same problems as you have with builders. I just wanted to have an alternative to them. bye blackdrag. |
|
|
Re: lisp for groovy?On 5 Jan 2006, at 18:14, Jochen Theodorou wrote: >> If your construct created a list and an instance of a metaclass >> then the list could be a list of names, values and tokens. >> {<select * from table where foo = bar>} > > what is this "<" and ">" here? new syntax? Yes because we are creating something other than a list we are creating a list and a metaclass. You proposal changes syntax too:) > >> This would create a list [new Name("select"), new Token("*"), new >> Name ("from"), ......] and a metaclass instance capable of >> resolving names at the point when the list is created (i.e. much >> like the metaclass for a closure). > > what about local variables? metaclass can't resolve them. And how > builds the list? the Compiler?, ok.. but then, why is that better > than using symbols? I like Demis idea of "unescaping" the variables > much better. Local variables are in exactly the same way as in Closure. That is to say they are moved onto the heap. If a name is used which matches a local variable then this transformation is performed. If the DSL uses that name as a symbol then the generated accessor is never used. No great loss. > >> The DSL looks at each name and can tell if it is a symbol or a >> variable name (as it knows the spelling of all the symbols it >> supports). > > But that doen't solve the problem with local variables See above. > >> Variables which refer to local on stack values are handled in >> exactly the same way as with closures. > > to do this I have to know "at compile time" what is a variable and > what not. This isn't Ruby where I can access the Stackframe. > Basically you have here the same problems as you have with > builders. I just wanted to have an alternative to them. No you don't have to now what's a variable and what a symbol at compile time. The DSL implementation knows at run time which name is a symbol and which is not. It uses the metaclass to access properties and call methods/closures just like the normal Groovy runtime. It's really a very small change to implement this. I can actually do it by a source transform in a script: dsl = {< if a > b then c = 1 >} goes to dsl = { if (false) [a, b, c] // make sure these names can be resolved via the closure's metaclass new DslHelper(metaclass, [new Name("if"), new Name("a"), new Token (">"), new Name("b"), new Name("then"), new Name("c"), new Token ("="), 1]) }() John Wilson The Wilson Partnership http://www.wilson.co.uk |
|
|
Re: lisp for groovy?John Wilson schrieb:
> > On 5 Jan 2006, at 18:14, Jochen Theodorou wrote: > >>> If your construct created a list and an instance of a metaclass >>> then the list could be a list of names, values and tokens. >>> {<select * from table where foo = bar>} >> >> what is this "<" and ">" here? new syntax? > > Yes because we are creating something other than a list we are creating > a list and a metaclass. You proposal changes syntax too:) it's not that, just wanted to be sure I didn't miss something ;) [...] > I can actually do it > by a source transform in a script: > > dsl = {< if a > b then c = 1 >} > > goes to > > dsl = { > if (false) [a, b, c] // make sure these names can be resolved via > the closure's metaclass > > new DslHelper(metaclass, [new Name("if"), new Name("a"), new Token > (">"), new Name("b"), new Name("then"), new Name("c"), new Token ("="), 1]) > }() how about this one? def dsl = {< if x > y then z = 1 >} goes to def dslList = [#if #x #> #y #then #z #= #1] and is used this way: def dsl = dslList.execute(x:a,y:b) println dsl.z I used #if short for Name and #> short for Token. the concept is a little different, as there are now bound and unbound variables besides the dsl elements. I can decide what to use for the evaluation and I can reuse the expression for different scopes without rewriting it. bye blackdrag |
|
|
Re: lisp for groovy?On 5 Jan 2006, at 20:13, Jochen Theodorou wrote: > how about this one? > > def dsl = {< if x > y then z = 1 >} > > goes to > > def dslList = [#if #x #> #y #then #z #= #1] > > and is used this way: > > def dsl = dslList.execute(x:a,y:b) > println dsl.z > > I used #if short for Name and #> short for Token. > > the concept is a little different, as there are now bound and > unbound variables besides the dsl elements. I can decide what to > use for the evaluation and I can reuse the expression for different > scopes without rewriting it. That looks perfectly fine. The metaclass can easily handle the binding of x to a and y to b. You may even have reinvented the delegate :)) John Wilson The Wilson Partnership http://www.wilson.co.uk |
|
|
Re: lisp for groovy?ok a minor point, but i still think the syntax could be more
welcoming as i think this bit will hurt readability: {< if x > ... maybe something like: def dsl = <[ if x > y then z = 1 ]> Cheers, Demis On 5 Jan 2006, at 20:56, John Wilson wrote: > > On 5 Jan 2006, at 20:13, Jochen Theodorou wrote: > >> how about this one? >> >> def dsl = {< if x > y then z = 1 >} >> >> goes to >> >> def dslList = [#if #x #> #y #then #z #= #1] >> >> and is used this way: >> >> def dsl = dslList.execute(x:a,y:b) >> println dsl.z >> >> I used #if short for Name and #> short for Token. >> >> the concept is a little different, as there are now bound and >> unbound variables besides the dsl elements. I can decide what to >> use for the evaluation and I can reuse the expression for >> different scopes without rewriting it. > > > That looks perfectly fine. The metaclass can easily handle the > binding of x to a and y to b. > > You may even have reinvented the delegate :)) > > > John Wilson > The Wilson Partnership > http://www.wilson.co.uk > > |
|
|
Re: lisp for groovy?Jochen Theodorou schrieb:
> Hi, > > my proposal may be a little bit odd in the result, but I really think it > could be very useful. My proposal consists of 3 Points > > 1) no top-level statements in lists > 2) new Token "°" or something different to make a symbol out of a > identifier > 3) remove "," from lists or make them optional > > this enables us to make list like this one: > > [°select "*" °from table °where foo "=" bar] > > table, foo and bar are handled as varibales > all tokens prefixed with ° are symbols, for this a new class > groovy.lang.Symbol will be created, which contains the property name, to > get the name of the symbol. I had secound thoughts about this... in http://blackdragsview.blogspot.com/2006/08/beyond-groovy-10-groovy-goes-lisp.html I described a theoretic Lisp system in Groovy, but there is something that we could use for DSLs as well. first, removing "," seems to be essential to me here. not just in Lists, but in general. Having a line like select "*" from table where foo "==" bar inside a builder, would allows us to return a Symbol, every time we meet a Property that is no local variable. "select" woudl be a method then and the above would be a short form of: select("*",new Symbol("from"),table,new Symbol("where"), foo, "==", bar) The job of resolving a name as symbol or local variable does the compiler, by forcing all local variables to be just that and no symbols. the job of finding out if a symbol is a Property of some sort or not, is a job for the builder and can be done at runtime. the builder can handle all names as symbols first and evaluate them later too. The bad thing is, that the operator characters can't be symbols. but we could rewrite our clause as: select all from table where foo is bar "all" and "is" are then symbols for the operators and the method can use the names to convert them into the operations, just as it would do with the operators as strings. So even without using closures explicitly here, we can have dsls with just the two changes to remove "," and to let the builder return symbols instead of the properties. The code would then look like: def table = "Customer" def foo = "id" def bar = "1000" def query = sqlbuilder.query{ select all from table where foo is bar } But I won't stop here... Knowing this we can let the IDE add code completion for the DSL too. Not automatic though, maybe if we add a syntax file for it... but anyway, that is possible. Parsing the DSL is of course still a job for the evaluating method then. The method needs to decide if a symbol is expected and if the symbol should get the value of a Property. Thinking about it... if (foo) {} else {} is also a kind of DSL. Such constructs would be expressable then, adding new ones too. Of course returning a symbol in general maybe no so good decision, we would use the MissingPropertyException then. Anyway, the goal to get DSLs is easily reachable through symbolic computing. Ah, yes, sideeffects... blocks must be bound always to the method before. That is not much different than we do already. A labled block would not be bound. The difference is that when haveing more than one block, we automatically know that they are all closures and that they belong to the same method. Btw, def query = sqlbuilder.query{ select all,from,table,where,foo,is,bar } is already possible. Thoughts? bye blackdrag -- Jochen Theodorou Groovy Tech Lead http://blackdragsview.blogspot.com/ --------------------------------------------------------------------- To unsubscribe from this list please visit: http://xircles.codehaus.org/manage_email |
| Free embeddable forum powered by Nabble | Forum Help |