Groovy: tap vs with

Viewed 1806

Groovy has tapand with functions. What is the difference between them

def user = new User('john', 1)
        .tap {userService.save(it)}

def user2 = new User('Alex', 2)
        .with {userService.save(it)}

userService updates the record and returns updated record.

class UserService {
    public User save(final User user) {
        // save user
        return updated // Id, lastmodified and other fields can be updated.
    }
}
3 Answers

tap always returns it no matter having a return statement or not but with will return the result of the last statement or statement that you explicitly return.

In your question, user will always the same object as created by new statement. However, user2 will be the return value of userService.save(it)

Chayne's answer really covers it and we should leave it as accepted, but I figured I would add an answer to "why do we in fact have two different methods".

With tap you can do things like:

def u = new User().tap {
  firstName = "Brother"
  lastName = "Bob"
}

without having to explicitly return it as you would have to with with:

def u = new User().with {
  firstName = "Brother"
  lastName = "Bob"
  it
}

with has been part of groovy for a long time, tap is a newer addition and it is explicitly there to support this kind of "return the modified object" pattern.

Now that we have tap, it leaves with as more appropriate in side effecting scenarios like this:

server.with {
    name = application.name
    status = status
    sessionCount = 3
    start()
    stop()
}

(example shamelessly stolen from the groovy docs)

where we are uninterested in the return value and just want to perform some operations on an object.

To further confuse things, it turns out that groovy has added a variant of with with a boolean argument with(boolean returnIt) where xxx.with(true) {} will get you the behavior of tap above and xxx.with(false) {} will give you the behavior of with without the argument.

If userService.save(it) returns a boolean then user will be a User and user2 will be a boolean

Related