Skip to content

Basics

This section of the guide will rapidly cover the basics of RSL. RSL shares a lot of conventions and syntax with popular languages like Python, so if you're familiar with programming, this will be pretty straightforward.

Variables & Assignment

To create a variable, you can do it through assignment. Let's use a string example:

name = "Alice"

You can re-assign variables. Types don't need to stay the same:

name = 2

You cannot create multiple variables this way on one line.

The following is illegal syntax

a, b = "one", "two"

instead, declare each variable on one line.

a = "one"
b = "two"

Data Types

RSL's data types closely mirror those of JSON. Namely: strings, ints, floats, bools, lists, and maps.

Strings

Strings can be delimited in three ways:

  1. Double quotes: "text"
  2. Single quotes: 'text'
  3. Backticks: `text`

All three behave the same way. To demonstrate:

greeting = "Hello!"
print(greeting)

greeting = 'Hello!'
print(greeting)

greeting = `Hello!`
print(greeting)
Hello!
Hello!
Hello!

Why 3 different delimiters?

Having 3 different delimiters is particularly useful when you want your string to contain one (or more) of the delimiter characters.

For example, if you want a double quote in your string, you can use double quote delimiters and escape them:

"She said \"Goodbye\""

However, this can be finicky and hard to read. Instead, you can pick one of the other two delimiters, for example:

'She said "Goodbye"'
`She said "Goodbye"`

We'll cover this again later, but as a note, backticks can be particularly useful in shell commands, as shell/bash commands may include single or double quotes, and backticks save us from having to escape them.

Strings can include special characters such as \n for new lines and \t for tabs.

print("Hello\tdear\nreader!")
Hello   dear
reader!

RSL also supports raw strings. Raw strings do not allow any escaping (including the delimiter used to create them). Use them when you want your contents to remain as "raw" and unprocessed as possible.

To use them, just prefix the delimiter of your choice (single/double quotes or backticks) with r.

text = r"Hello\tdear\nreader!"
print(text)
Hello\tdear\nreader!

Notice the printed string is exactly as written in code - neither the tab nor newline character were replaced.

Again, you could use any of the three delimiters for raw strings:

text = r"Hello\tdear\nreader!"
text = r'Hello\tdear\nreader!'
text = r`Hello\tdear\nreader!`

Raw strings for file paths

Raw strings can be quite handy for file paths, especially Windows-style ones that use backslashes:

path = r"C:\Users\Documents\notes.txt"

You cannot escape the raw string's own delimiter

RSL raw strings behave more like their equivalent in Go than Python. In Python, you can escape the delimiter used to make the raw string i.e. r"quote: \"!". If printed, this will display as quote: \"! i.e. the escape character is also printed. There are lots of discussions online about this somewhat odd behavior, which is why RSL (and Go) opted to instead keep the rules very simple and not allow escaping in raw strings of any kind.

Instead, if you try the same thing in RSL, you will get an error because the quote following \ will close the string, leaving a dangling !" at the end, which is invalid syntax.

int

RSL has ints. There's nothing unusual about them. Example:

team_size = 20
celsius = -5

Note that if you divide two ints, you will get back a float.

liters = 10
people = 4
print("This is a float:", liters / people)
This is a float: 2.5

float

The other number type is float:

length_meters = 2.68

If you want to define a whole number as a float, simply include a decimal place:

years = 20.0

bool

RSL uses lowercase true / false:

is_running = true
is_tired = false

list

RSL has two collection types: lists and maps. First, let's look at lists. These are also sometimes referred to as 'arrays' in other languages.

names = ["alice", "bob", "charlie"]

Lists you define can contain any types:

mixed = ["alice", true, 50, -2.4]

They can also be nested:

nested = ["alice", [1, ["very nested", "ahhh"]]]

Indexing and slicing works very similarly to Python. If we assume the 3 variables above exist, you can index with both positive and negative indexes:

print(names[0])
print(mixed[-1])  // grab last element in the list
print(nested[1][1][0])
alice
-2.4
very nested

And also you can slice:

numbers = [10, 20, 30, 40, 50]
print(numbers[1:3])
print(numbers[2:])
print(numbers[:-1])
[20, 30]
[30, 40, 50]
[10, 20, 30, 40]

map

The last type, and second of two collection types, is a 'map'. These may also be referred to as 'hashmap' or 'dictionary' in other languages.

scores = { "alice": 25, "bob": 17, "charlie": 36 }

Like lists, they can contain mixed types for values, and can nest. However, keys must be strings.

mixed_map = { 
  "alice": "accountant",
  "mylist": [ "London", 25 ],
}

nested_map = {
  "error": {
    "msg": "Request failed!",
    "code": 400,
  }
}

If we take the above example, values can then be accessed in two ways. First is the square bracket lookup:

print(mixed_map["alice"])
print(nested_map["error"]["msg"])
accountant
Request failed!

Alternatively, you can use a dot syntax. Note this second way only works for keys with no spaces in the name.

print(mixed_map.alice)
print(nested_map.error.msg)
accountant
Request failed!

You can modify maps using either syntax:

Using brackets
mymap = { "alice": 30 }

mymap["alice"] = 40
print(mymap)

