Tau
A functional interpreted programming language with a minimalistic design.
Install / Use
/learn @NicoNex/TauREADME
τ
Tau is a dynamically-typed open-source concurrent programming language designed to be minimal, fast and efficient.
Installation
In order to install Tau, you'll need Go and GCC.
Clone the repo with
git clone --recurse-submodules https://github.com/NicoNex/tau
cd tau
sudo make install
You can try it out in the terminal by simply running tau.
For additional info run tau --help.
Syntax
Hello World
We all start from here...
println("Hello World")
Examples
File
As every interpreter Tau supports files either by passing the path to the interpreter or by using the shebang.
#!/path/to/tau
println("hello world")
$ tau helloworld.tau
hello world
if-else blocks
myVar = 10
if myVar > 10 {
println("more than 10")
} else if myVar == 10 {
println("it's exactly 10")
} else {
println(myVar)
}
Declaring a function
fib = fn(n) {
if n < 2 {
return n
}
fib(n-1) + fib(n-2)
}
println(fib(40))
Noteworthy features
The return value can be implicit:
add = fn(x, y) { x + y }
sum = add(9, 1)
println(sum)
>>> 10
Also you can inline the if expressions:
a = 0
b = 1
minimum = if a < b { a } else { b }
The semicolon character ; is implicit on a newline but can be used to separate multiple expressions on a single line.
printData = fn(a, b, c) { println(a); println(b); println(c) }
Functions are first-class and treated as any other data type.
min = fn(a, b) { if a < b { a } else { b } }
var1 = 1
var2 = 2
m = min(var1, var2)
println(m)
>>> 1
Error handling
# errtest.tau
div = fn(n, d) {
if d == 0 {
return error("zero division error")
}
n / d
}
if failed(result1 = div(16, 2)) {
exit(result1)
}
println("the result of 16 / 2 is {result1}")
if failed(result2 = div(32, 0)) {
exit(result2)
}
println("the result of 32 / 0 is {result2}")
$ tau errtest.tau
the result of 16 / 2 is 8
error: zero division error
$
Beautiful error messages
# errtest.tau
increment = fn(n) {
return n + 1
}
increment("this will raise a runtime error")
error in file errtest.tau at line 4:
return n + 1
^
unsupported operator '+' for types string and int
Concurrency
Tau supports go-style concurrency.
This is obtained by the use of four builtins pipe, send, recv close.
pipecreates a new FIFO pipe and optionally you can pass an integer to it to create a buffered pipe.sendis used to send values to the pipe.recvis used to receive values from the pipe.closecloses the pipe.
Pipes can be buffered or unbuffered. Buffered pipes make the tau-routine sleep once send is called until at least one value is read from the pipe.
Once recv is called on an empty pipe it will cause the tau-routine to sleep until a new value is sent to the pipe.
send is used to send values to the pipe.
close closes the pipe thus allowing it to be garbage collected.
Calling recv on a closed pipe will return null.
listen = fn(p) {
for val = recv(p) {
println(val)
}
println("bye bye...")
}
p = pipe()
tau listen(p)
send(p, "hello")
send(p, "world")
send(p, 123)
send(p, "this is a test")
close(p)
REPL
Tau also comes with a multiline REPL:
Tau v2.0.0 on Linux
>>> repeat = fn(n, func) {
... for i = 0; i < n; ++i {
... func(i)
... }
... }
...
>>> repeat(5, fn(i) {
... println("Hello #{i}")
... })
...
Hello #0
Hello #1
Hello #2
Hello #3
Hello #4
>>>
Data types
Tau is a dynamically-typed programming language and it supports the following primitive types:
Integer
myVar = 10
Float
myVar = 2.5
String
myString = "My string here"
Tau also supports strings interpolation.
temp = 25
myString = "The temperature is { if temp > 20 { \"hot\" } else { \"cold\" } }"
println(myString)
>>> The temperature is hot
For raw strings use the backtick instead of double quotes.
s = `this is a raw string\n {}`
println(s)
>>> this is a raw string\n {}
Boolean
t = true
f = false
Function
pow = fn(base, exponent) {
if exponent > 0 {
return base * pow(base, exponent-1)
}
1 # You could optionally write 'return 1', but in this case the return is implicit.
}
Builtin Functions
Tau has an assortment of useful builtin functions that operate on many data types:
len(x)-- Returns the length of the given objectxwhich could be a String, List, Map or Bytes.println(s)-- Prints the Stringsto the terminal (standard out) along with a new-line.print(s)-- Same asprintln()but without a new-line.input(prompt)-- Asks for input from the user by reading from the terminal (standard in) with an optional prompt.string(x)-- Converts the objectxto a String.error(s)-- Constructs a new error with the contents of the Strings.type(x)-- Returns the type of the objectx.int(x)-- Converts the objectxto an Integer.float(x)-- Converts the objectxto a Float.exit([code | message, code])-- Terminates the program with the optional exit code and/or message.append(xs, x)-- Appends the objectxto the Listxsand returns the new List.new-- Constructs a new empty object.failed(f)-- Calls the Functionfand returns true if an error occurred.plugin(path)-- Loads the Plugin at the given path.pipe-- Creates a new pipe for sending/receiving messages to/from coroutines.send(p, x)-- Sends the objectxto the pipep.recv(p)-- Reads from the pipepand returns the next object sent to it.close(p)-- Closes the pipep.hex(x)-- Returns a hexadecimal representation ofx.oct(x)-- Returns an octal representation ofx.bin(x)-- Returns a binary representation ofx.slice(x, start, end)-- Returns a slice ofxfromstarttoendwhich could be a String, List or Bytes.keys(x)-- Returns a List of keys of the Mapx.delete(xs, x)-- Deletes the keyxfrom the Mapxs.bytes(x)-- Converts the Stringxto Bytes.
List
empty = []
stuff = ["Hello World", 1, 2, 3, true]
You can append to a list with the append() builtin:
xs =[]
xs = append(xs, 1)
Lists can be indexed using the indexing operator [n]:
xs = [1, 2, 3]
xs[1]
Map
empty = {}
stuff = {"Hello": "World", 123: true}
Keys can be added using the set operator [key] = value:
kv = {}
k["foo"] = "bar"
Keys can be accessed using the get operator [key]:
kv = ["foo": "bar"}
kv["foo"]
Loop
for i = 0; i < 10; ++i {
println("hello world", i)
}
lst = [0, 1, 2, 3, 4]
println(lst)
for len(lst) > 0 {
println(lst = slice(lst, 1, len(lst)))
}
Objects
When you invoke the new() builtin function, it creates a fresh, empty object. You can then add properties to this object using the dot notation.
The constructor is essentially a standard function that fills up this empty object with properties and values before it is returned.
Dog = fn(name, age) {
dog = new()
dog.name = name
dog.age = age
dog.humanage = fn() {
dog.age * 7
}
return dog
}
snuffles = Dog("Snuffles", 8)
println(snuffles.humanage())
>>> 56
Modules
Import
When importing a module only the fields whose name start with an upper-case character will be exported.
Same thing applies for exported objects, in the example Snuffles is exported but the field id won't be visible ouside the module.
# import_test.tau
data = 123
printData = fn() {
println(data)
}
printText = fn() {
println("example text")
}
TestPrint = fn() {
printData()
printText()
}
dog = fn(name, age) {
d = new()
d.Name = name
d.Age = age
d.id = 123
d.ID = fn() {
d.id
}
return d
}
Snuffles = dog("Mr Snuffles", 5)
it = import("import_test")
it.TestPrint()
println(it.Snuffles.Name)
println(it.Snuffles.Age)
println(it.Snuffles.ID())
>>> 123
>>> example text
>>> Mr Snuffles
>>> 5
>>> 456
Plugin
Tau plugin system makes it possible to import and use C shared libraries in Tau seamlessly. To run your C code in Tau just compile it with:
gcc -shared -o mylib.so -fPIC mylib.c
then you can import it in Tau with the plugin builtin function.
myplugin = plugin("path/to/myplugin.so")
Example
C code:
#include <stdio.h>
void hello() {
puts("Hello World!");
}
int add(int a, int b) {
return a + b;
}
int sub(int a, int b) {
return a - b;
}
Tau code:
myplugin = plugin("mylib.so")
myplugin.hello()
println("The sum is", int(myplugin.add(3, 2)))
println("The difference is", int(myplugin.sub(3, 2)))
Output:
>>> Hello World!
>>> The sum is 5
>>> The difference is 1
Related Skills
xurl
341.8kA CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
diffs
341.8kUse the diffs tool to produce real, shareable diffs (viewer URL, file artifact, or both) instead of manual edit summaries.
kubeshark
11.8kCluster-wide network observability for Kubernetes. Captures L4 packets, L7 API calls, and decrypted TLS traffic using eBPF, with full Kubernetes context. Available to AI agents via MCP and human operators via dashboard.
clearshot
Structured screenshot analysis for UI implementation and critique. Analyzes every UI screenshot with a 5×5 spatial grid, full element inventory, and design system extraction — facts and taste together, every time. Escalates to full implementation blueprint when building. Trigger on any digital interface image file (png, jpg, gif, webp — websites, apps, dashboards, mockups, wireframes) or commands like 'analyse this screenshot,' 'rebuild this,' 'match this design,' 'clone this.' Skip for non-UI images (photos, memes, charts) unless the user explicitly wants to build a UI from them. Does NOT trigger on HTML source code, CSS, SVGs, or any code pasted as text.