Foreword
Under Construction
Introduction
Welcome to The Calyxium Programming Language, an introductory book about Calyxium. The Calyxium programming language helps you write faster, reliable software. High-level ergonomics with purity, safety, and speed.
Who Calyxium is For
Calyxium is ideal for many people for a variety of reasons. Let’s look at a few of the most important groups.
Students
Calyxium is for students and those who are interested about learning functional programming concepts. Using Calyxium, many people have learned about topics like expression based languages, immutable variables and polymorphism. The community is very welcoming and happy to answer student questions. Through efforts such as this book, the Calyxium teams want to make functional concepts more accessible to more people, especially those new to programming.
who Is This Book For
This book assumes that you’ve written code in another programming language but doesn’t make any assumptions about which one. We’ve tried to make the material broadly accessible to those from a wide variety of programming backgrounds. We don’t spend a lot of time talking about what programming is or how to think about it. If you’re entirely new to programming, you would be better served by reading a book that specifically provides an introduction to programming. Don't feel threatened if you are new however, as it can be a good brain exercise, and you are also challenging yourself to do something new. Not a lot of people are doing that these days!
How to Use This Book
In general, this book assumes that you’re reading it in sequence from front to back. Later chapters build on concepts in earlier chapters, and earlier chapters might not delve into details on a particular topic but will revisit the topic in a later chapter.
You’ll find two kinds of chapters in this book: concept chapters and project chapters. In concept chapters, you’ll learn about an aspect of Calyxium. In project chapters, we’ll build small programs together, applying what you’ve learned so far. Chapters 2, 12, and 21 are project chapters; the rest are concept chapters.
Chapter 1 explains how to install Calyxium, how to write a “Hello, world!”
program.
Chapter 2 is a hands-on introduction to writing a program in Calyxium, having you build up a number guessing game. Here we cover concepts at a high level, and later chapters will provide additional detail. If you want to get your hands dirty right away, Chapter 2 is the place for that.
Chapter 3 covers Calyxium's features that are similar to those of other programming languages. If you’re a particularly meticulous learner who prefers to learn every detail before moving on to the next, you might want to skip Chapter 2 and go straight to Chapter 3, returning to Chapter 2 when you’d like to work on a project applying the details you’ve learned.
Chapter 5 discusses classes, structs and methods, and Chapter 6 covers enums, match
expressions, and the if
then
else
control flow construct.
Finally, some appendixes contain useful information about the language in a more reference-like format. Appendix A covers Calyxium’s keywords, Appendix B covers Calyxium’s operators and symbols and Appendix C covers Calyxium's built-in functions.
There is no wrong way to read this book: if you want to skip ahead, go for it! You might have to jump back to earlier chapters if you experience any confusion. But do whatever works for you.
The website version also contains a handy search feature over ↑ which you can use to search for Code Snippets in Appendix D or for anything else you can think of.
The Appendix
Under Construction
The following sections contain reference material you may find useful in your Calyxium journey.
Keywords
Operators
Functions
Snippets
Feel free to keep these tabs open in your browser as a reference you can alt
+ tab
to quickly.
Appendix A: Keywords
The following list contains keywords that are reserved for current or future use by Calyxium. As such, they cannot be used as identifiers. Identifiers are names of functions, variables, parameters, structs fields, modules, types.
Keywords Currently in Use
The following is a list of keywords currently in use, with their functionality described.
rec
- define a recursive functionif
- branch based on the result of a conditional expressionthen
- fallback forif
control flow constructselse
- fallback forthen
andif
control flow constructslet
- bind a variable or functionmatch
- match a value to patternswith
- branch based on the value of matchuse
- in a module path, refers to the modules rootmod
- define a moduletrue
- Boolean true literalfalse
- Boolean false literalenum
- define an enumerationrecord
- define a recordtype
- define a ADTfn
- define a anonymous functions, lambda abstraction
Deprecated keywords
Superseded byfor
- loops over itemsrec
Keywords Reserved for Future Use
The following keywords do not yet have any functionality but are reserved by Calyxium for potential future use.
class
extends
ref
Appendix B: Operators and Symbols
This appendix contains a glossary of Calyxium's syntax, including operators and other symbols that appear by themselves or in the context of paths, comments, tuples, brackets.
Operators
Table B-1 contains the operators in Calyxium, an example of how the operator would appear in context, a short explanation.
Table B-1: Operators
Operators | Example | Explanation |
---|---|---|
not | not expr | logical complement. |
!= | expr != expr | Nonequality comparison. |
== | expr == expr | Equality comparison. |
> | expr > expr | Greater than comparison. |
< | expr < expr | Less than comparison. |
>= | expr >= expr | Greater than or equal to comparison. |
<= | expr <= expr | Less than or equal to comparison. |
&& | expr && expr | Short-circuiting logical AND. |
+ | expr + expr | Arithmetic addition. |
- | expr - expr | Arithmetic subtraction. |
- | - expr | Arithmetic negation. |
* | expr * expr | Arithmetic multiplication. |
/ | expr / expr | Arithmetic division. |
% | expr % expr | Arithmetic remainder. |
** | expr ** expr | Arithmetic power. |
lsl | expr lsl expr | Left-shift. |
lsr | expr lsr expr | Right-shift. |
= | var = expr | Assignment. |
+= | var += expr | Arithmetic addition and assignment. |
-= | var -= expr | Arithmetic subtraction and assignment. |
*= | var *= expr | Arithmetic multiplication and assignment. |
/= | var /= expr | Arithmetic division and assignment. |
&= | var &= expr | Bitwise AND and assignment. |
`= | var `= expr | Bitwise OR and assignment. |
$= | var $= expr | Bitwise XOR and assignment. |
<<= | var <<= expr | Left-shift and assignment. |
>>= | var >>= expr | Right-shift and assignment. |
++ | var++ , expr++ | Incrementation. |
-- | var-- , expr-- | Decrementation. |
lor | expr lor expr | Bitwise OR. |
lxor | expr lxor expr | Bitwise XOR. |
lnot | lnot expr | Bitwise NOT. |
land | expr land expr | Bitwise AND. |
-> | pat -> expr | Part of match arm syntax. |
|> | var |> expr , expr |> expr | Passes left-hand value as input to right-hand expression. |
| | | pat | Part of match arm syntax. |
! | !var | Dereference mutable copy. |
^ | string ^ string | String concatenation. |
@ | array @ array | Array concatenation. |
.. | 1..10 , 1.. | Range operator (inclusive). |
? | cond ? expr : expr | Part of ternary conditional operator. |
: | var: type , cond ? expr : expr , array[start:end] | Type ascription or ternary branch separator, or slice range separator. |
; | expr; expr | Expression separator. |
. | object.field | Member access. |
_ | match x with | _ -> ... | Wildcard pattern. |
, | (a, b) | Comma separator (lists, tuples, args). |
:= | var := expr | Mutable copy assignment. |
Table B-2 shows symbols that create comments.
Table B-2: Comments
Symbol | Explanation |
---|---|
-- | Line comment |
-- $ | Inner line doc comment |
Table B-3 shows the contexts in which curly braces are used.
Table B-3: Curly Brackets
Context | Explanation |
---|---|
{...} | Block expression |
Table B-3 shows the contexts in which square brackets are used.
Table B-3: Square Brackets
Context | Explanation |
---|---|
[...] | Array literal |
expr[expr] | Collection indexing. Overloadable (Index ) |
Appendix C: Built-in functions
This appendix contains a glossary of Calyxium's built-in functions.
Under Construction
Built-ins Currently in Use
The following is a list of built-ins currently in use, with their functionality described.
panic
- immediately terminates the program and displays the given error messageprint
- prints to the terminalto_float
- converts integers to floatsto_int
- converts floats to integersto_bytes
- converts strings to an array of byteslength
- returns the size of an array or stringinput
- displays the prompt and reads a line of text from standard input, returning it as a unit.assert
- fails if the boolean expression is falsehead
- returns the first element of an arraytail
- returns a new array containing all elements except the firstreverse
- returns a new array with elements in the opposite order
Built-ins Reserved for Future Use
The following built-ins do not yet have any functionality but are reserved by Calyxium for potential future use.
map
- applies a function to each element of an array, returning a new array with the resultsfilter
- returns a new array containing only the elements for which the function returnstrue
fold
- reduces an array to a single value by applying a function cumulatively
Appendix D: Code Bytes
This appendix contains some commonly used snippet examples in Calyxium; designed to be searched by that search bar up ↑ give it a try!
Under Construction
For loops
As you can see in Appendix A for
loops have been discontinued
and are no longer accessible. For those of you who are used to imperative programming this may seem like a shock;
how am I supposed to loop things? You may ask, well its pretty simple. You use the rec
keyword. Below is a template for
loop and how to use it.
let rec iterator(index, max) {
if index < max then {
print(index)
iterator(index + 1, max)
}
}
iterator(0, 9)
The following code will run print
10 times.
This is a very simple for
loop style function but they can get much more
complex giving you more control than the standard for
keyword from other languages.
Calling the iterator
function starts the loop and you pass in index 0 and the max loop value.
Passing in the values like this is similar to for i in range(start, end)
in Python.
While loops
You can do a similar thing for a while
loop with the following code.
let rec iterator() {
print("I'm a happy while loop!")
iterator()
}
iterator()
Getting Started
Under Construction
Let's start your Calyxium journey! There’s a lot to learn, but every journey starts somewhere. In this chapter, we’ll discuss:
- Installing Calyxium on Linux, macOS and Windows
- Writing a program that prints
Hello, world!
Feel free to keep the Appendix tab open in your browser.
Installation
The first step is to install Calyxium. We'll download Calyxium through calyxup
, a command line tool for managing Calyxium versions and associated tools. You’ll need an internet connection for the download.
Note: if you prefer not to use
calyxup
for some reason, please see the Alternative Calyxium Installation Methods page for more options.
The following steps install the latest stable version of Calyxium, which is compatible with all of the book's examples. Some program outputs may vary from the book because Calyxium often improves error messages and warnings. In other words, any newer, stable version of Calyxium you install using these steps should work as expected with the content of this book.
Command Line Notation
Throughout the book, we’ll show some commands. Lines entered in the terminal all start with
$
or>
. You don’t need to type either character; it’s the command line prompt shown to indicate the start of each command. Lines that don’t start with$
typically show the output of the previous command. Unless stated otherwise, PowerShell-specific examples will use>
rather than$
.
Calyxium Installer
Currently Calyxup isn't finished so you are going to have to install the latest version semi manually from the downloads page
Installing Calyxium
and calyxup
on Windows, Linux and MacOS
PowerShell is required for calyxup you can find instructions on how to install PowerShell here
Open a PowerShell terminal and enter the following command:
> curl --proto '=https' --tlsv1.2 <add link> | pwsh -Command -
The command downloads a script and starts the installation of the calyxup
tool, which installs the latest stable version of Calyxium. You might be prompted
for your password.
TODO add install instructions when calyxup is done
Installing the calyxium-lang
Extension
It is highly recommended to install the calyxium-lang
extension by following the instructions here.
Useful Development Tools
This is a list of useful development tools
Formats
Extensions
Installing the calyxium-lang
Extension
To enable syntax highlighting and LSP server support, it's recommended to install the calyxium-lang
extension for your preferred text editor.
Visual Studio Code (VS Code)
Click this link to open VS Code to the extension page
Click install, you may be asked to restart VS Code.
Vim
Installation instructions coming soon.
Hello, world!
Now that you've installed Calyxium, it's time to write your first Calyxium program. It's traditional when learning a new language to write a little program that prints the text Hello, world! to the screen, so we’ll do the same here!
Creating a Project Directory
You'll start by making a directory to store your Calyxium code. It doesn't matter to Calyxium where your code lives, but for the exercises and projects in this book, we suggest making a projects
directory in your home directory and keeping all
your projects there.
Open a terminal and enter the following commands to make a projects
directory
and a directory for the “Hello, world!”
project within the projects
directory.
For Linux, macOS and PowerShell on Windows, enter this
$ mkdir ~/projects
$ cd ~/projects
$ mkdir hello_world
$ cd hello_world
For Windows CMD, enter this:
> mkdir "%USERPROFILE%\projects"
> cd /d "%USERPROFILE%\projects"
> mkdir hello_world
> cd hello_world
Writing and Running a Calyxium Program
Next, make a new source file and call it main.cx
. Calyxium files always end with
the .cx
extension. If you’re using more than one word in your filename, the
convention is to use an underscore to separate them. For example, use
hello_world.cx
rather than helloworld.cx
.
Now open the main.cx
file you just created and enter the code in listed below.
print("Hello, world!")
Save the file and go back to your terminal in the
~/projects/hello_world
directory. Enter the following
commands to run the file:
$ calyxium main.cx
Hello, world!
Regardless of your operating system, the string Hello, world!
should print to
the terminal.
If Hello, world!
did print, congratulations! You’ve officially written a Calyxium
program. That makes you a Calyxium programmer. Welcome to the club!
Let’s review this “Hello, world!” program in detail.
print("Hello, world!")
This line does all the work in this little program: it prints text to the screen. There are two important details to notice here.
-
print
calls the function to display contents to your terminal. -
You see the
"Hello, world!"
string. We pass this string as an argument toprint
, and the string is printed to the screen. -
Unlike in Python,
print
does not automatically add a newline (\n
) at the end. If you want a line break, you’ll need to include\n
yourself.
Programming a Guessing Game
Under Construction
Common Programming Concepts
This chapter covers concepts that appear in almost every programming language and how they work in Calyxium. Many programming languages have much in common at their core. None of the concepts presented in this chapter are unique to Calyxium, but we’ll discuss them in the context of Calyxium and explain the conventions around using these concepts.
Specifically, you’ll learn about variables, basic types, functions, comments, and control flow. These foundations will be in every Calyxium program, and learning them early will give you a strong core to start from.
Keywords
The Calyxium language has a set of keywords that are reserved for use by the language only, much as in other languages. Keep in mind that you cannot use these words as names of variables or functions. Most of the keywords have special meanings, and you’ll be using them to do various tasks in your Calyxium programs; a few have no current functionality associated with them but have been reserved for functionality that might be added to Calyxium in the future. You can find a list of the keywords in Appendix A.
Variables and Mutability
By default, variables are immutable. This is one of the many nudges Calyxium gives you to write your code in a way that takes advantage of the safety that Calyxium offers. However, you still have the option to make your variables mutable. Let’s explore how and why Calyxium encourages you to favor immutability and why sometimes you might want to opt out.
When a variable is immutable, once a value is bound to a name, you can't change that value. To illustrate this, generate a new file called variables.cx
in your projects
directory.
Then, open variables.cx
and add it's following code which won't interpret just yet:
Filename: variables.cx
let x = 10
x := 12
Save and run the program using calyxium variables.cx
. You should receive an error message regarding an immutability error, as shown in this output:
This example shows how the interpreter helps you find errors in your programs.
interpreter errors can be frustrating, but really they only mean your program
isn’t safely doing what you want it to do yet; they do not mean that you’re
not a good programmer! Experienced
You received the error message:
random `x`
because mutable x
doesn't exist yet add later.
Data Types
Under Construction
In calyxium there are 5 primitive data types
Int
This is an integer number (whole number) and is used to store numbers without decimals, it can be positive and negative.
It ranges between LOWEST
and HIGHEST
. If you try to make it bigger or smaller than these ranges you will get unintended results.
For example 10
or -3000
To specify an int in code you can just type out the number.
Float
This is any number and is used to store numbers with decimals, it can be positive and negative.
It ranges between LOWEST
and HIGHEST
. If you try to make it bigger or smaller than these ranges you will get unintended results.
The term float refers to the fact that the decimal can "float" between positions. Its full name is Floating Point Number.
For example 10.009
or -3000.33
To specify a float in code you can add .0
to the end of the number.
One interesting property of floats is that the higher the number the less precise the number will be because there isn't enough room to store the digits after the decimal point.
Say a the max size of a float is 7 characters, when the numbers before the decimal are only 3 characters 200.457
you will have enough room for 3 more numbers, however if there are 5 characters 20000.1
you only have enough room for 1 number after the decimal making the number much less precise, and you can start to get artifacts in your computations. This is what causes graphical artifacts in games where the players position can become high enough to start allowing floating point precision problems.
String
This is a string (sequence) of chars and is used to store any word, phrase, paragraph you can think of!
The term string comes from "stringing" a sequence of characters together. The longest string you can make is HIGHEST
.
Although some devices may not be able to display them, strings can hold any character you will come across; that is,
if they are within the char size limit.
For example "Hello world!"
or "جبن"
or even "😎👍"
To specify a string in code you just surround anything you want to write with a "
character
Byte
This is a single character and is want a string is composed of. Again, it can be any character you can think of.
It can also be referred to as a char. The biggest character you can make is BYTES
bytes. Once again, although some devices may
not be able to display them, chars can be any character you will come across, as long as they are within the limit.
If you try and put more than one character in a char you will get an error, so just make it a string if you are unsure.
For example 'ö'
or 'ب'
or even '😎'
To specify a byte in code you just surround a single character you want to write with a '
character
Bool
Short for boolean, this data type has 2 states true
or false
. Sort of like a yes or no.
By doing not my_boolean
you can reverse a boolean. These are used to control the flow of a program.
The name comes from English mathematician George Boole who developed Boolean algebra.
These are the least memory intensive only taking a single bit of storage.
To write a boolean simply write true
or false
.
How Functions Work
Under Construction
Comments
All programmers strive to make their code easy to understand, but sometimes extra explanation is warranted. In these cases, programmers leave comments in their source code that the interpreter will ignore but people reading the source code may find useful.
Here’s a simple comment:
-- hello, world
In Calyxium, the idiomatic comment style starts a comment with two dashes, and the
comment continues until the end of the line. For comments that extend beyond a
single line, you’ll need to include --
on each line, like this:
-- So we're doing something complicated here, long enough that we need
-- multiple lines of comments to do it! Whew! Hopefully, this comment will
-- explain what's going on.
Documentation Comments
Calyxium also supports a second kind of comment, documentation comments. These are used to provide structured, tool-readable documentation for your code, such as functions, constants, or modules.
Here’s a simple documentation comment:
-- $ hello, world i am a documentation comment $
In Calyxium, documentation comments follow the same syntax rules as normal comments, but with a special marker (-- $ ... $
) to distinguish them. These comments are designed to integrate with your text editor to provide features like:
- Hover tooltips
For example:
-- $ Returns the square of a number $
let square(x) {
x * x
}
To enable documentation comment support in your editor, install the calyxium-lang Extension.
Control Flow
Under Construction
It's not a bug it's a feature
Under Construction
Alternative Installation methods
Note: It is highly recommend that you use
calyxup
. Standard Installation Method page.
This guide is not for the faint hearted. You have been warned!\
Building it yourself
This method may not always result in a successful install as the version of Calyxium on Github may have some compatibility issues; especially if you use the dev branch. It is recommend that you stay on the the main branch which has less updates but should remain compatible for all devices. Of course, because you are using a more up to date version of Calyxium that has not been publicly released yet there may be new breaking changes that have not yet been documented in the books. With that out of the way, lets start with cloning the repository:
Cloning the repository
The first thing you want to do to build calyxium yourself is to clone the repository
You will need some form of Git to clone the repository. See methods here
If you have Github Desktop installed you can go to the repository
and click the Code
Button, then press the Open with Github Desktop
button and Github Desktop should open asking you if you would like to clone the repository, press the blue Clone
button.
If you do not have Github Desktop but do have Git installed you can enter the following command into any terminal.
Make sure you are in the target parent directory of where you want the repository to be cloned.
This is normally located at %USERPROFILE%\Documents\Github\
for Windows users. To ensure the repository is cloned to that location enter this command into your terminal.
> git clone https://github.com/calyxium-lang/calyxium %USERPROFILE%\Documents\Github\calyxium
If you are not a Windows user or are already in the target parent directory run this command instead.
> git clone https://github.com/calyxium-lang/calyxium
Installing OCaml
Now that you have cloned the repository you will need to go through the process of installing OCaml onto your system.
You can download and install OCaml from the official site.
Installing Dune
Once you have installed OCaml you will need to install Dune using the following command.
$ opam install dune menhir
If you are having issues with opam, remember to activate the opam switch with the following command on cmd.
$ for /f "tokens=*" %i in ('opam env') do @%i
and for PowerShell use this command.
> (& opam env) -split '\r?\n' | ForEach-Object { Invoke-Expression $_ }
Please note that on Windows if you want to use the
dune
orcalyxium
commands you will need to run either of the above commands whenever you start a new terminal.opam
should not require this. The book will assume you have ran the command above.
If you want to circumvent this you have 2 options, either add dune
and calyxium
to the system environment variables, or make a new terminal profile which automatically runs the command when opened. It is recommend to do the latter approach because you don't have to do this same process if you use other opam tools, you should also add calyxium
to the system variables so its accessible to all terminal processes; calyxup
would normally do this for you.
Adding to system variables
To add calyxium
to the system environment variables run this command in PowerShell. This is assuming you cloned the repository to the recommended path.
For those curious USERPROFILE
is just your C:\Users\NAME\
Folder, but it works for everybody, so no need to change anything!
> $target = "$env:USERPROFILE\Documents\GitHub\calyxium\_build\default\bin"; $old = [Environment]::GetEnvironmentVariable("Path", "User"); if (-not ($old -split ';' | ForEach-Object { $_.Trim() } | Where-Object { $_ -eq $target })) { [Environment]::SetEnvironmentVariable("Path", "$old;$target", "User") }
Creating terminal profile
To create a new terminal profile which automatically runs the command afore mentioned whenever opened begin by pressing Windows
and then typing out terminal
and pressing enter
. This should open a new terminal. Now press the ^
button next to the +
button. This should open a menu. Press the Settings
button. Then down in the bottom left corner press the Open JSON file
button. This should now open notepad. In here add the following JSON block in the list of profiles.
{
"colorScheme": "CGA",
"commandline": "cmd.exe /k for /f \"tokens=*\" %i in ('opam env') do @%i",
"guid": "{f79c35ac-42f6-4755-82db-da7e34ac0399}",
"hidden": false,
"icon": "%USERPROFILE%\\Documents\\Apps\\ocaml-logo.png",
"name": "OPAM",
"startingDirectory": "%USERPROFILE%"
},
You can put it anywhere you like in the list to determine which order it shows up on the menu.
To give the terminal an icon like the rest you can download this picture.
This JSON specifies the logo to be located at Documents\Apps\
however you can put it wherever you like. You can also use a different icon if you wish. You can also use a different theme or even a different profile name, but keep the commandline
the same.
Bonus tip
If you didn't know, in Windows Explorer you can click the directory bar, type cmd
, and hit enter. This handy shortcut allows you to open a terminal right within the directory, so you don't have to cd
to whichever folder you want to be in.
This bonus tip is going to show you how you can do this with this new profile you created with whatever keyword you want.
To do this make a new .bat
file named what you want to type in to open this new profile terminal. For example opt
(opam terminal)
then enter the following code into the file and save it to where you want. In this instance we will use the directory where we put our icon earlier.
@echo off
setlocal
set "cwd=%cd%"
wt -p "OPAM" -d "%cwd%"
Alternatively with your new found shortcut abilities go into this directory in explorer and enter pwsh
into the directory bar and hit enter.
Now paste this code to generate the opt.bat
script for you, and you can simply rename it after if you wish by hitting F2
. Do not set the name to any pre existing command names or shortcuts as this will not work.
> Set-Content -Encoding ASCII opt-launch.bat "@echo off`nsetlocal`nset `"cwd=%cd%`"`nwt -p `"OPAM`" -d `"%cwd%`""; $s=(New-Object -ComObject WScript.Shell).CreateShortcut("$PWD\opt.lnk"); $s.TargetPath="$PWD\opt-launch.bat"; $s.WindowStyle=7; $s.Save()
After you've done this you can run the following script to add the path to your environmental variables. Again use PowerShell and note that this will assume you have put the .bat
in the same directory as the .png
icon.
> Set-Content -Encoding ASCII opt.bat "@echo off`nsetlocal`nset `"cwd=%cd%`"`nwt -p `"OPAM`" -d `"%cwd%`""
Now you can use the opt
shortcut in Windows Explorer and on the start menu, that means you can press Windows
and type opt
press enter
and it will also open the terminal profile. Neat!
Running Dune
Now that you've installed Dune and hopefully made a new terminal profile and completed the bonus tip we can opt
into the %USERPROFILE%\Documents\GitHub\calyxium
directory and run the following 2 commands in sequence.
$ dune build --profile release
$ dune install
Pretty self explanatory right? Thats it! You've completed this tutorial. You deserve a pat on the back! If you ever pull a new commit from the base repository, before you try and use Calyxium, run the following command to stop anything strange from happening (speaking from experience). Then run both commands again.
$ dune clean