mymap.alice = 50
print(mymap)
{ alice: 40 }
{ alice: 50 }

You can also add keys this way:

mymap = { "alice": 30 }
mymap["bob"] = 31
mymap.charlie = 32
print(mymap)
{ alice: 30, bob: 31, charlie: 32 }

Operators

RSL offers operators similar to many other languages. Below sections very quickly demonstrate.

Arithmetic

RSL follows the standard order of operations for operators () , + , - , * , / , %:

  1. Parentheses
  2. Multiplication, Division, Modulo
  3. Addition, Subtraction
print(1 + 4 / 2)    // 3
print(2.5 * 3 - 1)  // 6.5
print((4 + 5) * 2)  // 18
print(5 % 3)        // 2

Dividing two integers will result in a floating point number.

print(5 / 2)  // 2.5

Comparison

Comparisons return bools that can be used in e.g. if statements.

String comparison is done based on contents.

print("alice" == "alice")  // true
print("alice" == "bob")    // false
print("alice" != "bob")    // true
print("alice" == "Alice")  // false

Numbers can also be compared with the standard comparators > , >= , < , <= , ==.

print(2 >= 2)  // true
print(2 > 2)   // false
print(2 <= 2)  // true
print(2 < 2)   // false
print(2 == 2)  // false

You cannot use these operators (outside of ==) to compare non-numbers such as strings:

print("alice" > "bob")  // error

But you can check them for equality (will always return false, except ints and floats that are equal):

print(2 == "alice")  // false
print(2 == 2.0)      // true

Difference From Python on True == 1 and False == 0

In Python, False == 0 and True == 1 are true, because under the hood, False is really int 0 and True is really int 1, hence they're equal. That's not the case in RSL. In RSL, any two values of different types are not equal.

The reasoning stems from truthy/falsy-ness. In Python, both 1 and 2 are truthy. But only 1 equals True. RSL avoids this oddity of making 1 special by instead making any two different types not equal (except ints/floats).

Logical

RSL uses and and or for binary logical operations.

print(false and false)  // false
print(false and true)   // false
print(true  and false)  // false
print(true  and true)   // true

print(false or  false)  // false
print(true  or  false)  // true
print(false or true)    // true
print(true  or  true)   // true

And it uses not for logical negation.

print(not true)   // false
print(not false)  // true

Concatenation

You can concatenate strings with +.

first = "Alice"
last = "Bobson"
print(first + last)
Alice Bobson

You cannot concatenate a string and a non-string. First convert the non-string into a string.

This can be done in several ways, the easiest is probably via string interpolation:

a = 5
text = "Number: "
print(text + "${a}")
Number: 5

Compound Operators

a = 3
a += 2   // a is now 5
a -= 1   // a is now 4
a *= 3   // a is now 12
a %= 10  // a is now 2
a /= 4   // a is now 0.5

RSL does not support ++ or -- syntax.

Ternary

RSL supports ? : style ternary operators.

<condition> ? <true case> : <false case>

a = 5
b = a > 0 ? "larger than 0" : "less than 0"
print(b)
larger than 0

Control Flow

If Statements

RSL employs very standard if statements.

You are not required to wrap conditions in parentheses ().

if units == "metric":
  print("That's 10 meters.")
else if units == "imperial":
  print("That's almost 33 feet.")
else:
  print("I don't know what measurement system!")

For Loops

RSL allows "for each" loops for iterating through collections such as lists.

names = ["Alice", "Bob", "Charlie"]
for name in names:
  print("Hi ${name}!")
Hi Alice!
Hi Bob!
Hi Charlie!

You can also iterate through a range of numbers using the range function, which returns a list of numbers within some specified range.

for i in range(5):
  print(i)
0
1
2
3
4

You can also invoke range with a starting value i.e. range(start, end) and with a step value i.e. range(start, end, step).

If you want to iterate through a list while also having a variable for the item's index, you can do that by adding in an additional variable after the for. The first variable will be the index, and the second the item.

names = ["Alice", "Bob", "Charlie"]
for i, name in names:
  print("${name} is at index ${i}")
Alice is at index 0
Bob is at index 1
Charlie is at index 2

When iterating through a map, if you have one variable in the loop, then that variable will be the key:

colors = { "alice": "blue", "bob": "green" }
for k in colors:
  print(k)
alice
bob

If you have two, then the first will be the key, and the second will be the value.

colors = { "alice": "blue", "bob": "green" }
for k, v in colors:
  print(k, v)
alice blue
bob green
  • TBC
  • switch

Truthy / Falsy

RSL supports truthy/falsy logic.

For those unfamiliar, this means that, instead of writing the following (as an example):

if len(my_list) > 0:
    print("My list has elements!")

you can write

if my_list:
    print("My list has elements!")

Essentially, you can use any type as a condition, and it will resolve to true or false depending on the value.

The following table shows which values return false for each type. All other values resolve to true.

Type Falsy Description
string "" Empty strings
int 0 Zero
float 0.0 Zero
list [] Empty lists
map {} Empty maps

Note that a string which is all whitespace e.g. " " is truthy.

Converting Types

  • TBC
  • parsing
  • casting (once implemented)