Learn 10X in Y Minutes

Tenecs is pronounced "ten-ex", like "10X"

This is a practical crash course in the style of Learn X in Y Minutes: short explanations and lots of runnable snippets.

Table of Contents

  1. Packages and imports
  2. Values and basic types
  3. Comments and type aliases
  4. Functions
  5. Structs and data modeling
  6. Lists and generics
  7. Control flow with if and when
  8. Syntactic sugar
  9. Tests

Packages and imports

// Every file starts with a package.
package main

// Imports
import tenecs.go.Main
import tenecs.go.Runtime

// Main wires your app to runtime.
app := Main((runtime: Runtime) => {
  runtime.console.log("Hello world!")
})

Values and basic types

package basics

// Use := to create values.
name := "Ada"
isActive := true
count := 3

// Type annotations are optional.
welcome: String = "Hello"

Comments and type aliases

package basics

// Single-line comment
/* Multi-line
comment */

typealias UserId = String

userId: UserId = "user-123"

Functions

package basics

import tenecs.string.join

// (arg: Type): ReturnType => { ... }
greet := (name: String): String => {
  join("Hello, ", name)
}

// You can also type a function explicitly.
formatter: (a: String, b: String) ~> String = (a: String, b: String): String => {
  join(a, b)
}

// Named arguments are supported.
example := (): String => {
  formatter(a = "Ada", b = " Lovelace")
}

Structs and data modeling

package domain

// Structs are typed product types.
struct User(
  id: String,
  email: String
)

admin := User("1", "admin@example.com")

Lists and generics

package collections

names := <String>["Ada", "Lin"]

// Generic function
identity := <T>(value: T): T => {
  value
}

firstName := identity<String>("Ada")

Control flow with if and when

package control

describe := (value: Boolean | String): String => {
  when value {
    is boolValue: Boolean => {
      if boolValue {
        "true"
      } else {
        "false"
      }
    }
    is textValue: String => {
      textValue
    }
  }
}

classify := (value: Boolean | String | Void): String => {
  when value {
    is text: String => {
      text
    }
    other _rest => {
      "not a string"
    }
  }
}

Syntactic sugar

Tenecs has shortcuts that compile down to regular function calls and when blocks.

Arrow invocation (->)

package sugar

f := (str: String): String => {
  str
}

g := (str: String, another: String): String => {
  str
}

usage := (): String => {
  // Sugar:
  "foo"->f()->g("bar")

  // Equivalent:
  g(f("foo"), "bar")
}

Type-based short-circuit declaration

package sugar

import tenecs.string.join

stringOrInt := (): String | Int => {
  3
}

usage := (): String | Int => {
  // Sugar: if Int, return early; otherwise continue as String.
  str :? Int = stringOrInt()
  join(str, "!")
}

// Equivalent:
usageExpanded := (): String | Int => {
  when stringOrInt() {
    is int: Int => {
      int
    }
    other str => {
      join(str, "!")
    }
  }
}

Tests

package test

import tenecs.test.UnitTest
import tenecs.test.UnitTestSuite

_ := UnitTest("hello unit test", (testkit) => {
  testkit.assert.equal("hello", "hello")
})

_ := UnitTestSuite("math suite", (registry) => {
  registry.test("one equals one", (testkit) => {
    testkit.assert.equal(1, 1)
  })
})