Magik (programming language)

Magik is an object-oriented programming language that supports multiple inheritance, polymorphism and is dynamically typed. It is provided by GE Energy as part of its Smallworld technology platform and was designed from the outset to implement complex applications for enterprise utilities such as power distribution and telecommunications.

Magik (Inspirational Magik) was originally introduced in 1990 and has been improved and updated over the years. Its current version is 4.0 or Magik SF (Small Footprint).

Similarities with Smalltalk
Magik itself shares some similarities with Smalltalk in terms of its language features and its architecture: the Magik language is compiled into byte codes interpreted by the Magik virtual machine. The Magik virtual machine is available on several platforms including Microsoft Windows, various flavours of Unix and Linux.

Magik is console based and code can be modified on the fly even when an application is running. The console can also be used to execute Magik code and to see the results.

Compiled code is stored in a single file called an image file. Each image file holds the compiled byte-codes and the state of the session (for example variable values) when the image was last saved.

Language features
Magik uses the  token to mark sections of code as comments:
 * Comments

# This is a comment.

Magik uses the  operator to make assignments:
 * Assignments

a << 1.234 b << b + a

For clarity, this notation is read as "A becomes 1.234" or "b becomes b plus a". This terminology separates assignment from comparison.

Magik also supports a compressed variation of this operator that works in a similar way to those found in C:

b +<< a # Equivalent to b << b + a

As well as conventional data types such as integers, floats and strings Magik also implements symbols. Symbols are a special token data type that are used extensively throughout Magik to uniquely identify objects. They are represented by a colon followed by a string of characters. Symbols can be escaped using the vertical bar character. For example:
 * Symbols

a << :hello # whenever :hello is encountered, it is the same instance b << :|hello world|

Magik variables are not typed as they are in say C# and can reference different objects at runtime. Everything in Magik is an object (there is no distinction between objects and primitive types such as integers):
 * Dynamic typing

a << 1.2    # a floating point number is assigned to variable 'a'  a << "1.2"   # later, a string is assigned to variable 'a'

Objects are implemented in Magik using exemplars. Exemplars have similarities to classes in other programming languages such as Java, but with important differences. Magik supports multiple inheritance, and mixins (which implement functionality with no data). New instances are made by cloning an existing instance (which will typically be the exemplar but does not have to be).
 * Objects

New exemplars are created using the statement, for example:

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

This code fragment will define a new exemplar called  that has two slots (or fields) called   (pre-initialized to 34) and   (pre-initialised to "hello") that inherits from two existing exemplars called   and.

Magik implements all usual binary operators for comparison, as well as a few unusual ones. The  and   operators are used for comparing specific instances of objects, or object references rather than values.
 * Comparison

For example:

a << "hello" b << "hello"

a = b returns True (_true) because the values of a and b are the equal a _is b returns False (_false) because a is not the same instance as b

a << "hello" b << a

a = b returns True (_true) because the values of a and b are the equal a _is b returns True (_true) because b was assigned the specific instance of the same object as a, rather than the value of a.

Methods are defined on exemplars using the statements  and  :
 * Methods

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

It is convention to supply two methods  (to create a new instance) and   (to initialize an instance).

# New method _method person.new(name, age) _return _clone.init(name, age) _endmethod

# Initialize method. _private _method person.init(name, age) # Call the parent implementation. _super.init(name, age) # Initialise the slots. .name << name .age << age _return _self _endmethod

The  creates a physical copy of the   object. The  statement allows objects to invoke an implementation of a method on the parent exemplar. Objects can reference themselves using the  statement. An object's slots are accessed and assigned using a dot notation.

Methods that are not part of the public interface of the object can be marked private using the  statement. Private methods can only be called by,   and.

Optional arguments can be declared using the  statement. Optional arguments that are not passed are assigned by Magik to the special object  (the equivalent of null). The  statement can be used to declare a list of optional arguments.

_method my_object.my_method(_gather values) _endmethod

In Magik the,  ,   and   statements allow iteration.
 * Iteration

_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

Here values.elements is an iterator which helps to iterate the values.

In Magik generator methods are called iterator methods. New iterator methods can be defined using the  and   statements:

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

Magik also supports functions called procedures. Procedures are also objects and are declared using the  and   statements. Procedures are assigned to variables which may then be invoked:
 * Procedures

my_procedure << _proc @my_procedure(a, b, c)   _return a + b + c  _endproc

x << my_procedure(1, 2, 3) # x = 6

Because Magik was originally developed in England, methods in the core smallworld libraries are spelled using British English. For example:
 * Language Quirks

Use "initialise", not "initialize".

Like other programming language Magik too has collections. They include the following:
 * Collections
 * Simple Vector
 * Rope
 * Hash Table
 * Property List
 * Equality set
 * Bags

Hello World example
The following is an example of the Hello World programme written in Magik:

write ("Hello World 1!")