Skip to end of metadata
Go to start of metadata

Abstract

  • No need for a syntax difference between simple closures and markup closures.
  • No need for another breaking change that our users would have to bear.

Why a breaking change for markup?

James' proposal introduces a breaking syntactical change to differentiate markup and non-markup closures. Because supposedly static typing could not be preserved without that. But I think this is a misleading statement, and here's why...

Groovy roots with a pinch of humour

Groovy is a dynamic scripting language which can also support static typing. In the expression "dynamic scripting language", there's "dynamic". However, some have been favouring static typing over dynamic and duck typing. And they want to relegate dynamic features aside, in quarantine, as if it were the new plague of the language. Although I firmly believe everyone can live in peace together without anyone left on the side of the road.

I think James' proposal tries to address a problem which doesn't really exist – or at least that can be solved thanks to other mechanisms we've already decided to implement in the JSR. Moreover, it'd introduce a breaking change in people's code by requiring to use a special syntax to support markup closures.

Main concerns about static typing

  1. we'd like to be able to do code-completion in IDEs,
  2. we'd want IDEs to support refactoring of Groovy code source too,
  3. we would also like our users to be aware of the presence of potentially different rules in markup closures,

First of all, at the meeting, we've all agreed we needed a more powerful Meta-Object Protocol which would give us more control on what's called and from where, thanks to more context.

Furthermore, we've also decided that an introspection API is needed. As long as we're using static typing, this introspection API, which will be available from the MetaClass, can tell IDEs and the compiler what names are possible for a given object. And of course, local names can easily be completed without that.

That is, at compile-time or at the time the user writes his code, the methods, properties and fields are known, hence, code-completion (1) and refactoring (2) can be provided by your IDE. Even for builders with static names or with an infinite number of names with a subset of known names.

And eventually, since the user is smart, he knows when using a builder the rules might be a little different. Which makes (3) a non-existing problem. A programmer will never use a method at random, as if he'd not know what a given method was supposed to do.

Problems with the new syntax construct

  • it will break people's code, because they will have to support the new syntax for markup,
  • even with the syntax difference, automatic refactoring can't always be achieved without the risk of breaking code, that's why IDEs often require some feedback from the user to decide what's exactly to be done,
  • it makes me think he believes our users are not smart enough to know that they are using a builder in their code.

Other alternative

Furthermore, if we really want the compiler to not check for names at all for some reason, I think we should use the "dynamic" or "@Dynamic" annotation/keyword at the class or at the method level – that we've discussed at the meeting – to warn the compiler that we really don't want it to check any name. Such a marker/annotation would be definitely more pleasant to read. It'd be an "addition" to the language, and not a breaking change.

Conclusion

All the potential problems James' proposal addresses can be solved easily simply because through the new MOP and through the introspection API we'll design, we'll have everything we need for code-completion, or for refactoring. And it doesn't diserve introducing a new code construct and to break all the usages of builders for problems which are no real problems.

So, in conclusion, we should take actions towards focusing on thinking about the MOP and the introspection API. That's how things we'll become clearer to all of us. While designing these parts, we'll know if this syntax change is needed or not. And I suspect it will not even be needed at all as explained above.

  • No labels

9 Comments

  1. My proposal was to do with name resolution, not to do with being static or dynamic.

    Dynamic languages like Smalltalk, Ruby and Python have sane & simple to follow name resolution rules - currently Groovy's are a mess purely because of Markup which is why I tried to fix this with my proposal.

    Take a look at Closures in Smalltalk and Ruby - those are what we were meant to have in Groovy but they got broken along the way by hacking in Markup into the same language concept.

    What I want is to have real closures back like Smalltalk/Ruby - and to support Markup too for when new name resolution policies are required.

    I still see no argument for why we should not implement true Closure support. Its got nothing to do with static typing or refactoring.

  2. Guillaume: if a closure's metaclass can be changed arbitrarily, how will an IDE be able to deduce which metaclass to query to which names any given closure can handle?

    James: The weightiest argument I see against true (or "textbook") closure support is that introducing it would break existing code. I agree with you that the markup/closure mix we currently have is a mess with respect to name resolution, but perhaps now is not the time to fix it.

  3. Alan: if we don't fix it now as part of the JSR its never gonna be fixed and the name resolution in Groovy will be horribly broken forever. The proposal is a minor change to scripts using markup (and leaves closure syntax which is way more common) intact.

  4. James: other languages evolve in incompatible ways. Python has a mechanism ("from future import <new feature>") for introducing breaking changes over the course of several dot-releases. Groovy could do something similar, and then we could evolve whenever we wanted to.

    I'll post a quick discusson of an incompatible-change mechanism for Groovy 1.1 as soon as I get a moment.

  5. Alan: in fact, we won't change metaclasses of objects (as we still can do currently), but we'll create new instances with a new metaclass through some become(MetaClass mc) method which will deprecate setMetaClass(mc). So the benefit is that you will be able to know what's the metaclass of a given object – even in some cases of dynamic typing!

    James: I don't see why we couldn't have sane and simple name resolution in Groovy. You'll have to re-read John's take on that topic. It's very simple in fact. And this wiki page was mostly to address the concerns you kept repeating at the meeting, nothing more, I don't claim to cover all the topics in that page – and particularly how name resolution should actually work.

  6. Guillaume: read the title of my propsal (smile)

  7. James: Then I wonder why you're speaking of syntax changes if it's just about name resolution. And I also wonder why you were concerned with refactoring and code-completion.

    We can have very simple rules for name resolution, yet allowing us to have lexical closures. You should have a closer look at John's email on that topic – and provide your feedback:

    http://article.gmane.org/gmane.comp.lang.groovy.jsr/1289

    I don't think we can have anything simpler than that: easy to understand, easy to remember.

  8. The reason I'm talking of syntax changes is because the name resolution rules for Closures are completely different from Markup.

  9. Note that John's proposal is fine for Markup but it does not match the name resolution mechanism for Closures in any languages like lisp, smalltalk, ruby et al. Closures are very well known and used concepts in other languages which we should support in Groovy IMHO.

    I keep saying it but you keep not hearing it - Closures name resolution in Groovy is completely broken - we don't have real closures any more since we hacked the closure syntax to support builders which was a massive mistake.

    I want to fix that for 1.0 otherwise we've a horribly broken language.