Search code examples
groovystack-overflow

Stack Overflow error while finding common elements between two lists


I have this code:

def input1 = ['a','b','e','r','t']
input2 = ['v','n','m','y']
ans = []

def common(def element,def i) {
  if (element == input2[i]) {
    ans << element
    return
  } else {
    common(element,++i)
  }
}  

for (i=0;i<input1.size();i++) {
  common(input1[i],0)
}

which is generating Stack Overflow error. Why is this happening?

Edit:

I'm trying to create my own way of finding common element between two lists.


Solution

  • You never check if i is greater than the length of input2, and in Groovy, getting beyond the length of a List returns null

    So on the first element, it will keep looping round

    if (element == input2[i]) {
    

    for ever-increasing values of i, calling the common function every time, as it never matches a

    Guessing at what you are trying to do, this can all be re-written as:

    def input1 = ['a','b','e','r','t']
    def input2 = ['v','n','m','y']
    def ans = input1.intersect( input2 )
    

    But it's hard to be sure what you want, and you dont explicitly say.

    Edit

    One method of deep recursion that avoids Stack Overflows is to use Groovy's trampoline method.

    def common
    common = { Object element, Collection list ->
      if( list.size() == 0 ) {                     // element not found.  Return null
        null
      }
      else if( list.head() == element ) {          // element found.  Return it
        element
      }
      else {
        common.trampoline( element, list.tail() )  // Trampoline down the list and check again
      }
    }
    common = common.trampoline()
    
    def elements = ['a','b','e','v','r','t'].collect { // For each element in this list
                     common( it, ['v','n','m','y'] )   // Find if it's in our other list
                   }.findAll()                         // And remove the nulls
    
    assert elements == [ 'v' ]
    

    But I'd still use intersect in this case, the above is just to show one of Groovy's ways you can avoid too-deep recursion...