Ѧ simple laחguagέ
ഽor ƩveЯyone

Citrine is a simple programming language that's easy to learn and use. It's so simple, it does not even have special constructs for loops and conditions. Everything is done by sending messages to objects. You can learn Citrine in a couple of minutes!
News | API | Why | C-API
Citrine on Github
☞ f := Array ← 0 ; 1.

0 to: 12 step: 1 do: {

   #take the last element of f
   ☞ a := f last.
   #take the element before that
   ☞ b := f secondLast.
   #write them down
   ✎ write:
      'the sum of ❲ a ❳ and ❲ b ❳'.
   #calculate the sum
   ☞ sum := (a + b).
   ✎ write: 
      ' is ❲ sum ❳ '.

   # add the sum to the array
   f add: sum.

☞ f := Lijst ← 0 ; 1.

0 tot: 12 stap: 1 doen: {

   #neem laatste element van f
   ☞ a := f laatste.
   #neem het element ervoor
   ☞ b := f een-na-laatste.
   #schrijf het op
   ✎ schrijf:
      'de som van ❲ a ❳ en ❲ b ❳'.

   #bereken de som
   ☞ som := (a + b).
   ✎ schrijf: 
      ' is ❲ som ❳ '.

   # voeg de som toe aan de lijst
   f erbij: som.
Download Citrine 0.7.8 download citrine
the sum of 1 and 0 is 1
the sum of 1 and 1 is 2
the sum of 2 and 1 is 3
the sum of 3 and 2 is 5
the sum of 5 and 3 is 8
the sum of 8 and 5 is 13
the sum of 13 and 8 is 21
the sum of 21 and 13 is 34
the sum of 34 and 21 is 55
the sum of 55 and 34 is 89
the sum of 89 and 55 is 144
the sum of 144 and 89 is 233
the sum of 233 and 144 is 377

Learn Citrine in one minute

In Citrine, everything is an object. You write a program by making these objects talk to each other, by sending messages.

There are 5 literal objects: Nil, Booleans (True,False), Numbers (i.e. 1,2,3.5,100 and so on), Strings (any text between 'single quotes') and code Blocks: { :parameter1 :parameter2 ...code... }.

Some other rules: you can assign a value to variable using :=, comments start with a # and every line ends with a dot (.).

☞ x := 3 factorial. #x = 6
☞ x := 3 factorial factorial. #x = 720

Here we send the message 'factorial' to 3, the resulting value (6) gets assigned to x (we use the hand for that, the keyword 'var' is also allowed). On the second line we chain two messages (factorial), resulting in x = 720. A keyword message is a message with arguments:

☞ x := 3 between: 1 and: 10. #True
☞ x := 2 + 3. #5

A message that is just one single symbol (+-/*) is a binary message and always has exactly one argument, the object that follows. You can chain keyword messages with a comma (,):

✎ write: 'hello ', write: 'world'.
hello world


Control Flow

To create a loop, send the message 'times:' to a number together with a block of code:

3 times: { :i ✎ write: i. }. #prints: 012

This will run the block of code 3 times. To break out of a loop, use break (and continue to skip remainder of the current iteration), the following loops prints: 98765. Also note that we compare using = not ==.

9 to: 0 step: -1 do: { :i 
	✎ write: i. ( i = 5 ) break.

To compare things, send messages like ifTrue: or ifFalse: to expressions that result in boolean values:

☞ ⛁ := 4.
☞ ☕ := 2.5.
(⛁ ≥ ☕) ifTrue: {
	✎ write: 'Buy coffee'.
}, else: {
	✎ write: 'Too expensive'.

You can catch errors by attaching a catch block to your code:

{  2 / 0. } catch:
{ :error ✎ write: error. }, run.
Division by zero.

Craft your own Objects

You can give a block of code a name:

☞ echo := { :x ↲ (x + x). }.
✎ write: (echo applyTo: 'hi'). #hihi

To create your own object and make it respond to messages:

Cat := Object new.
Cat on: 'name:' do: { :n ⚿ name := n. }.
Cat on: 'name' do: { ↲ ⚿ name. }. 

This creates a cat object that responds to 'name:' to change its name and 'name' to tell its name. The object stores its name in a property 'name'. To access a property, use or 'my'. Usage:

cat := Cat new.
cat name: 'Diva'.
✎ write: cat name. #prints Diva

If you want to reuse old code, base your object on a previously crafted one (this is called prototypal inheritance):

RoyalCat := Cat new.
RoyalCat on: 'name' do: { :n
	↲ 'your royal highness ' + ( ⛏ `name ).

Here, we override the behaviour for message 'name' with a new response. The symbol 'plays' back another response from the same object. To reference an overridden one, prefix the message with a backtick (`).

✎ write: ((RoyalCat new name: 'Diva') name).
your royal highness Diva

Tips & Tricks

Use ❲ ❳ to embed a variable in a string (string interpolation):

☞ name := 'Santa'.
✎ write: '❲name❳ comes to town'.
Santa comes to town

You can modify existing objects (malleable objects), for instance, to make numbers respond to × :

Number on: '×' do: { :b ⛏ times: b. }.
7 × { :i ✎ write: i. }.

You can make objects respond to arbitrary messages (generic responses) as well:

echo := Object new.
echo on: 'respondTo:' do: { :s ↲ 2 × :s }.
echo ho!. #ho!ho!

Citrine uses dynamic scoping:

☞ f := { q := 2. }.
{ ☞ q := 1. f run. ✎ write: q. } run. #prints 2

To translate a Citrine program from one language into another:

ctr -t en2nl.dict myprogram.ctr


Where can I find more documentation?

All documentation can be found in the man files. You can also consult the online manual pages.

Why does Citrine use icons in the language?

Citrine simply makes use of the possibilities of utf-8. Icons are more descriptive than abbreviations like 'var', they are quicker to type (once you configured your editor), language agnostic (can be used in Dutch source code as well) and allow more natural looking texts (in case of the thin space vs camelCase).

What's up with the languages?

Citrine can be compiled in different languages. This means the core messages can be English, Dutch, French or Icelandic. This allows Citrine to be used by a wider audience (i.e. schools). At time of writing, only English and Dutch versions are available. If you like to translate Citrine into your language, please contact me! While some language distributions are available on the download page, this site does not cover all different language versions (that would be too much work). The idea is that a Citrine ambassador will create and maintain a separate website for a language-specific distribution of Citrine.

Where can I find translation tables?

Here are the translation tables:

- Translation CSV English-Dutch

Can I use Citrine to teach programming?

Yes, because Citrine can be compiled in your native language. Citrine takes away language barriers and makes software development accessible to a wider audience. Citrine can also be tailored to suit the needs of a specific course and audience. Contact me for details!

Why has Citrine no built-in functionality X?

Citrine is a minimalist language. The Citrine project focuses on producing a better language. You can add new functionality by using a plugin. Plugins are automatically loaded as soon as you start talking to the object. Put your plugins here:


Some 3rd party plugins: Plugin: JSON (by MadCapJake), Plugin: CURL (by MadCapJake)

In line with the UNIX philosophy you can also invoke other programs to perform certain tasks using the shell:

✎ write: (💻  shell: 'ls -la').

This will print the contents of the current working directory on the screen. You can use the Slurp object to interweave other languages (like shell) with Citrine. Every message you send to the Slurp object gets absorbed into a string, the obtain message returns the resulting string, example:

✎ write: (💻  shell: (Slurp ls: '-la', obtain)).

This allows for a more natural notation.

How can I use the icons in the examples?

Download the font package and install 'Citrine.ttf'. Now configure your editor as follows (I use Geany and Geany Macros, a macro package for Geany is included ):

cp ~/.config/geany/plugins/Geany_Macros/settings.conf ~/.config/geany/plugins/Geany_Macros/settings_backup.conf

cp macros.ini ~/.config/geany/plugins/Geany_Macros/settings.conf

icon code keys ascii
2264ALT+< or ALT+L<=:
2265ALT+> or ALT+M>=:
2684ALT+/ (? but without shift)Dice
2022ALT+*Add element to Array

Trick: Use the thin space (2009) to form messages with a space. For instance:

(coffee < 10) if true: { ✎ write: 'refill'. }.


Can I use Citrine to write webapps?

Yes, Citrine ships with a CCGILIB-based HTTP plugin (mods/request/libctrrequest.so) that allows you to deal with GET and POST requests. you can use the Request object like this:

get  := Request get: 'search'.
list := Request getArray: 'orders[]'.
post := Request post: 'message'.
list := Request postArray: 'orders[]'.
file := Request file: 'avatar'.

Storm Server is a CCGILib based SCGI server for Citrine for hi-traffic web applications, to start an instance of Storm we put the following code in storm.ctr:

#Citrine Storm Server Demo storm.ctr
#Put your Citrine scripts in /var/www/htdocs/...
#To kill this server
#kill $(cat /var/run/storm.pid)
Pen write: 'Start Citrine Storm Server v1', brk.
Request host:'localhost' listen:4000 pid:'/var/run/storm.pid' callback: {
	#Now set the content type and any other headers
        Pen write: 'Content-type: text/html\n\n'.
	#Load the script file
	var fname := Command env: 'DOCUMENT_URI'.
        var script := File new: '/var/www/htdocs' + fname.
        #Run it!
	script include.


Can I serve Citrine applications with NGINX?

Sure, add the following configuration lines to: /etc/nginx/nginx.conf:

location ~ \.ctr$ {
        try_files $uri $uri/ =404;
        include   scgi_params;


What platforms are supported? How do I distribute Citrine?

Citrine runs on 64-bit X86 Linux and 64-bit X86 OpenBSD. There is a 64 bit X86 Windows port available as well. Community versions for FreeBSD and macOS are available as well (but I don't know where, please contact the community members).
If you want to use Citrine as your main programming language for a certain project, I recommend using one of the versions available on the download page. If you want to teach programming using the Citrine programming language, I recommend providing your students with a Virtual Machine.

What about functional programming style?

For the fans of functional programming:

☞ multiplier := { :m 
	↲ { :x 
		↲ (⚿ f * x).
	} set: 'f' value: m.
☞ double := multiplier applyTo: 2.
☞ q := double applyTo: 9. #yields 18

Have another question?
Visit Citrine Programming Language Forum!
There you can talk to other Citrine community members, ask questions, discuss new features, issues, bug reports and so on.

Citrine Support Contract Light € 39,-

gaborsoftware GaborSoftware offers various support contracts for the Citrine Programming Language. Benefits of a support contract include: priority status on github, a sponsor logo on the partner page and access to proprietary plugins (like GTK plugin) when available. With a Citrine Support Contract Light you also show your support for this project to the rest of the Citrine community. You can get a Citrine Support Contract Light for just € 39,- a year.

The Citrine Programming Language is a product of GaborSoftware © copyright 2018 all rights reserved. Citrine Programming Language created by Gabor de Mooij and the Citrine community. In-language (citrine.ttf) icons from the ionicons project (MIT licensed), FontAwesome (SIL OFL 1.1) by Dave Gandy - http://fontawesome.io and Typicons by S. Hutchings (SIL Open Font Licence).
Website and photography by Gabor de Mooij (photo 1: 'Train near Edinburgh Castle', photo 2: 'Box of wooden letter stamps at Apple Market, London', photo 3: 'Wall decorations in a pub in Edinburgh', photo 4: 'Moonstreet, London', photo 5: 'Ceiling of a monument in Paris'. ). Book icon from WikiMedia Commons Project. 'Citrine in a box' icon created by Gabor de Mooij using multiple assets from the WikiMedia Commons Project.
Contact me:

Founder & Original Author: Gabor de Mooij
Windows version of Citrine: Twiggler
Foundation work Json & Curl plugins: MadcapJake
Special thanks to: DennisCGc, Takano32, LeoTindall, Janus, Shinriyo, Marianne.
Citrine Community

Citrine respects your privacy and does not use cookies. For details read the Citrine Privacy Statement.
7252 visits since 3 March 2018