Tutorial

!warning: This tutorial is in progress, and the code is not yet fully functional

Prerequisites

First, install or run the language in the browser, as explained here.

When you run the executable called "tablam" it enter in the "repl" mode, in the terminal. You write the code and press "Enter" key to execute.

You can also write the code in a text file with the extension ".tbm", and use a programming text editor like Sublime or Visual Studio Code, then call tablam -f name_file.tbm to execute it.

Introduction

Normally the tutorial of a programming language starts with the famous "hello world"1.

Then it shows some small taste of syntax and later pretends that you read the rest of the (potentially large) documentation and somehow, you will "get it".

We, instead, will do something different. We build a simple program (a mini shopping cart) that shows what is the point of the language.

But first is necessary to talk about what kind of programming language TablaM is. Is based on a paradigm called "Relational Model". What is that? You will learn almost everything just staring, intensely, at this table:

namepriceqty
Hamburger10.22
Soda3.04
French fries7.02
A table. Also a "relation".

You probably have guessed a lot of things just looking at this table. It looks like it talks about sales for a fast food store. You get an idea of what kind of products are available, at what prices and what quantities were given.

This is what makes the relational model its power. Is fairly "visual" and considers the data (relations) as "first-class citizen". But also, exist many other things that the relation tell us about:

Write the first program

Now, to express this relation in TablaM, you need to write in the repl, or a text editor, with a file called sales.tbm:

let sales:= [
  name:Str, price:Dec, qty:Int;
  "Hamburger", 10.2, 2;
  "Soda", 3.0, 4;
  "French fries", 7.0, 2;
]

Let's explain what all that text means:

nametypetype usage
nameStrFor text, data in UTF8 format
priceDecFor numbers, as 64 bit decimals, like money
qtyIntFor numbers, as 64 bit integers, like quantities, positions, counts, etc

Now with this data, we can do a lot of stuff, thanks to:

The relational operators

We can use "queries" to manipulate the data stored in relations. This "queries" are called relational operators because they express different operations on relations.

The character ? is called "the query operator" and mark when a relational operator will be used.

We will only worry about this 2 operations for now:

?select

The ?select operator (aka: projection or SELECT * FROM in SQL), allow filtering the columns in a relation. Using the character # to indicate that is a name (like #price) or a number (like #0) of a column:

let products := sales ?select #name
print(products)
> Vec[name:Str; 'Hamburger'; 'Soda'; 'French fries']

?where

The ?where operator (aka: selection or where... in SQL), allow filtering the rows in a relation. It needs a "Boolean expression*", i.e.: expression that compares values, columns or returns true/false. The = is the equal operator, more logical operators.

-- let soda := sales ?where #name = "Soda" (TBD)
let soda := sales ?where #0 = "Soda" -- #0 is #name column

let cheaper := sales ?where #1 < 5.0 -- #1 is #price column

Some math

Now we can start to do more stuff. We can know how many money we get for this sale:

let profit_items := sales?select #price * #qty -- arithmetic operations in relational operators (TBD)
print(profit_items)
let profit_total := sum(profit_items)
print(profit_total)

And which product give the biggest profit:

let most := sales?select #price * #qty
let most := max(most)
print(most)

Note how each operation work in relations and return relations.

Single values like 1 or "Soda" are also relations. Also know as "scalars". TablaM considers it relations of 1 whole column, 1 whole row and 1 cell.

This mean that this is possible:

let price := 1.0 ?select #0

Now, we can continue with the program and make it more useful. We said before that the values are "immutable" by default. This mean that if we want to change them we need to create new values from the olds. Let's add another sale:

let new_sale := ["Hot dog", 4.0, 1]
let sales := add(sales, new_sale)
print(sales)

Something weird happened here. TablaM use types to not mix wrong things, yet where it say that new_sale is [name:Str, price:Dec, qty:Int;]?.

Well, is because TablaM use a neat trick: Their values are not only typed, but also compared structurally. In other languages, two things are different just to be named differently:

// In rust, a nominal typed language
struct SalesA {name:Str, price:Dec, qty:Int}
struct SalesB {name:Str, price:Dec, qty:Int}
let a := SalesA::new("Hot dog", 4.0, 1)
let b := SalesB::new("Hot dog", 4.0, 1)
a = b //false

Instead, in TablaM, two things are equal if their schema/header match:

-- In TablaM, a structural typed language
let a := ["Hot dog", 4.0, 1]
-- is automatically infered the header [name:Str, price:Dec, qty:Int;]

let b := [name:Str, price:Dec, qty:Int; "Hot dog", 4.0, 1]
a = b -- true!

Comming soon in "TablaM, the awesome programming language":

Sorry for the cliffhanger, but TablaM is still in development. Hopefully we can answer:

If wanna to support this vision, please consider fund the project clicking in:

Buy Me A Coffee

or helping in the developing at https://github.com/Tablam/TablaM.

1

And is print("hello world"), by the way.