Skip to end of metadata
Go to start of metadata

It's be great to use groovy syntax to define new Groovy methods.

We'll probably need to use some kind of module feature for this.

e.g.

Then later on we could use this module via

How it works

A module would be converted into a kind of class which implements some marker interface called 'Module' which could then use a static initializer to register the new methods on the MetaClass /MetaClass registry.

Issues

A simple implementation is for each use to install the new methods. If clashes or ordering issues happen we may want a way to have local copies of the MetaClass / MetaClassRegistry.

We could maybe have a static MetaClassRegistry instance inside each Module class which could be referenced in the bytecode explicitly when we invoke methods.

Then the class we compile with the use statements could store a static final reference to this MetaClassRegistry and refer to it when performing dynamic method dispatches.

We could also use this mechansims to add static (global) methods to the Module too. Another posibility is to apply pointcuts to a Module so we could use the Module abstraction for adding AOP advice?

  • No labels

9 Comments

  1. We should use the class form if we are also going to allow the addition of properties, etc. If its just methods, I think the method form is superior. There should be a default set of "use" statements that are implicit in all classes/scripts:

    1) use whatever the default groovy module will be
    2) use current package.GroovyMethods

    I think that you should be able to chain modules as well. So if there are "use" statements in a module, those methods will be available to anyone that uses the top level module.

  2. Additionally, it might be nice for scripts to have a different set of "use" methods to make scripting like functionality easier to use. For instance, we might have a global "exec" method. Oh that reminds me, there needs to be a way to make methods like println as well.

  3. Suggestion from another java programmer to make the whole thing look more Java like:

    definition side:

    package bash;

    class BashFile augments java.io.File {
    void leftShift(File f)

    Unknown macro: { // copy f to this }

    }

    use side:

    use bash.*

    new File("dest.txt") << new File("src.txt")

    This way we don't have to create a new top-level type and it looks a little more like java and a little more like imports.

  4. I like the "augments' syntax. It's very clear.

  5. As long as these changes are just adding extra (static) methods to the class (like DefaultGroovyMethods) does now, we should make sure that these extra methods only apply in classes you want them to. i.e. two different classes could add the same method to String, without affecting each other. I don't know how this will work, but if there are conflicts like this the feature wont scale.

    I think this is basically what Sam's example shows. i.e. only the class with "use bash.*", gets the see this new File method.

  6. I don't like use keyword.

    I suggest finding extension class using classloader. For example, it we want to extends Collection, we create class (Java or Groovy does not matter) ru/mx1/groovy/util/CollectionSuperDuperExtension.java

    then we create file META-INF/groovy/class-ext/java.util.Collection

    and pack both into one jar (collection-extensions.jar). Groovy would ask classloader for resource META-INF/groovy/class-ext/<class-name> to find the name of extension class.

    After that we just drop this jar into classpath and use groovy as usually:

  7. Would the classloader approach make it difficult (/messy/complex) to do this inside an IDE, or in another environment where your code isn't inside a Jar (or classes aren't loaded by the default classloader)?

    It also doesn't allow you the granularity that the "use" keyword allows in that you'd have extensions defined at the jar level rather than the class level - I'm guessing that in practice this wouldn't usually be too restrictive, though.

    I'd say either way is something new to Java, so why not have a keyword rather than a classloader extension... maybe "use" is too generic (like "import") though?

  8. to Rob Newsome:

    You code not need to be in Jar file. Extension classes and their descriptors must be inside same Jar. And you need to have this Jar in classpath.

    And it is not quite new, there is similar technique "Service provider" in Jar file http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider , it is used, for example to look up XML implementations (in Xerces, in particlar).

    I don't want to use explicit use statement to use extensions it provided one or two times. See:

    And. I think suggested use syntax is not very useful, it can be simply avoided with

  9. Ahhhhhhh I see... sorry, misunderstood.

    It would mean that extensions would be fairly global and it wouldn't be obvious what you're using - usually in Java you can be pretty confident you know what non-core classes/methods you're using in your code based on what imports you have at the top of the class. This would mean that it would depend on what's on the classpath. Which you would still have with an explicit import facility. Don't know how much this matters to people though.

    Perhaps there's also scope with this system for the same extension method to be declared in two places on the classpath? In which case with some sort of explicit import you'd perhaps be able to warn/error.