Sí, lo hay de hecho. Más o menos.
Newspeak no tiene estado estático ni estado global. Esto significa que la única forma posible de obtener acceso a una dependencia es inyectarla explícitamente. Obviamente, esto significa que el lenguaje, o en el caso de Newspeak más precisamente, el IDE necesita facilitar la inyección de dependencia, de lo contrario el lenguaje será inutilizable.
Entonces, el lenguaje no está diseñado para DI, más bien la necesidad de DI es una consecuencia del diseño del lenguaje.
Si no hay un estado estático ni un estado global, entonces no puede simplemente "alcanzar" el éter y extraer algo. Por ejemplo, en Java, la estructura del paquete es un estado estático. Solo puedo decir java.lang.Stringy tengo la Stringclase. Eso no es posible en Newspeak. Todo lo que trabajas tiene que ser provisto explícitamente, de lo contrario simplemente no puedes hacerlo. Entonces, todo es una dependencia, y cada dependencia es explícita.
¿Quieres una cuerda? Bueno, primero debes pedirle al stdlibobjeto que te entregue la Stringclase. Ah, pero ¿cómo se accede a la stdlib? Bueno, primero debes pedirle platformque te entregue el stdlibobjeto. Ah, pero ¿cómo se accede a la platform? Bueno, primero debes pedirle a alguien que te entregue el platformobjeto. Oh, pero ¿cómo se accede a alguien menos? Bueno, primero debes pedirle a otra persona que te entregue el objeto.
¿Hasta dónde llega el agujero del conejo? ¿Dónde se detiene la recursividad? Todo el camino, en realidad. No para Entonces, ¿cómo puedes escribir un programa en Newspeak? Bueno, estrictamente hablando, ¡no puedes!
Necesitas alguna entidad externa que lo una todo. En Newspeak, esa entidad es el IDE. El IDE ve todo el programa. Puede unir las piezas dispares juntas. El patrón estándar en Newspeak es que la clase central de su aplicación tiene un acceso llamado platform, y el IDE Newspeak inyecta un objeto en ese acceso que tiene métodos que devuelven algunas de las necesidades básicas de programación: una Stringclase, una Numberclase, una Arrayclase, y así.
Si desea probar su aplicación, puede inyectar un platformobjeto cuyo Filemétodo devuelva una clase con métodos ficticios. Si desea implementar su aplicación en la nube, inyecte una plataforma cuya Fileclase en realidad esté respaldada por Amazon S3. Las GUI multiplataforma funcionan mediante la inyección de diferentes marcos de GUI para diferentes sistemas operativos. Newspeak incluso tiene un compilador experimental Newspeak-to-ECMAScript y un marco GUI respaldado por HTML que le permite portar una aplicación GUI con todas las funciones desde el escritorio nativo al navegador sin cambios, simplemente inyectando diferentes elementos GUI.
Si desea implementar su aplicación, el IDE puede serializar la aplicación en un objeto en el disco. (A diferencia de su antepasado, Smalltalk, Newspeak tiene un formato de serialización de objetos fuera de imagen. No tiene que llevar la imagen completa con usted, precisamente porque se inyectan todas las dependencias: el IDE sabe exactamente qué partes del sistema su aplicación utiliza y lo que no hace. Por lo tanto, serializa exactamente el subgrafo conectado del espacio de objetos que comprende su aplicación, nada más).
Todo esto funciona simplemente llevando la orientación a objetos al extremo: todo es una llamada de método virtual ("envío de mensaje" en la terminología de Smalltalk, de la cual Newspeak es un descendiente). ¡Incluso la búsqueda de superclase es una llamada de método virtual! Toma algo como
class Foo extends Bar // using Java syntax for familiarity
o, en Newspeak:
class Foo = Bar () () : ()
En Java, esto creará un nombre Fooen el espacio de nombres global estático, y buscará Baren el espacio de nombres global estático y creará la Bar Foosuperclase. Incluso en Ruby, que es mucho más dinámico, esto seguirá creando una constante estática en el espacio de nombres global.
En Newspeak, la declaración equivalente significa: crear un método getter llamado Fooy hacer que devuelva una clase que busque su superclase llamando al método named Bar. Nota: esto no es como Ruby, donde puede poner cualquier código Ruby ejecutable como la declaración de superclase, pero el código solo se ejecutará una vez cuando se cree la clase y el valor de retorno de ese código se convierta en la superclase fija. No. ¡Se Barllama al método para cada búsqueda de método!
Esto tiene algunas implicaciones profundas:
- dado que un mixin es básicamente una clase que todavía no conoce su superclase, y en Newspeak, la superclase es una llamada de método virtual dinámico y, por lo tanto, se desconoce, cada clase también es automáticamente un mixin. Obtienes mixins gratis.
Como una clase interna es solo una llamada a un método que devuelve una clase, puede anular ese método en una subclase de la clase externa, por lo que cada clase es virtual. Obtienes clases virtuales gratis:
class Outer {
class Inner { /* … */ }
}
class Sub extends Outer {
override class Inner { /* … */ }
}
Neolengua:
class Outer = () (
class Inner = () () : ()
) : ()
class Sub = Outer () (
class Inner = () () : ()
) : ()
Como la superclase es solo una llamada a un método que devuelve una clase, puede anular ese método en una subclase de la clase externa, las clases internas definidas en la superclase pueden tener una superclase diferente en la subclase. Obtiene la herencia de jerarquía de clases de forma gratuita:
class Outer {
class MyCoolArray extends Array { /* … */ }
}
class Sub extends Outer {
override class Array { /* … */ }
// Now, for instances of `Sub`, `MyCoolArray` has a different superclass
// than for instances of `Outer`!!!
}
Neolengua:
class Outer = () (
class MyCoolArray = Array () () : ()
) : ()
class Sub = Outer () (
class Array = () () : ()
) : ()
y, por último, lo más importante para esta discusión: dado que (aparte de los que definió en su clase, obviamente) solo puede llamar a los métodos en su (s) clase (s) que encierra léxicamente y su (s) superclase (s), una clase más externa de nivel superior no puede llamar a cualquier método en absoluto , excepto los que se inyectan de forma explícita: una clase de nivel superior no tiene una clase envolvente cuyos métodos se podría llamar, y no puede tener una superclase que no sea el predeterminado, ya que la declaración superclase es una llamada al método, y obviamente no puede ir a la superclase ( esla superclase) y tampoco puede ir a la clase léxica, porque no hay ninguna. Lo que esto significa es que las clases de nivel superior están completamente encapsuladas, solo pueden acceder a lo que se les inyecta explícitamente y solo se les inyecta lo que piden explícitamente. En otras palabras: las clases de nivel superior son módulos. Obtiene un sistema de módulos completo de forma gratuita. De hecho, para ser más precisos: las clases de nivel superior son declaraciones de módulos, sus instancias son módulos. Entonces, obtienes un sistema de módulos con declaraciones de módulos paramétricos y módulos de primera clase de forma gratuita, algo que muchos sistemas de módulos, incluso muy sofisticados, no pueden hacer.
Para que toda esta inyección sea indolora, las declaraciones de clase tienen una estructura inusual: consisten en dos declaraciones. Uno es el constructor de la clase, que no es el constructor que construye las instancias de la clase, sino el constructor que construye el entorno en el que se ejecuta el cuerpo de la clase. En una sintaxis similar a Java, se vería así:
class Foo(platform) extends Bar {
Array = platform.collections.Array
String = platform.lang.String
File = platform.io.File
| // separator between class constructor and class body
class MyArray extends Array { /* … */ }
// Array refers to the method defined above which in turn gets it from the
// platform object that was passed into the class "somehow"
}
Neolengua:
class Foo using: platform = Bar (
Array = platform collections Array
String = platform streams String
File = platform files ExternalReadWriteStream
) (
class MyArray = Array () () : ()
) : ()
Tenga en cuenta que la forma en que un programador de Newspeak realmente verá las clases es así:
Sin embargo, ni siquiera puedo comenzar a hacerle justicia. Tendrás que jugar con eso tú mismo. Gilad Bracha ha dado un par de charlas sobre varios aspectos del sistema, incluida la modularidad. Dio una charla realmente larga (2 horas) , la primera hora de las cuales es una introducción completa al lenguaje, incluida la historia de la modularidad. El capítulo 2 de la plataforma de programación Newspeak cubre la modularidad. Si hojeas Newspeak en Squeak: una guía para Perplexed (también conocido como Newspeak-101) , obtienes una idea del sistema. Newspeak by Example es un documento en vivo (es decir, se ejecuta dentro del puerto Newspeak-on-ECMASCript, cada línea de código es editable, cada resultado es inspeccionable) que demuestra la sintaxis básica.
Pero realmente, tienes que jugar con eso. Es tan diferente de todos los idiomas principales e incluso de la mayoría de los idiomas no convencionales que es difícil de explicar, tiene que ser experimentado.