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 theSome
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 outputmap
: Applies a function to every element of the collection and returns a new collectionfilter
: Filters the elements of the collection based on a function and returns a new collectionhead
: Returns the first element of the collectiontail
: Returns a new collection without the first elementof
: 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 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
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
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
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
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']
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
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