Magik (lenguaje de programación)

Magik es un lenguaje de programación orientada a objetos que soporta herencia múltiple, polimorfismo y cuyos tipos de datos son dinámicos. GE Energy lo proporciona como parte de la plataforma Smallworld y fue diseñado en un principio para implementar aplicaciones complejas para empresas como telecomunicaciones.

Magik fue creado originalmente en 1990, y a través de los años fue mejorado y actualizado. La versión actual es la 4.0 o Magik SF (Small Footprint).

Similitudes con Smalltalk

Magik tiene algunas similitudes con Smalltalk en términos de características del lenguaje y arquitectura: el lenguaje Magik se compila en bytecode que es interpretado por la Máquina virtual de Magik. La máquina virtual de Magik está disponible en varias plataformas, entre ellas Microsoft Windows, varias versiones de Unix y Linux.

Magik está basado en consola, y el código puede ser cambiado mientras la aplicación se está ejecutando. La consola puede ser utilizada tanto para ejecutar código Magik como para ver los resultados.

El código compilado se guarda en un único archivo llamado archivo imagen. Cada archivo imagen contiene el bytecode completo y el estado de la sesión (por ejemplo valores de variables) del momento del último guardado de la imagen.

Características del lenguaje

Comentarios

Magik usa el # para marcar secciones de código como comentario:

 # Esto es un comentario.
Asignaciones

Magik usa el operador << para hacer asignaciones:

 a << 1.234
 b << b + a

Esta notación se lee como "a se convierte en 1.234" o "b se convierte en b+a". Esto sirve para diferenciar correctamente asignación de comparación.

Magik soporta también una variación comprimida del operador que funciona de forma similar a los que podemos encontrar en C:

 b +<< a # Equivalente a b << b + a
Símbolos

Así como los tipos de datos convencionales como enteros, números en coma flotante y cadenas, Magik también implementa símbolos. Los símbolos son un tipo de dato especial que son usados extensamente en Magik para identificar de forma única los objetos. Se representan mediante dos puntos ":" seguidos de una cadena de caracteres. Los símbolos se pueden escapar mediante la barra vertical "|". Por ejemplo:

 a << :hello  # Cuando se encuentre :hello se referirá a la misma instancia
 b << :|hello world|
Tipos dinámicos

Las variables de Magik no tienen tipos fijados como en C# y pueden referenciar diferentes objetos en la ejecución. Cualquier cosa en Magik es un objeto (No hay distinción entre objetos y tipos de datos primitivos como los enteros):

 a << 1.2     # un número en coma flotante asignado a la variable 'a'
 a << "1.2"   # más tarde se le asigna una cadena a la variable 'a'
Objetos

Los objetos se implementan en Magik usando ejemplares. Los ejemplares son parecidos a las clases de otros lenguajes de programación como Java, pero con importantes diferencias. Magik soporta herencia múltiple y mezclas. Las nuevas instancias se crean clonando una ya existente (que típicamente es el ejemplar, pero no tiene por qué serlo).

Los nuevos ejemplares se crean con la sentencia def_slotted_exemplar(), por ejemplo:

 def_slotted_exemplar(:my_object,
 {
   {:slot_a, 34},
   {:slot_b, "hello"}
 }, {:parent_object_a, :parent_object_b})

Este fragmento de código define un ejemplar llamado my_object que tiene dos huecos (o campos) llamados slot_a (preinicializado con el valor 34) y slot_b (preinicializado con el valor "hello") que hereda de dos ejemplares ya existentes llamados parent_object_a y parent_object_b.

Comparación

Magik implementa todos los operadores binarios típicamente usados (=, <, <=, >, >=, ~=/<>) para la comparación, así como algunos más inusuales. Los operadores _is y _isnt se usan para comparar instancias específicas de objetos, o referencias de objetos en lugar de valores.

Por ejemplo:

 a << "hello"
 b << "hello"
 a = b retorna True (_true) porque los valores de a y b son iguales
 a _is b returna False (_false) porque a y b no son la misma instancia
 a << "hello"
 b << a
 a = b retorna True (_true) porque los valores de a y b son iguales
 a _is b retorna True (_true) porque b se asigna a una instancia específica del mismo objeto que a, en lugar del mismo valor que a.
Métodos

Los métodos se definen en los ejemplares usando las sentencias _method y _endmethod:

 _method my_object.my_method(a, b)
   _return a + b
 _endmethod

Esta es una forma de sustituir los métodos new() (para crear nuevas instancias) y init() (para inicializar una instancia).

 # Método New
 _method person.new(name, age)
   _return _clone.init(name, age)
 _endmethod
 # Método Initialize
 _private _method person.init(name, age)
    # Llama la implementación del padre.
    _super.init(name, age)
    # Inicializa los campos.
    .name << name
    .age << age
   _return _self
 _endmethod

El _clone crea una copia física del objeto person. La sentencia _super permite a los objetos invocar una implementación de un método en un ejemplar padre. Los objetos pueden referenciarse a sí mismos usando la sentencia _self. A los campos de un objeto se accede usando la notación de punto ".".

Los métodos que no son parte de la interfaz pública de un objeto pueden ser marcados como privados usando la sentencia _private. Los métodos privados solo pueden ser llamados por _self, _super y _clone.

Hay argumentos opcionales que se pueden declarar con la sentencia _optional. Los argumentos opcionales que no son pasados son asignados por Magik a un objeto especial _unset (el equivalente a NULL). La sentencia _gather se puede usar para declarar una lista de argumentos opcionales.

 _method my_object.my_method(_gather values)     
 _endmethod
Iteración

En Magik las senencias _for, _over, _loop y _endloop permiten iterar.

 _method my_object.my_method(_gather values)
   total << 0.0
   _for a _over values.elements()
   _loop
      total +<< a
   _endloop
   _return total
 _endmethod
 m << my_object.new()
 x << m.my_method(1.0, 2, 3.0, 4) # x = 10.0

Los nuevos metedos de iteración se definen usando las sentencias _iter y _loopbody:

 _iter _method my_object.even_elements()
   _for a _over _self.elements()
   _loop
     _if a.even? _is _true
     _then
        _loopbody(a)       
     _endif
   _endloop
 _endmethod
Procedimientos

Magik también soporta funciones llamadas procedimientos. Los procedimientos son también objetos, declarados con las sentencias _proc y _endproc. Los procedimientos son asignados avariables que pueden ser invocadas:

 my_procedure << _proc @my_procedure(a, b, c)
   _return a + b + c
 _endproc
 x << my_procedure(1, 2, 3) # x = 6
Peculiaridades lingüísticas

Puesto que Magik fue desarrollado originalmente en Inglaterra, los métodos del núcleo y las librerías de Smallworld está esctitas en inglés británico British English. Por ejemplo:

  Se usa "initialise", en vez de "initialize".

Ejemplo Hello World

El siguiente fragmento de código es el programa que emite el mensaje "hello world" escrito en Magik:

 write ("Hello World!")
Este artículo ha sido escrito por Wikipedia. El texto está disponible bajo la licencia Creative Commons - Atribución - CompartirIgual. Pueden aplicarse cláusulas adicionales a los archivos multimedia.