3

I make myself familiar with groovy and am a little surprised that the following code runs:

class Main {
    static void main(String[] args) {
        abc : 1
    }
}

What is abc : 1 ? I think it might be a map as the following code:

class Main {

    static void main(String[] args) {
        print(abc : 1)
    }

}

leads to [abc:1] being printed to the console, but

class Main {

    static void main(String[] args) {
        def map = abc : 1
    }

}

compiles not!!! But the most confusing part is that wrapping the expression into a closure

class Main {

    static void main(String[] args) {
        def closure = {-> abc : 1}
        print closure()
    }

}    

leads to 1 being printed to the console and not [abc:1]. Is there any use of the colon I am not aware of?

Szymon Stepniak
  • 40,216
  • 10
  • 104
  • 131

1 Answers1

5

There are 2 different usage context in your example.

1. Named parameters

In the first example, you've used Groovy's named parameters. The following Groovy code:

print(abc: 1)

is an equivalent of

print([abc: 1])

Groovy uses a map to represent named arguments and this construction is available only in the method invocation. That is why when you have tried assigning abc : 1 to a variable, compilation failed with an error.

2. Labeled statements

The second example that uses a closure is an example of labeled statement. If you format your code it would look like this:

def closure = { ->
    abc:
    return 1 // return is optional of course in this case. I added it to make the example more explicit
}

print closure() // prints 1

Keep in mind that labels have no impact on the semantics of the code, that is why you get 1 in return. Labels are present in the abstract syntax tree and they can be used to manipulate the code (e.g. Spock Framework uses labels like given, when, then to add specific behavior to a test).

Szymon Stepniak
  • 40,216
  • 10
  • 104
  • 131
  • You can also use labels for shortcutting out of nested loops, ie: https://stackoverflow.com/a/886979/6509 – tim_yates Jan 05 '19 at 14:22
  • @tim_yates: Does a label only label one statement or an entire block? I would have assumed that outerloop also labels the statement 'System.out.println("Done");'. Can i break statement only escape loops and switch statements or can I also escape a labeled block of code. In the latter case I would have expected that 'Done' is not printed. – Samuel Graf Jan 05 '19 at 15:18
  • The former I believe. Using labels in this way is generally avoided as it can make code hard to understand though. I don't remember writing one in the past 5 years – tim_yates Jan 05 '19 at 15:51
  • @Szymon Stepniak: I try to summarize: \n – Samuel Graf Jan 05 '19 at 16:14
  • In my first class abc is a label for the statement: 1. Here the label is like a comment and doesn't change the outcome. In the second class abc:1 is interpreted as map. In method calls Object:Object, Object: Object, ... is always interpreted as [Object: Object, Object: Object, ...] (Remark: If the key is not set in parenthesis it is read as String, i.e 'Object'!!!). In the third class compilation fails as outside of method calls the brackets can not be omitted and one can not label parts of statements but only entire statements. Forth Class is equivalent to first One. Did I get it right? – Samuel Graf Jan 05 '19 at 16:37
  • Can you edit the question, or ask a new one? Comments are dreadful for code blocks on stackoverflow – tim_yates Jan 05 '19 at 18:54
  • I don't know how to properly answer someone in stack overflow. There is little sense in answering someone by editing my questions because it is related to this one person, or is it still the proper way? – Samuel Graf Jan 06 '19 at 15:28
  • 1
    @SamuelGraf Regarding your summarizing questions - you get it right. The 1st and 4th class from your example uses labeled statement, and as you have mentioned - it does change the outcome. The 2nd class uses named parameters (an equivalent of method expecting a single HashMap as a parameter), and the 3rd class fails to compile, because this notation in this context (assigning a value to a variable) is not valid - in this case you have to define a map using square brackets. – Szymon Stepniak Jan 06 '19 at 16:00