-4

For the lab problem of insects combinatorics, below is my solution using tree recursion:

func Paths(m int, n int) int {
    length := m
    width := n

    var f func(int, int) int

    f = func(h int, v int) int {
        if h == width && v == length {
            return 1
        } else if h < width && v < length {
            return f(h, v+1) + f(h+1, v)
        } else if v < length {
            return f(h, v+1)
        } else if h < width {
            return f(h+1, v)
        } /*else { // this condition doesn't occur
            return 0
        }*/
    } // Line 19

    return f(1, 1)
}

else block is not required(invalid) for above solution, but compiler gives missing return error at Line 19

How to avoid missing return error for above code?

overexchange
  • 15,768
  • 30
  • 152
  • 347
  • 4
    "How to avoid missing return error" --- every function path should end with `return`. So, to avoid it - you should `return` an integer. – zerkms Jun 05 '20 at 07:19
  • 2
    For one thing, it’s far from obvious that the condition can’t occur (in fact, it’s trivial to create cases where it *does* occur, e.g. `Paths(0, 0)`): Go is right to complain. If *you* are somehow sure, rewrite the code to make it obvious. For another, are you sure there’s no bug in your conditional? You sometimes compare `h` to `length` and sometimes to `width` (and vice-versa for `v`). Without knowing the problem you’re solving that seems a priori unlikely. – Konrad Rudolph Jun 05 '20 at 08:15
  • Not related to your question, but there's no reason to ever do `return } else`. Just delete the else. – Jonathan Hall Jun 05 '20 at 08:16
  • @KonradRudolph Hey you are right `h` should always be compared with `width`. Query edited.. Typo – overexchange Jun 05 '20 at 08:48

2 Answers2

3

Go doesn't know that // this condition doesn't occur, and when analyzing your code, it sees that if none of the conditions of the if statements are satisfied, it's missing a return value.

One way to "fix" this is to do something like panic("does not occur"). I dislike that, though, as throughout the years I've encountered way too many log entries saying "does not occur"...

Alternatively, you could use what is probably a more natural approach in Go:

if cond1 {
  return v1
}
if cond2 {
  return v2
}
//... other cases ... 
return v3

Or maybe even a switch statement:

switch {
case cond1:
  return v1
case cond2:
  return v2
//... other cases ... 
default:
  return v3
} 

The "else if"s you're using are unnecessary, as each case results in the function returning immediately. Check Effective Go to read about this pattern. It's used all around in the standard library, too (ie, avoiding unnecessary else's).

Also, since you said that there's absolutely no way that all the conditions would be false, there's no need to test the last one: it's the "else" case.

Bruno Reis
  • 37,201
  • 11
  • 119
  • 156
0

You are expressly stating that the function f returns an int, and the problem is there are scenarios in this function whereby the condition is not meet any of your if...elseif conditions:

package main

import "fmt"

func main() {
    fmt.Println(Paths(0, 0))
    fmt.Println(Paths(1, 0))
    fmt.Println(Paths(0, 1))
}

func Paths(m int, n int) int {
    length := m
    width := n

    var f func(int, int) int

    f = func(h int, v int) int {
        if h == length && v == width {
            return 1
        } else if h < width && v < width {
            return f(h, v+1) + f(h+1, v)
        } else if v < length {
            return f(h, v+1)
        } else if h < width {
            return f(h+1, v)
        } else { // this condition does occur
            return 0
        }
    } // Line 19

    return f(1, 1)
}

So these scenarios are allowed by the function. You might validate these values before entering this function, but the problem is this function does not do any of that, and it is valid to pass those values through.

If you are confident that 0,0; 0,1; and 1,0 will not be the input values, you can avoid the last else if h < width { by just having an else; however this will change the logic of the function. Given, also, that the function Paths is exported, you should probably do validation on the values coming in, if you need to ensure that the 0,0; 0,1; and 1;0 options are not permissible.

If it suits your purpose, you could just have a return right at the end of the function, for returning 0 or -1 to indicate that the value is incorrect. Personally, if these values are not acceptable in the function, it would be best to validate the input and return an error or if you must, panic.

func Paths(m int, n int) int {
    length := m
    width := n

    var f func(int, int) int

    f = func(h int, v int) int {
        if h == length && v == width {
            return 1
        } else if h < width && v < width {
            return f(h, v+1) + f(h+1, v)
        } else if v < length {
            return f(h, v+1)
        } else if h < width {
            return f(h+1, v)
        }

        return 0
    }

    return f(1, 1)
}
Raymond Jones
  • 112
  • 1
  • 3
  • 8
  • 1
    People who downvote an answer **really** should leave an explanatory comment, especially when the answer is as thoughtful as this. – Konrad Rudolph Jun 05 '20 at 08:42
  • 1
    @KonradRudolph Hey... I didn't downvote, but that was typo.. `h` should always be compared with `width`... It was typo. i don't think we need an answer for recorrecting `h` comparsion with `width`. I think `return 0` at the end is actually misleading conceptually, except satisfying the GO syntax. We should remove it – overexchange Jun 05 '20 at 08:51