def flatten(level = -1)
      return self if level == 0
      array = self.to_a
      if array.frozen?
        return self.class.new(array.flatten(level).freeze)
      elsif array.flatten!(level) # returns nil if no changes were made
        return self.class.new(array.freeze)
      else
        return self
      end
    end
def flatten(level = -1)
      return self if level == 0
      array = self.to_a
      if array.frozen?
        return self.class.new(array.flatten(level).freeze)
      elsif array.flatten!(level) # returns nil if no changes were made
        return self.class.new(array.freeze)
      else
        return self
      end
    end
Return a new `Tuple` with all nested tuples and arrays recursively "flattened
 out". That is, their elements inserted into the new `Tuple` in the place where
 the nested array/tuple originally was. If an optional `level` argument is
 provided, the flattening will only be done recursively that number of times.
 A `level` of 0 means not to flatten at all, 1 means to only flatten nested
 arrays/tuples which are directly contained within this `Tuple`.

 @example
   t = Erlang::Tuple["A", Erlang::Tuple["B", "C", Erlang::Tuple["D"]]]
   t.flatten(1)
   # => Erlang::Tuple["A", "B", "C", Erlang::Tuple["D"]]
   t.flatten
   # => Erlang::Tuple["A", "B", "C", "D"]

 @param level [Integer] The depth to which flattening should be applied
 @return [Tuple]