In the following piece of code (taken from the Groovy Semantics Manual page), why prefix the assignment with the keyword def?
def x = 0
def y = 5
while ( y-- > 0 ) {
println "" + x + " " + y
x++
}
assert x == 5
The def keyword can be removed, and this snippet would produce the same results. So what's the effect of the keyword def ?
It's syntactic sugar for basic scripts. Omitting the "def" keyword puts the variable in the bindings for the current script and groovy treats it (mostly) like a globally scoped variable:
x = 1
assert x == 1
assert this.binding.getVariable("x") == 1
Using the def keyword instead does not put the variable in the scripts bindings:
def y = 2
assert y == 2
try {
this.binding.getVariable("y")
} catch (groovy.lang.MissingPropertyException e) {
println "error caught"
}
Prints: "error caught"
Using the def keyword in larger programs is important as it helps define the scope in which the variable can be found and can help preserve encapsulation.
If you define a method in your script, it won't have access to the variables that are created with "def" in the body of the main script as they aren't in scope:
x = 1
def y = 2
public bar() {
assert x == 1
try {
assert y == 2
} catch (groovy.lang.MissingPropertyException e) {
println "error caught"
}
}
bar()
prints "error caught"
The "y" variable isn't in scope inside the function. "x" is in scope as groovy will check the bindings of the current script for the variable. As I said earlier, this is simply syntactic sugar to make quick and dirty scripts quicker to type out (often one liners).
Good practice in larger scripts is to always use the "def" keyword so you don't run into strange scoping issues or interfere with variables you don't intend to.
Ted's answer is excellent for scripts; Ben's answer is standard for classes.
As Ben says, think of it as "Object" -- but it is much cooler in that it does not constrain you to the Object methods. This has neat implications with respect to imports.
e.g. In this snippet I have to import FileChannel
// Groovy imports java.io.* and java.util.* automatically
// but not java.nio.*
import java.nio.channels.*
class Foo {
public void bar() {
FileChannel channel = new FileInputStream('Test.groovy').getChannel()
println channel.toString()
}
}
new Foo().bar()
e.g. But here I can just 'wing it' as long as everything is on the classpath
// Groovy imports java.io.* and java.util.* automatically
// but not java.nio.*
class Foo {
public void bar() {
def channel = new FileInputStream('Test.groovy').getChannel()
println channel.toString()
}
}
new Foo().bar()
According to this page, def is a replacement for a type name and can simply be thought of as an alias for Object (i.e. signifying that you don't care about the type).
As far as this single script is concerned there is no practical difference.
However, variables defined using the keyword "def" are treated as local variables, that is, local to this one script. Variables without the "def" in front of them are stored in a so called binding upon first use. You can think of the binding as a general storage area for variables and closures that need to be available "between" scripts.
So, if you have two scripts and execute them with the same GroovyShell, the second script will be able to get all variables that were set in the first script without a "def".
The reason for "def" is to tell groovy that you intend to create a variable here. It's important because you don't ever want to create a variable by accident.
It's somewhat acceptable in scripts (Groovy scripts and groovysh allow you to do so), but in production code it's one of the biggest evils you can come across which is why you must define a variable with def in all actual groovy code (anything inside a class).
Here's an example of why it's bad. This will run (Without failing the assert) if you copy the following code and paste it into groovysh:
bill = 7
bi1l = bill + 3
assert bill == 7
This kind of problem can take a lot of time to find and fix--Even if it only bit you once in your life it would still cost more time than explicitly declaring the variables thousands of times throughout your career. It also becomes clear to the eye just where it's being declared, you don't have to guess.
In unimportant scripts/console input (like the groovy console) it's somewhat acceptable because the script's scope is limited. I think the only reason groovy allows you to do this in scripts is to support DSLs the way Ruby does (A bad trade-off if you ask me, but some people love the DSLs)
Actually, I don't think it would behave the same...
variables in Groovy still require declaration, just not TYPED declaration, as the right-hand side generally contains enough information for Groovy to type the variable.
When I try to use a variable that I haven't declared with def or a type, I get an error "No such property", since it assumes that I'm using a member of the class containing the code.
Related
I'm currently building a small DSL, which needs to specify a set of properties in key=value pairs, however the keys may contain dashes '-' or periods '.' and I can't seem to get it to work.
Boiled down I essentially try passing a Map as a delegate to a closure, but the syntax keeps alluring me.
As an example, consider this:
def map = [:]
map.with {
example1 = 123
//exam-ple2 = 123
//'exam-ple3' = 123
//(exam-ple4) = 123
exam.ple5 = 123
//'exam.ple6' = 123
}
Example 1 is fine, key equals value and easy readable. Examples 2 and 4 are according to the compiler a binary expression and won't compile. Examples 3 and 6 are constant expressions and won't compile. Example 5 will compile, but generate a NPE at runtime.
I can use workarounds like passing the Map as an argument to the closure, which gives me example 3 and 6, but the verbosity of it annoys me.
Does anybody have any ideas how to neatly DSL a property map?
BTW: I call the DSL from java not groovy, so tricks on the parsing side has to be java :)
UPDATE 1 : After the inital comments and answers..
So the script is evaluated by a GroovyShell as a DelegatingScript, where the delegate is a Java object. The closure contains properties from .properties files, that needs to be defined in different context, e.g.
env {
server-name=someHost1
database.name=someHost2
clientName=someHost3
}
The delegating (Java) object would read this block as
public void env(Closure closure) {
Map map = new HashMap();
closure.setDelegate(map);
closure.setResolveStrategy(Closure.DELEGATE_ONLY);
closure.call();
... do something with map...
}
Now the user (i.e. not me) will probably copy from the original property files into the script and change the names, hence I would rather they could do it without having to edit too much as it is bound to cause typos..
As I stated I has also example 3 and 6 covered as well, but yes, Tim, I forgot the implicit it :)
For now I have changed the format to a string, so the DSL writes something like
env '''
server-name=someHost1
database.name=someHost2
clientName=someHost3
'''
That is, using a multi-line string instead of a closure, and then read the string and using a standard java.util.Properties:
public void env(String envString) {
Properties properties = new Properties;
properties.load(new StringReader(envString))
....etc
}
And although this works, the mix of having closures and multi-line string is the only downside for now.
In a map declaration, Groovy parses identifiers such as example1 and example2 as string keys to a map:
[ example1: 1, example2: 2 ]
In the .with{} context, it probably uses a setProperty(property, value) mechanism.
But your case features expressions exam.ple and exam-ple. Those expressions have precedence, thus, Groovy will try to resolve them first (with probably something like exam.getProperty('ple') and exam.minus(ple), respectively).
You have some syntactic alternatives, but you will have to make it clear to Groovy what are supposed to be string keys and what are other expressions:
def map = [
'exam.ple4' : 4, // direct map declaration
example5 : 5 // unambiguous key declaration: no quotes needed
]
map.with {
example1 = 1
put 'exam.ple2', 2 // ambiguous, needs quotes
it.'exam-ple3' = 3 // as per #TimYates suggestion
}
assert map['exam-ple3'] == 3
assert map.'exam.ple2' == 2
assert map['exam.ple4'] == 4
assert map.example5 == 5 // again, no quotes needed for key
What is the command in groovy to ensure a class variable is unaffected by a closure? As we know a closure captures the environment that its wrapped in. So, if I have a closure that increments an integer class variable for example, then that variable is changed for the class. What I want is for a closure to have its own copy of a variable so it does not affect the class variable. Is it possible? In Objective C for example we would use the __Block command and that would make the block be able to change the value of a captured variable. Now, I am asking for the opposite of __Block in my case as closures are already changing the variables they are scoped in.
Lets take a look at a clear example of what I want:
def class myCoolClass {
def x=1
def myMethodThatReturnsClosure(){
//lets return a closure who's scope will include the x=1
myClosure
}
def showMeXFromMyCoolClass(){
println "this is x from myCoolClass:$x"
}
def myClosure={
println "im printing x:$x"
//lets change x now from within closure
x++
}
}
def x = new myCoolClass();
def c=x.myMethodThatReturnsClosure();
c(); //we are changing x ...x = 1
c(); //we are changing x again ...x = 2
c(); //we are changing x again ...x = 3
x.showMeXFromMyCoolClass(); //...x = 4
//i dont want x to be 4 in the last call, i want x to be 1.
//i want it unchanged. how to tell closure to take its own copy
I realize in groovy a closure knows about its environment. It "closes out" around the function that its wrapped in. Is there lambda in groovy then? I think lambda would not know about its environment right? But lets say I want only want variable to not know about its environment and others should, then lambda would not be good.
Your example code is not valid Groovy syntax. You may want to debug it and update the example with the fixes. Nevertheless, you got your point across.
One way of making the closure use a copy of the class variable is to make a copy of the variable and use it instead of x in the closure.:
def myMethodThatReturnsClosure() {
def myX = x
{
println "im printing x:$myX"
myX++
}
}
This assumes the variable is a primitive, which grooy handles differently so that a copy is made. Otherwise the new variable would just be a reference to the original. In the latter case, you'd have to clone the object to get a copy.
I'm reading this: A closure looks a lot like a regular Java or Groovy code block, but actually it's not the same. The code within a regular code block (whether its a method block, static block, synchronized block, or just a block of code) is executed by the virtual machine as soon as it's encountered. With closures the statements within the curly brackets are not executed until the call() is made on the closure. In the previous example the closure is declared in line, but it's not executed at that time. It will only execute if the call() is explicitly made on the closure
And I'm thinking, how is this true, in Java if you have an instance method, the code is only executed when the method is called then how are they saying above that is executed by the VM as soon as it sees it ?
If I have a method func(){int a =5; return a+5;} this will be executed only when called is my understanding.
The description might be better taken with just synchronized block or regular scope braces. What it's attempting to show is that when the thread of execution hits a regular code block, it continues on executing the contents. With closure definitions, the code in the block is not immediately executed - it's used to define/instantiate a closure object (say, clos) which contains that logic, and which can be later executed via clos.call() (or just clos()).
example:
def x = 1
synchronized(this) {
x = 1000
}
println x //x == 1000
vs.
def x = 1
Closure clos = {
x = 1000
}
println x // x == 1
clos() // or clos.call()
println x // x == 1000
W/R/T method/static blocks: It's unclear to me if there is some nuanced way in which "encountered" and "executed" can be used in a JVM context that makes that part of the statement correct, but for practical purposes, it's at best misleading. Methods are still only executed when called, and not by virtue of their declarations being located in the apparent path of code execution, as the following can be run in groovyConsole to show:
def x = 1
void methodA() {
x = 1000
}
def b = {
x = x + 1
}
println x // x is still 1
Another analogy, which is not necessarily technically accurate, is to think about Closures as anonymous inner classes that have a single method (the body of the closure).
Doing either closure.call() or closure() (short-hand for call()), invokes that single method.
Closures have additional features, of course, but I think that this is a good way to think about the basics.
There are some other questions on here that are similar but sufficiently different that I need to pose this as a fresh question:
I have created an empty class, lets call it Test. It doesn't have any properties or methods. I then iterate through a map of key/value pairs, dynamically creating properties named for the key and containing the value... like so:
def langMap = [:]
langMap.put("Zero",0)
langMap.put("One",1)
langMap.put("Two",2)
langMap.put("Three",3)
langMap.put("Four",4)
langMap.put("Five",5)
langMap.put("Six",6)
langMap.put("Seven",7)
langMap.put("Eight",8)
langMap.put("Nine",9)
langMap.each { key,val ->
Test.metaClass."${key}" = val
}
Now I can access these from a new method created like this:
Test.metaClass.twoPlusThree = { return Two + Three }
println test.twoPlusThree()
What I would like to do though, is dynamically load a set of instructions from a String, like "Two + Three", create a method on the fly to evaluate the result, and then iteratively repeat this process for however many strings containing expressions that I happen to have.
Questions:
a) First off, is there simply a better and more elegant way to do this (Based on the info I have given) ?
b) Assuming this path is viable, what is the syntax to dynamically construct this closure from a string, where the string references variable names valid only within a method on this class?
Thanks!
I think the correct answer depends on what you're actually trying to do. Can the input string be a more complicated expression, like '(Two + Six) / Four'?
If you want to allow more complex expressions, you may want to directly evaluate the string as a Groovy expression. Inside the GroovyConsole or a Groovy script, you can directly call evaluate, which will evaluate an expression in the context of that script:
def numNames = 'Zero One Two Three Four Five Six Seven Eight Nine'.split()
// Add each numer name as a property to the script.
numNames.eachWithIndex { name, i ->
this[name] = i
}
println evaluate('(Two + Six) / Four') // -> 2
If you are not in one of those script-friendly worlds, you can use the GroovyShell class:
def numNames = 'Zero One Two Three Four Five Six Seven Eight Nine'.split()
def langMap = [:]
numNames.eachWithIndex { name, i -> langMap[name] = i }
def shell = new GroovyShell(langMap as Binding)
println shell.evaluate('(Two + Six) / Four') // -> 2
But, be aware that using eval is very risky. If the input string is user-generated, i would not recommend you going this way; the user could input something like "rm -rf /".execute(), and, depending on the privileges of the script, erase everything from wherever that script is executed. You may first validate that the input string is "safe" (maybe checking it only contains known operators, whitespaces, parentheses and number names) but i don't know if that's safe enough.
Another alternative is defining your own mini-language for those expressions and then parsing them using something like ANTLR. But, again, this really depends on what you're trying to accomplish.
I read use keyword in Groovy. But could not come out with, for what it has been exactly been used. And i also come with category classes, under this topic,what is that too? And from, Groovy In Action
class StringCalculationCategory {
static def plus(String self, String operand) {
try {
return self.toInteger() + operand.toInteger()
} catch (NumberFormatException fallback) {
return (self << operand).toString()
}
}
}
use (StringCalculationCategory) {
assert 1 == '1' + '0'
assert 2 == '1' + '1'
assert 'x1' == 'x' + '1'
}
With the above code, can anyone say what is the use of use keyword in groovy? And also what the above code does?
See the Pimp My Library Pattern for what use does.
In your case it overloads the String.add(something) operator. If both Strings can be used as integers (toInteger() doesn't throw an exception), it returns the sum of those two numbers, otherwise it returns the concatenation of the Strings.
use is useful if you have a class you don't have the source code for (eg in a library) and you want to add new methods to that class.
By the way, this post in Dustin Marx's blog Inspired by Actual Events states:
The use "keyword" is actually NOT a keyword, but is a method on
Groovy's GDK extension of the Object class and is provided via
Object.use(Category, Closure). There are numerous other methods
provided on the Groovy GDK Object that provide convenient access to
functionality and might appear like language keywords or functions
because they don't need an object's name to proceed them. I tend not
to use variables in my Groovy scripts with these names (such as is,
println, and sleep) to avoid potential readability issues.
There are other similar "keywords" that are actually methods of the Object class, such as with. The Groovy JDK documentation has a list of such methods.
A very good illustration is groovy.time.TimeCategory. When used together with use() it allows for a very clean and readable date/time declarations.
Example:
use (TimeCategory) {
final now = new Date()
final threeMonthsAgo = now - 3.months
final nextWeek = now + 1.week
}