Le 2015-10-28 à 21:40, Edinson E. Padrón Urdaneta <edinson.padron.urdaneta@gmail.com> a écrit :

I'm sorry mate. That happens when you code at midnight in a polluted groovysh. Try this out:


I don’t know what you are talking about ;-)

def check(condition) {
  // Define and initialize a new map
  def map = [:]

  // Replace the `is` method from the map's metaclass
  map.getMetaClass().is = { bool ->
      println "checking if $condition yields $bool, with 'is'"
  }

  // Return the map
  map
}



Brillant !  I have to say I'm surprised that `map.getMetaClass().is = ...` only changes that map's metaClass, i.e. I expected it to change the `metaClass` instance of the `Map` class, not the `metaClass` instance of a (single) `Map` instance.  

I wonder if this is an accident or designed that way ?

If it is by design, then that's very good for the purpose of a dsl as 1) `is` can then be used, 2) with your technique, the metaclass manipulation is local to the Map instance created in the chained method definition, therefore I don't have to compromise on hiding Groovy to my DSL (as Jason explained).

In summary, to support the command expression

   every 'member' of 'family' is 'adult'

my chained method definition is :

def every(member) {
    [of: { what ->
        def map = [:]
        map.getMetaClass().is = { value ->
           println "every - of - is : $member, $what, $value"
        }
        map
    }]
}

Running it yields the expected result :

every - of - is : member, family, adult

Granted, writing the chained method definition is a little more tricky, partly because one have to be careful of dynamic scoping for `member` and `what`, but the net result is very nice.

Thank you very much for your ideas !

Marc


On Wed, Oct 28, 2015 at 8:31 PM, Marc Paquette <marcpa@mac.com> wrote:
Your suggestion seemed promising, but I can’t make it work :
1) `map.metaClass` is null
2) `map.getClass().metaClass.is = null` or `Map.metaClass.is = null` does not remove the `is` method
3) `map[is]` gives `Caught: groovy.lang.MissingPropertyException: No such property: is for class: …`

I am curious, you said « but it works », what version of groovy (groovy --version) did you use ?
 

Le 2015-10-28 à 01:08, Edinson E. Padrón Urdaneta <edinson.padron.urdaneta@gmail.com> a écrit :

If you want to use `is` in your DSL you could try:

def check(condition) {
  // Define and initialize a new map
  def map = [:]

  // Remove the `is` method from the map's metaclass
  map.metaClass.is = null

  // Add the key-value pair we care for the DSL
  map[is] = { bool ->
      println "checking if $condition yields $bool, with 'is'"
  }

  // Return the map
  map
}

I don't know if the above follows good practices or at very least is a good idea (remember that I'm very new) but it works.


On Wed, Oct 28, 2015 at 12:19 AM, Edinson E. Padrón Urdaneta <edinson.padron.urdaneta@gmail.com> wrote:
Well, I'm very new to groovy so I could be very wrong but `is` is a method of `GroovyObjectSupport`, so maybe you are invoking that method in your DSL without knowing that.

On Tue, Oct 27, 2015 at 10:47 PM, Marc Paquette <marcpa@mac.com> wrote:
Playing with DSL here (going through chapter 19 of « Groovy In Action, second edition », well worth the read).  It seems that one cannot use the word ‘is’ to build a command chain dsl, but ‘IS’ or ‘Is’ or ‘iS’ are ok… Or is it something I’m doing wrong ?

```
[marcpa@MarcPaquette dsl]$ groovy --version
Groovy Version: 2.4.3 JVM: 1.8.0_60 Vendor: Oracle Corporation OS: Mac OS X
[marcpa@MarcPaquette dsl]$ cat chainWithLowerCaseIsFails.groovy
def check(condition) {
    [is: { bool ->
        println "checking if $condition yields $bool, with 'is'"
    },
    IS: { bool ->
        println "checking if $condition yields $bool, with 'IS'"
    }]
}

cond = (1<2)
check cond is true
check cond IS true
[marcpa@MarcPaquette dsl]$ groovy chainWithLowerCaseIsFails.groovy
checking if true yields true, with 'IS'
[marcpa@MarcPaquette dsl]$
```

Marc Paquette