def product(*tuples)
      tuples = tuples.map { |tuple| Erlang.from(tuple) }
      # if no tuples passed, return "product" as in result of multiplying all elements
      return super if tuples.empty?

      tuples.unshift(self)

      if tuples.any?(&:empty?)
        return block_given? ? self : []
      end

      counters = Array.new(tuples.size, 0)

      bump_counters = lambda do
        i = tuples.size-1
        counters[i] += 1
        while counters[i] == tuples[i].size
          counters[i] = 0
          i -= 1
          return true if i == -1 # we are done
          counters[i] += 1
        end
        false # not done yet
      end
      build_array = lambda do
        array = []
        counters.each_with_index { |index,i| array << tuples[i][index] }
        array
      end

      if block_given?
        while true
          yield build_array[]
          return self if bump_counters[]
        end
      else
        result = []
        while true
          result << build_array[]
          return result if bump_counters[]
        end
      end
    end
def product(*tuples)
      tuples = tuples.map { |tuple| Erlang.from(tuple) }
      # if no tuples passed, return "product" as in result of multiplying all elements
      return super if tuples.empty?

      tuples.unshift(self)

      if tuples.any?(&:empty?)
        return block_given? ? self : []
      end

      counters = Array.new(tuples.size, 0)

      bump_counters = lambda do
        i = tuples.size-1
        counters[i] += 1
        while counters[i] == tuples[i].size
          counters[i] = 0
          i -= 1
          return true if i == -1 # we are done
          counters[i] += 1
        end
        false # not done yet
      end
      build_array = lambda do
        array = []
        counters.each_with_index { |index,i| array << tuples[i][index] }
        array
      end

      if block_given?
        while true
          yield build_array[]
          return self if bump_counters[]
        end
      else
        result = []
        while true
          result << build_array[]
          return result if bump_counters[]
        end
      end
    end
Cartesian product or multiplication.

 @overload product(*tuples)
   Return a `Tuple` of all combinations of elements from this `Tuple` and each
   of the given tuples or arrays. The length of the returned `Tuple` is the product
   of `self.size` and the size of each argument tuple or array.
   @example
     t1 = Erlang::Tuple[1, 2, 3]
     t2 = Erlang::Tuple["A", "B"]
     t1.product(t2)
     # => [[1, "A"], [1, "B"], [2, "A"], [2, "B"], [3, "A"], [3, "B"]]
 @overload product
   Return the result of multiplying all the elements in this `Tuple` together.

   @example
     Erlang::Tuple[1, 2, 3, 4, 5].product  # => 120

 @return [Tuple]