Intro
Intro to Sire
Sire is the default language for Pallas and is bootstrapped directly from PLAN. It is also possible to compile mainstream functional languages to PLAN. At that point, much Pallas development—including full-stack web applications—will be accomplished by writing in those languages only, leaving Sire responsible for code that needs to be optimized by the runtime (like new crypto libraries, say).
Getting familiar
Open up a bootstrapped Sire REPL. As a reminder:
Or if you're using the docker images:
We're going to hands-on learn a few basic concepts: Top-level bindings, let bindings and function application.
A few meta-points to note at the outset:
;
is a comment in Sire. used here, it'll be to explain what's happening inlineThe arrow keys won't work in the REPL. Use backspace. If you get into a strange state with carriage returns and are unable to backspace, just hit return a few times, ignore any errors, and start again.
The REPL will print ASCII values of integers. If you enter
65
you'll get back%A
. Don't think about this too much yet. We'll cover this in detail on the next page.There is no input prompt in the REPL. And the result of the previous computation (after hitting
enter
) is just printed out on the next line. So if you're only reading and not following along live in the REPL, generally the first line of text you see in a code block is the user input, and the lines following it is the result of hitting theenter
key.The single-character "symbolic operators" you'll see here are referred to as runes. They are core syntactic elements that perform various functions in Sire, like function application and data structure definition.
Top-level binding - =
=
Binds a value globally - not scoped.
In the REPL:
Function application - |
, ()
|
, ()
add
is a function in Sire. It takes two arguments and adds them together. We apply add
to 1
and 3
like so:
You can also apply functions with ()
:
This is actually a short form for (| add 1 3)
- we're still doing function application with |
under the hood, but the |
rune is a special case that can be omitted in this context. All runes can be written several different ways (as you'll see next with the =
rune).
Let's combine both of the above concepts to create our own named function. Note the way in this case you start the line with =
(followed by a space) and the name of the function is the first value after the opening parenthesis.
The REPL now has a function named addTwo
bound to its top-level scope. The function takes a single value (called input
) and all it does is apply (with |
) the add
function to two arguments, a hard-coded 2
and whatever input was provided.
Scoped/Let binding - @
@
@
binds a value to the present scope.
We can see this by trivially modifying our addTwo
function to bind an arbitrary name and use that for the addition:
On the second line, we bound a new name, renamedInput
with the value of originalInput
. Then 2
is added to it.
To prove to yourself that renamedInput
is only bound within the function scope, try calling it at the top-level of the REPL:
Natural numbers, byte-arrays and strings
Nat - natural number
All values in Pallas are trees, whose leaves are natural numbers. Throughout the system, these are referred to as "nats". The REPL will represent these values as ASCII for printing purposes, which can be confusing at first and should be noted up front. For instance, the character a
is encoded as 97
in ASCII:
The full explanation is of how nats are rendered is here, but we suggest you continue along for now without getting too bogged down in the REPL representation of nats.
Bar - byte-array, and Strings
A "bar" is an array of UTF-8 bytes. You create a bar like this:
You only need to use the curly braces when spaces are present in your byte array:
While it may be attractive to think about bars and strings interchangeably, they are not identical and when working between the two you'll often need to use conversion functions (like natBar and barNat. There are more standard library functions for working with bars on a structural level (folding, splitting at indexes, filtering, etc.) while the string standard library functions are more geared to character-level functions like capitalization and checking if a character is an alphanumeric.
Trust us that you can and should basically just use bars for everything string-like and you can move along to the section on data structures below, but if you're interested in seeing the deep dive, it's here.
A Few Simple Data Structures
Rows - []
[]
Rows/vectors are basically arrays (not Lists - see below). They are defined with [ ]
:
We'll get into more of the standard library/convenience functions later, but we'll need a few now, too, in order to prove to ourselves some details of rows. idx
is used to get the value at a given index in a row:
len
will give you the size of the row:
Lists - ~[]
~[]
Lists are zero-terminated, nested row 2-tuples. They are declared by prepending a ~
to what looks like row syntax, like this: ~[]
(in the REPL we have to wrap this in parentheses):
Incidentally, you can create a list from a row with the listFromRow
function:
Comparison, Booleans and Maybes
TRUE
is represented as the nat 1
, while FALSE
is the nat 0
.
The =?=
operator is a unit test. It's scope is the same as a top level definition and so it cannot be used within a function.
It takes two arguments and exists source file loading if they are not equal, otherwise it evaluates without issue.
eql
and friends
eql
and friendsThe eql
function takes two parameters and returns TRUE
if they're equal)
Similarly, we have neq
for "not equal". Also:
lth
- true when first parameter is less than secondlte
- true when first parameter is less then or equal to secondgth
- true when first parameter is greater than secondgte
- true when first parameter is greater than or equal to second
if
if
if
is a function with three parameters: what is being tested for truthiness; what to return if true; what to return if false.
The if
function's first parameter was 1
, a true value, so the second parameter was returned.
not
not
Negation.
and
, or
and
, or
and
and or
are functions that do what you'd expect:
Last updated