No Stack Level Too Deep

Build Status

Simple way to avoid stack level too deep

Installation

# Gemfile
gem 'no_sltd'
$ gem install no_sltd

Usage

def my_recursive_func
  ...
end

# ↓ just add `no_sltd` before `def`

require 'no_sltd'
no_sltd def my_recursive_func
  ...
end

or

def my_recursive_func
  ...
  my_recursive_func
  ...
end

# ↓ wrap the recursive function call with `no_sltd { }`

require 'no_sltd'
def my_recursive_func
  ...
  no_sltd { my_recursive_func }
  ...
end

examples

def sum_up n
  return 1 if n == 1
  sum_up(n-1) + n
end
sum_up 100000 #=> stack level too deep

# ↓↓↓↓

no_sltd def sum_up n
  return 1 if n == 1
  sum_up(n-1) + n
end
sum_up 100000 #=> 5000050000
def fibonacci a, memo={0 => 0, 1 => 1}
  return memo[a] if memo[a]
  memo[a] = fibonacci(a-1, memo) + fibonacci(a-2, memo)
end
fibonacci 100000 #=> stack level too deep

# ↓↓↓↓

no_sltd def fibonacci a, memo={0 => 0, 1 => 1}
  return memo[a] if memo[a]
  memo[a] = fibonacci(a-1, memo) + fibonacci(a-2, memo)
end
fibonacci 100000 #=> 2597406934722172......
fact = lambda do |n|
  n.zero? ? 1 : n * fact.call(n-1)
end
fact.call 10000 #=> stack level too deep

# pass the proc to `no_sltd`
fact = no_sltd ->(n) {
  n.zero? ? 1 : n * fact.call(n-1)
}
fact.call 10000 #=> 2846259680917054......

# or wrap the recursive call with `no_sltd { }`
fact = lambda do |n|
  n.zero? ? 1 : n * no_sltd { fact.call(n-1) }
end
fact.call 10000 #=> 2846259680917054......

Pros

  • simple & easy

Cons

  • memory eater
  • slow