Heschoon
Heschoon

Reputation: 3017

Recreating the if/else in groovy: giving multiple closures arguments to a function

While trying to reinvent the if/else syntax with closures in groovy, I couldn't manage to make it work. I think putting multiple closures outside the parenthesis is not permitted, but it could be something else.

If it isn't permitted, how would you reproduce the if/else syntax? This is a thought experiment, so don't tell me about the the inefficiency of this implementation.

My code:

void ifx(boolean condition, Closure action){
  ["${true.toString()}": action].get(condition.toString(), {})()
}

void ifx(boolean condition, Closure action, Closure elsex){
  ["${true.toString()}": action, "${false.toString()}": elsex].get(condition.toString())()
}

void elsex(Closure action){
    action()
}

ifx(1==2){
    println("1")
} ifx(1==3){
    println("2")
} elsex{
    println("3")
}

Error message:

java.lang.NullPointerException: Cannot invoke method ifx() on null object

Upvotes: 0

Views: 1014

Answers (2)

Will
Will

Reputation: 14559

Something along these lines works:

updated with closures to avoid global state:

def ifx( outerCondition, outerBlock ) {
  boolean matched = false
  def realIfx
  realIfx = { condition, block ->
    if (condition) {
      matched = true
      block()
    }
    [ifx: realIfx, elsex: { elseBlock -> if(!matched) elseBlock() }]
  }

  realIfx outerCondition, outerBlock
}

And some testing:

def result

ifx(1 == 2) {
  result = 1
} ifx(1 == 3) {
  result = 2
} elsex {
  result = 3
}

assert result == 3
result = null


ifx (1 == 2) {
  result = 1
} ifx (2 == 2) {
  result = 2
} elsex {
  result = 3
}

assert result == 2
result = null

ifx (true) {
  result = 1
} ifx (2 == 1) {
  result = 2
} elsex {
  result = 3
}

assert result == 1

Upvotes: 2

blackdrag
blackdrag

Reputation: 6518

ifx (1==2) {} ifx(1==3) {} elsex {} is a command chain expression translating to ifx(1==2,{}).ifx(1==3,{}).elsex({}). Since void translates to null, it should be clear that the second ifx call then fails with a NPE. To realize an if/else kind of thing I would maybe do the following

void ifx(boolean condition, Closure ifBlock, Closure elseBlock) {
 ....
}
ifx (1==2) {...}{...}

meaning not using an else keyword at all. IF you want to keep your idea, you have to return something on which you can call elsex and ifx.. Or if not ifx, then put a newline in after the first ifx

Upvotes: 1

Related Questions