user7858768
user7858768

Reputation: 1026

Bash: why does 'return 0' in parenthesis doesn't exit the function

In the following bash code example. I expect return 0 to exit the function when calling the function with 0. However, the function continues forward.

ignoringReturnStatement(){
  local seconds="$1"
  [[ "$seconds" -eq "0" ]] && (echo "equals 0" && return 0 )

  echo "Didn't exit with 'return 0'"
  return 1
}
ignoringReturnStatement 0 && echo "Return code truthy" || echo "Return code falsy"

Output

equals 0
Didn't exit with 'return 0'
Return code falsy

Why in the world is return 0 ignored? Does it somehow get scoped down the just parentheses () that its in? (I am used to bash not doing much scoping down so that would be super surprising)

I could refactor this code to work as expected using more verbose if syntax:

respectingReturnStatement(){
  local seconds="$1"
  if [[ "$seconds" -eq "0" ]]; then
     echo "equals 0"
     return 0
  fi

  echo "Didn't exit with 'return 0'"
  return 1
}
respectingReturnStatement 0 && echo "Return code truthy" || echo "Return code falsy"

But why does && (... return 0) syntax not work here?

Upvotes: 1

Views: 411

Answers (1)

chepner
chepner

Reputation: 531798

It's not being ignored; it's executing in a subshell. It's not immediately obvious to me if it fails, because it's not being used in a function in that shell, or if it "returns" from that subshell to the function.

To fix this, use {...}, not (...), so that return executes in the same shell as the rest of the function.

foo (){
  local seconds="$1"
  [[ "$seconds" -eq "0" ]] && { echo "equals 0"; return 0; }

  echo "Didn't exit with 'return 0'"
  return 1
}

There's little reason to use && over ;, since you want to return even if, for some rare reason, echo fails.

Upvotes: 3

Related Questions