¿Qué usos tiene el 'convertido:' de Smalltalk?


12

El become:mensaje en Smalltalk hace que un objeto cambie a otro, afectando todas las referencias a él.

¿Qué usos tiene esta función de lenguaje? ¿Se usa en código real? ¿Es solo una curiosidad? ¿Se considera una buena / mala práctica usarlo?

Respuestas:


11

Gilad Bracha habla con become:cierta extensión:

Una de las características más singulares y potentes de Smalltalk es también una de las menos conocidas fuera de la comunidad Smalltalk. Es un pequeño método llamado convertido en:.

Lo que se hace: intercambia las identidades de su receptor y su argumento. Es decir, después

a convertido en: b

todas las referencias al objeto denotado por a antes del punto de llamada se refieren al objeto denotado por b, y viceversa.

Tómese un minuto para internalizar esto; podrías malinterpretarlo como algo trivial. No se trata de intercambiar dos variables, se trata literalmente de que un objeto se convierta en otro. No conozco ningún otro idioma que tenga esta característica. Es una característica de enorme poder y peligro.

Considere la tarea de extender su lenguaje para admitir objetos persistentes. Supongamos que desea cargar un objeto desde el disco, pero no desea cargar todos los objetos a los que se refiere de forma transitiva (de lo contrario, es simplemente deserialización de objetos). Entonces carga el objeto en sí, pero en lugar de cargar sus referencias directas, las reemplaza con objetos de cascarilla.

Las cáscaras reemplazan los datos reales en el almacenamiento secundario. Esa información se carga perezosamente. Cuando realmente necesita invocar un método en una cáscara, es doesNotUnderstand: el método carga el objeto de datos correspondiente desde el disco (pero de nuevo, no de forma transitiva).

Luego, se convierte en :, reemplazando todas las referencias a la cáscara con referencias al objeto recién cargado y vuelve a intentar la llamada.

Algunos motores de persistencia han hecho este tipo de cosas durante décadas, pero generalmente dependían de un acceso de bajo nivel a la representación. Become: le permite hacer esto en el nivel del código fuente.

Ahora ve a hacer esto en Java. O incluso en otro lenguaje dinámico. Reconocerá que puede hacer una forma general de futuros de esta manera y, por lo tanto, la pereza. Todo ello sin acceso privilegiado al funcionamiento de la implementación. También es útil para la evolución del esquema, por ejemplo, cuando agrega una variable de instancia a una clase. Puede "remodelar" todas las instancias según sea necesario.

Por supuesto, no deberías usar Become: casualmente. Tiene un costo, que puede ser prohibitivo en muchas implementaciones. Al principio, Smalltalks, llegar a ser: era barato, porque todos los objetos se referenciaban indirectamente por medio de una tabla de objetos. En ausencia de una tabla de objetos, se convierte en: atraviesa el montón de una manera similar a un recolector de basura. Cuanta más memoria tenga, más caro se vuelve: se convierte.

Tener una tabla de objetos ocupa almacenamiento y ralentiza el acceso; pero te ofrece una gran flexibilidad. El soporte de hardware podría aliviar la penalización del rendimiento. La ventaja es que muchos problemas difíciles se vuelven bastante manejables si está dispuesto a pagar el costo de la indirección a través de una tabla de objetos por adelantado. Recuerde: cada problema en informática puede resolverse con niveles adicionales de indirección. Alex Warth tiene un trabajo muy interesante que encaja en esta categoría, por ejemplo.

Become: tiene varias variaciones: una forma se convierte en: cambia la identidad de un objeto A a la de otro objeto B, de modo que las referencias a A ahora apuntan a B; las referencias a B permanecen sin cambios. A menudo es útil convertirse en: a granel: transmutando las identidades de todos los objetos en una matriz (ya sea unidireccionalmente o bidireccionalmente). Un grupo convertido: lo que hace mágicamente atómicamente es ideal para implementar actualizaciones reflexivas a un sistema, por ejemplo. Puede cambiar todo un conjunto de clases y sus instancias de una sola vez.

Incluso puede concebir el tipo seguro convertido en:. Dos vías se vuelven: solo es seguro para los tipos si el tipo de A es idéntico al de B, pero una forma se vuelve: solo requiere que el nuevo objeto sea un subtipo del antiguo.

Puede ser hora de reconsiderar si tener una tabla de objetos es realmente algo bueno.

Efectivamente, lo que obtienes es una forma de carga diferida a través de lo que equivale a metaprogramación. Como señala Bracha, esto puede ser muy útil, pero también es peligroso, ya que puede tener un grave impacto en el rendimiento.


Estaría más preocupado por becomeel impacto en mi cordura que en el rendimiento de mi programa ...
Benjamin Hodgson

Hardware support could ease the performance penalty.De todos los lugares en los que he escuchado esto, la comunidad Smalltalk ha sido la más destacada. ¿Por qué deberíamos "gastar" mejoras de hardware en habilitar paradigmas de programación idealistas cuando en su lugar podría conducir a un mayor rendimiento, un menor uso de energía o una mayor capacidad?
Alexander - Restablece a Mónica

2

No se usa mucho. En la imagen de Pharo 5 que tengo abierta, hay 9 remitentes de #become :, 7 de los cuales están en pruebas unitarias. Se utiliza en el compilador en la generación de código y en la biblioteca de serialización de Fuel para reemplazar los proxies por su contenido.


Interesante. ¿Para qué lo usan las pruebas unitarias?
dpk

para ver si funciona ...
Stephan Eggermont
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.