Hello World
fn main() {
    println!("Hello, world!");
}

Run the program:

cargo run

This is the normal Rust entry point. println! is a macro that writes formatted output to the terminal.

Variables

Variables are immutable by default. Use mut when the value should change.

let language = "Rust";
let mut count = 1;
count += 1;

Rust values are immutable unless you mark them with mut, which makes state changes explicit.

Ownership

Values have a single owner. Borrow with references when a function should read data without taking ownership.

fn main() {
    let name = String::from("Dan");
    greet(&name);
    println!("{}", name);
}

fn greet(name: &str) {
    println!("Hello, {name}");
}

This shows borrowing with &name, so the function can read the value without taking it away from the caller.

Hello World
const message: string = "Hello, world!";
console.log(message);

Run with a TypeScript runtime or compile first:

npx tsx main.ts

This defines a typed string and logs it. It is the basic TypeScript shape for a tiny script.

Types
type User = {
  id: number;
  name: string;
  active: boolean;
};

const user: User = {
  id: 1,
  name: "Dan",
  active: true,
};

This type describes the expected object shape, then the object literal follows that contract.

Functions
function greet(name: string): string {
  return `Hello, ${name}!`;
}

console.log(greet("world"));

This function makes both the input and output types explicit, which is one of the main benefits of TypeScript.

Function Clauses and Guards

Use multiple function heads to make branching explicit. Guards keep each clause narrow and readable.

defmodule AccessLevel do
  def label(%{role: :admin}), do: "full access"
  def label(%{role: :editor, active: true}), do: "edit access"
  def label(%{role: role}) when role in [:viewer, :guest], do: "read only"
  def label(_), do: "no access"
end

This keeps branching close to the function definition, which makes Elixir code easier to scan than one large conditional.

Pipelines

The pipe operator passes the previous result as the first argument to the next function.

users
|> Enum.filter(& &1.active)
|> Enum.map(& &1.email)
|> Enum.sort()

Prefer pipes when each step transforms the same value. Avoid hiding complex branching inside a long pipeline.

This reads top to bottom like a data flow. Each step takes the previous result and transforms it a little more.

Structs

Structs are maps with a fixed shape and a module name. They are useful for domain data.

defmodule User do
  defstruct [:id, :email, active: true]
end

user = %User{id: 1, email: "[email protected]"}

case user do
  %User{active: true, email: email} -> {:ok, email}
  %User{} -> {:error, :inactive}
end

This shows a struct as a predictable map shape for domain data, plus pattern matching on that struct in a case.

With

with flattens a sequence of pattern matches that may fail.

with {:ok, user} <- fetch_user(id),
     {:ok, plan} <- fetch_plan(user),
     true <- plan.active do
  {:ok, %{user: user, plan: plan}}
else
  false -> {:error, :inactive_plan}
  {:error, reason} -> {:error, reason}
end

Use it when each successful step feeds the next one.

This is useful when several steps can fail and each successful result feeds the next one.

Processes and Messages

Elixir processes are lightweight and communicate by sending messages.

parent = self()

spawn(fn ->
  send(parent, {:result, 42})
end)

receive do
  {:result, value} -> value
after
  1_000 -> {:error, :timeout}
end

This demonstrates Elixir’s concurrency model: lightweight processes send messages instead of sharing mutable state.

GenServer Shape

A GenServer keeps state behind a process and exposes a client API.

defmodule Counter do
  use GenServer

  def start_link(initial), do: GenServer.start_link(__MODULE__, initial)
  def increment(pid), do: GenServer.call(pid, :increment)

  @impl true
  def init(initial), do: {:ok, initial}

  @impl true
  def handle_call(:increment, _from, count) do
    next = count + 1
    {:reply, next, next}
  end
end

This is the usual GenServer layout: public API at the top, callbacks below, and state kept inside the process.

Strings
str := "Hello"

Multiline string

str := `Multiline
string`

This shows regular strings and raw multiline strings. Raw strings are handy when you want to keep formatting as written.

Numbers

Typical types

num := 3          // int
num := 3.         // float64
num := 3 + 4i     // complex128
num := byte('a')  // byte (alias for uint8)

Other Types

var u uint = 7        // uint (unsigned)
var p float32 = 22.7  // 32-bit float

Go keeps numeric types explicit. The examples show the common defaults plus a few typed variants when precision or size matters.

Arrays
// var numbers [5]int
numbers := [...]int{0, 0, 0, 0, 0}

This creates a fixed-size array. In day-to-day Go, slices are more common, but arrays are the underlying fixed-length value.

Pointers
func main () {
  b := *getPointer()
  fmt.Println("Value is", b)
func getPointer () (myPointer *int) {
  a := 234
  return &a
a := new(int)
*a = 234

Pointers point to a memory location of a variable. Go is fully garbage-collected.

Pointers let you work with the same value across functions without copying it. Go keeps them simpler than C by handling memory cleanup for you.

Type Conversion
i := 2
f := float64(i)
u := uint(i)

Go does not do many implicit numeric conversions, so converting types directly like this is normal.

Slice
slice := []int{2, 3, 4}
slice := []byte("Hello")

Slices are the main sequence type in Go. They are lightweight views over array-backed data and are used much more than arrays.

Condition
if day == "sunday" || day == "saturday" {
  rest()
} else if day == "monday" && isTired() {
  groan()
} else {
  work()
}
if _, err := doThing(); err != nil {
  fmt.Println("Uh oh")

This shows the normal if and else if flow in Go, plus the common if err != nil pattern for error handling.

Switch
switch day {
  case "sunday":
    // cases don't "fall through" by default!
    fallthrough

  case "saturday":
    rest()

  default:
    work()
}

Go switch blocks are clean by default because cases do not fall through unless you ask for it explicitly.

Loop
for count := 0; count <= 10; count++ {
  fmt.Println("My counter is at", count)
}
entry := []string{"Jack","John","Jones"}
for i, val := range entry {
  fmt.Printf("At position %d, the character %s is present\n", i, val)
n := 0
x := 42
for n != x {
  n := guess()
}

Go uses for for every looping style: counted loops, range loops, and condition-based loops.

Condition
if day == "sunday" || day == "saturday" {
  rest()
} else if day == "monday" && isTired() {
  groan()
} else {
  work()
}
if _, err := doThing(); err != nil {
  fmt.Println("Uh oh")

Despite the title here, this example is another Go conditional. It shows the same straight-line branching style used in most Go code.

Bash Add
add() {
    echo $(( $1 + $2 ))
}

This just adds the two input numbers with Bash arithmetic and prints the sum.

C++ Add
int add(int param1, int param2)
{
    return param1 + param2;
}

This just adds the two input numbers with the language’s normal arithmetic and returns the sum.

C# Add
static int Add(int param1, int param2)
{
    return param1 + param2;
}

This just adds the two input numbers with the language’s normal arithmetic and returns the sum.

Elixir Add
defmodule Add do
  def add(param1, param2), do: param1 + param2
end

This just adds the two input numbers with the language’s normal arithmetic and returns the sum.