Pregunta

¿Hay alguna manera fácil de probar si un objeto es inmutable (números, nulo) o no (matriz, hash, objetos)? En otras palabras, ¿podrían modificarse los efectos secundarios de otro código?

Motivación: quiero crear un almacén de valores versionados, pero algunos de los datos son matrices. Algunos de los arreglos almacenarán objetos personalizados, y podría invertir la relación almacenando la propiedad 'in' y buscándola. Pero también me gustaría poder almacenar matrices de símbolos, otras matrices, etc.

¿Fue útil?

Solución

No hay objetos primitivos en Ruby. Por lo tanto, esto no se puede detectar de manera directa.

¿No puedes simplemente usar Marshal o YAML para tu tienda versionada? Luego, podrá cargar y guardar todos los tipos de objetos de forma gratuita. ¿Por qué reinventar la rueda?

No sé qué quieres lograr exactamente, pero mirar la fuente de YAML puede ser interesante para ver cómo manejan este problema. La implementación de codificación Ruby YAML simplemente implementa el método to_yaml para todas las clases relevantes. Consulte yaml / rubypes. .

Otros consejos

Encontré una forma ineficiente:

class Object
  def primitive?
    begin
      self.dup
      false
    rescue TypeError
      true
    end
  end
end

La idea de la mutabilidad realmente no se aplica en Ruby de la misma manera que en otros idiomas. El único objeto inmutable es uno congelado. Incluso puede agregar métodos y variables de instancia a Fixnums. Por ejemplo:

class Fixnum
  attr_accessor :name
end
1.name = "one"
2.name = "two"

Obviamente, la gran mayoría de las veces, las personas no serán lo suficientemente patológicas como para agregar atributos a Fixnum, pero el punto es que ningún objeto no congelado es realmente inmutable.

Si puede llegar a una lista canónica de clases que quiere asumir que son inmutables, puede pasar y darles a todos un método inmutable? () que devuelve true (y Object una versión que devuelve falso). Pero como dijo wvanbergen, la mejor manera de asegurarse de que su copia de un objeto no cambie es copiarla en profundidad con Marshal.

Otra diferencia: ¿los objetos nativamente inmutables no se pueden congelar, pero aún así devuelven falso de congelado?

5.freeze.frozen? == false

Congelar no genera una excepción (a diferencia de dup) Sin embargo, sí modifica (permanentemente) los objetos mutables.

He descubierto que puedo (al menos en su estado actual) organizar mi aplicación para que funcione con objetos congelados, y Ruby me dará una excepción si intento modificarlos directamente. Sin embargo, congelación solo afecta el primer nivel del objeto , y las matrices, etc. almacenadas en él todavía pueden modificarse.

¿Esto solo se aplica a 1.8 - 5.frozen? devuelve verdadero en ruby1.9 (pero no en irb1.9)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top