Neha Patil (Editor)

Citrine (programming language)

Updated on
Edit
Like
Comment
Share on FacebookTweet on TwitterShare on LinkedInShare on Reddit
Designed by
  
Gabor de Mooij

First appeared
  
2014

Developer
  
Gabor de Mooij

Typing discipline
  
dynamic

Paradigm
  
Object-oriented, prototype-based

Stable release
  
0.2 / 2014; 3 years ago (2014)

Citrine is a general purpose programming language for Unix-like operating systems. It focuses on readability and maintainability. Readability is achieved by syntactic and conceptual minimalism. The language is heavily inspired by Smalltalk and Self but has some very distinctive features. Like Smalltalk, Citrine treats everything as an object and focuses on sending messages to these objects. However unlike Smalltalk, Citrine lacks the concept of a class. In this regard, Citrine is more like Self and JavaScript because it uses prototypes. The combination of Smalltalk like messages and prototypes is what makes Citrine unique.

Contents

Syntax

Citrine has a very limited syntax and it's very closely related to Smalltalk. Everything in Citrine is an object, there are 5 literals:

  • Nil
  • True, False
  • 0,1,2,3
  • 'String'
  • { param | ...block of code... }
  • The code block literal uses a pipe symbol to separate the parameters from the logic '|', if there are no parameters, the backslash should be used instead '\'.

    Citrine only supports full line comments, comments start with a '#'.

    A Citrine program is basically a sequence of messages sent to objects. For instance, to calculate the factorial of the number 5, the message 'factorial' is sent to the number 5.

    This is called a unary message because it takes no arguments. A binary message is always a single UTF-8 character; this differs from Smalltalk, where there is a fixed set of binary messages. Here is an example:

    Here a binary message '+' is sent to number 6, the argument of this binary message is '7', this will result in a new number object '13'. Assigning the outcome of this operation to a variable uses the assignment operator: :=.

    Also note that each line in a Citrine program ends with a dot, just like in Smalltalk. Besides unary and binary messages, Citrine offers keyword messages, which take arguments interspersed with the message itself just like Smalltalk and Objective-C.

    The code snippet above will return a boolean object True.

    Control flow

    Just like Smalltalk, control flow in Citrine is implemented by strategic use of messages. For instance, writing a conditional statement requires sending a block of code to a boolean.

    Likewise, a for-loop is written as:

    Besides for-loops, Citrine features each-loops, while-loops and a simple times loop, the latter uses the binary message '*'.

    To break out of a loop in Citrine one has to send the message 'break' to a boolean, this allows a conditional break from a loop without having to factor out the break conditions:

    Pipelines

    Unlike Smalltalk, Citrine has no semi-colon to send a message to the original receiver. Instead Citrine has a comma token ',' used to chain keyword messages, this allows writing Unix-like pipelines. The following code uses a pipeline-like syntax to replace all the 'o' characters with zeroes, the resulting string would be something like: '1010101...'.

    Prototypes

    The biggest difference from Smalltalk is the use of prototypes. Citrine does not have a concept of a class, it only knows about objects. An object is created using the new message:

    This object can be made to respond to messages by ordering the object to listen to events. This is kind of similar to adding methods in languages like Java:

    As stated above, inheritance is based on prototypes. To derive an object from another object, the new message must be sent to the object to be extended:

    Unicode

    Citrine uses UTF-8 unicode extensively, both objects and messages can consist of unicode symbols. All string length are calculated using UTF-8. Citrine distinguishes string length and size in bytes:

    returns the length of the string in UTF-8 code pointes, while:

    returns the number of bytes.

    Scoping

    Citrine uses dynamic scoping instead of lexical scoping. Thus, there is no need for dependency injection or global variables, but it might be harder to reason about than lexical scope. This is similar in programming languages like Emacs Lisp and BASIC. In code blocks the var keyword needs to be used to declare a local variable.

    Demonstration:

    References

    Citrine (programming language) Wikipedia