Documentation

In the following, you will learn everything you need apart from Python to write qb. For everything else, refer to the Python Documentation

Standard Library

qb comes with an extensive standard library. Here are all the different code objects that you can use


Functions

cout

Prints the given value to the console


Usage: cout("Hello, World!")
Output: Hello, World!
cin

Reads a line of input from the console


Usage: name = cin("Enter your name: ")
cout("Hello, " + name)

Output: Enter your name: John
Hello, John
lshift(x: int, y: int) -> int

Returns the result of shifting x to the left by y bits


Usage: result = lshift(2, 3)
cout(result)

Output: 16
rshift(x: int, y: int) -> int

Returns the result of shifting x to the right by y bits


Usage: result = rshift(16, 3)
cout(result)

Output: 2
head[T](xs: T) -> T

Returns the first object of an iterator


Usage: list = [1, 2, 3, 4, 5]
first = head(list)
cout(first)

Output: 1
tail[T](xs: T) -> T

Returns a copy of the iterator, omitting the first element


Usage: list = [1, 2, 3, 4, 5]
without_first = tail(list)
without_first(first)

Output: [2, 3, 4, 5]
@entrypoint(*args, **kwargs)

A unique decorator baked into the language to set the entrypoint for a program


Usage: @entrypoint
fn main(args):
    5 |> fac |> cout

fn fac(n):
    if n == 0:
        return 1
    else:
        return n * fac(n - 1)

Output: 120

Types

Some[T]

Opposite of the None type. Represents a value of type [T]


Attributes
  • value: A value of type [T]

Methods
  • unwrap(self) -> T: Returns the value of the Some object
  • __init__(self, value: T): Constructor

Usage: some = Some(5)
value = some.unwrap()
cout(value)

Output: 5
maybe

A type union that represents a value that may or may not be present


Usage: fn div(a, b) -> maybe:
    if b == 0:
        return None

    else:
        return Some(a / b)

result = div(5, 0)

match result:
    case Some(x):
        cout(x)

    case None:
        cout("Division by zero")

Output: Division by zero
either

A type union that represents a value that may be present or an error


Usage: fn div(a, b) -> either:
    if b == 0:
        return Exception("Division by zero")

    else:
        return Some(a / b)

result = div(5, 0)

match result:
    case Some(x):
        cout(x)

    case Exception(x):
        cout(x)

Output: Division by zero
collection

A lazy evaluated collection, that behaves like a list, but immutable with some neat additional methods


Attributes
  • *args: The elements of the collection

Methods
  • for_each: Recursively applies a function to every element of the collection and omits the output
  • map: Applies a function to every element of the collection and returns a new collection
  • filter: Filters the elements of the collection based on a function and returns a new collection
  • head: Returns the first element of the collection
  • tail: Returns a new collection without the first element
  • of: Creates a collection from an iterable

Usage: col = collection(1, 2, 3, 4, 5)
col.for_each(cout)
mapped_col = col.map(lambda x: x * 2)
filtered_col = col.filter(lambda x: x % 2 == 0)
first_element = col.head()
rest_elements = col.tail()
col_from_iterable = collection.of([6, 7, 8, 9, 10])

Output: 1
2
3
4
5
collection(2, 4, 6, 8, 10)
collection(2, 4)
1
collection(2, 3, 4, 5)
collection(6, 7, 8, 9, 10)
infinite_range

Returns an object that can be used similar to a normal range object, but with no end.


Attributes
  • start: The starting value of the range (default is 0)
  • step: The step value for the range (default is 1)

For a detailed description of the infinite_range type and it's usages, please refer to this section.





Syntax

qb is full with syntactic sugar to enhance your experience. Here is all the syntactic elements that you can use

Function definition

Function is qb are defined with the fn keyword. This is the case for normal and anonymous functions


Usage # Normal function
fn add(a, b):
    return a + b

# Anonymous function
add_anon = (fn a, b -> a + b)

add(5, 3) |> cout
add_anon(5, 3) |> cout

Output 8
8
In- and decreasing by one

qb allows you to in- and decrease an integer using ++ and -- respectively


Usage a = 5
a |> cout

a++
a |> cout

a--
a |> cout

Output 5
6
5
Checking for unequalness

To check if two values are not equal, you can use the <> operator


Usage a = 5
b = 3

a == b |> cout
a <> b |> cout

Output False
True
Ranges

qb lets you define ranges using the .. operator. It will create an exlusive range from the number infront of the operator to the number after the operator.


Usage 1..5 |> list |> cout
2..10 |> list |> cout

Output [1, 2, 3, 4]
[2, 3, 4, 5, 6, 7, 8, 9]

One thing special about qb is that it allows for infinite ranges. If you put no number after the operator, it will create an infinite range starting from the number infront of the operator.


Usage 1..[:5] |> list |> cout
1..[:10] |> list |> cout

for i in 1..:
    i |> cout

Output [2, 3, 4, 5]
[2, 3, 4, 5, 6, 7, 8, 9, 10]
1
2
3
4
5
...# to infinity
Entry point management

qb features a meta-decorator that allows you to set the entrypoint for your program. Simply put @entrypoint above your function and it will be set as the entry point. It also allows for the passing of parametres. Note that only one entry point can be present per file


Usage @entrypoint
fn main():
    5 + 5 |> cout

from sys import argv

@entrypoint(argv)
fn main(args):
    args |> cout

Output 10
['main.qb']
Multi line lambda

qb allows for anonymous functions with multiple lines. For this, enclose the logic of your function within {| |}


Usage collection(1, 2, 3, 4, 5).for_each(fn x -> {|
    x++
    x = x ** 2
    x |> cout
|})

Output 4
9
16
25
36
Pipe operator

The pipe operator |>, which you've already seen lots in these docs, can be used to "pipe" a value into a function from the left hand side and pass it as an argument.


Usage 5 |> (fn a, b -> a + b)(3) |> cout
Output 8