What does curly brackets syntax mean in Groovy?
Asked Answered
C

1

14

What does this syntax mean in Groovy?

class CreateMessagePage extends Page {
    static at = { assert title == 'Messages : Create'; true }
    static url = 'messages/form'
    static content =  {
        submit { $('input[type=submit]') }
        MyVeryStrangeForm { $('form') }
        errors(required:false) { $('label.error, .alert-error')?.text() }
    }
}

(taken from Spring MVC Test HtmlUnit manual)

The question is about Groovy and I would like know the answer in Groovy terms.

What is content? Is it a static variable? Is its name is random or predefined by base class of Page?

What is = (equal sign) after it? Is it an assignment operator?

What is at the right hand side of =? Is this a closure? Or if this an anonymous class? Or if these are the same?

What is submit inside curly braces?

Is this a variable? Why there is no assignment operator after it then?

Is this a function definition? Can I define functions in arbitrary places in Groovy? If this is a function definition, then what is errors then?

Is submit is a function call, receiving { $('input[type=submit]') } as a parameter? If yes, then where is this function can be defined? For example, where is MyVeryStrangeForm defined (is nowhere)?

If this was function call, then it won't work since it's undefined...

Claycomb answered 7/1, 2016 at 15:47 Comment(0)
P
19

Quick answer to all questions: it's a block of code, like anonymous function, called closure in Groovy.

See http://www.groovy-lang.org/closures.html

In Groovy you can reference/pass/set such closure, as in any Functional Language.

So this:

static at = { assert title == 'Messages : Create'; true }

means that class field at will be set to this closure (notice, not result of closure execution, but closure itself, as block of code). Type of at is omitted there, but it could be static def at or static Object at, or static Closure at

This code could be executed anytime later, in different context, with title defined, etc.

This:

submit { $('input[type=submit]') }

means calling a function submit with closure as argument.

If you want to write own function like this, it should be something like:

def submit(Closure code) {
    code.call()
}

Brackets could be omitted, so it could be written as submit({$('input[type=submit]')}). Same for other function as well, it could be println 'hello world!' instead of println('hello world').

There's also a common practice to define closure as last argument, like:

def errors(Map opts, Closure code) {
  ....
}

at this case you could pass first arguments as usual, wrapped in brackets, and closure outside:

errors(required:false) { ...... }

same to:

errors([required: false], { ..... })
Phenetole answered 7/1, 2016 at 16:48 Comment(11)
By why it didn't written form = { $('form') } but form { $('form') }, i.e. without assignment?Claycomb
I mean I would understand this if it would always written "as in any functional language"Claycomb
This is not calling function because I am allowed to write my own names there!Claycomb
you should delegate them into closure, please read link to official docsPhenetole
Are you absolutely sure it is function call? May be it is some Geb DSL?Claycomb
what's the difference? Groovy DSL is usually done through closures and functions calls. So it's both, DSL and function callPhenetole
I don't understand how it can be function call if I can use arbitrary name. Where the function is defined? There are all possible function names pre-defined in Groovy somewhere?Claycomb
oh, i see, you mean where this submit are defined? I guess this ones just catched by methodMissing of the closure delegatePhenetole
just checked sources: github.com/geb/geb/blob/master/module/geb-core/src/main/groovy/… that's true, this is processed by methodMissingPhenetole
So this is a call to undefined function, which is processed in special way by base class?Claycomb
yes, in groovy you can handle call of non existing function.Phenetole

© 2022 - 2024 — McMap. All rights reserved.