Language Features

Ziv is designed to provide a robust set of features that make it easy to write code that is both efficient and easy to read. This document provides an overview of the language features that Ziv provides.

Table of Contents

Simple and Readable Syntax

Ziv emphasizes readability and simplicity, making it easy to write and understand code. The syntax is clean and minimalistic, reducing the likelihood of errors and enhancing the readability of the code.

Example:

fn greet(name: string) -> void:
    print("Hello, " + name + "!")

    if name == "Alice":
        print("You are awesome!")
    else:
        print("Nice to meet you!")

greet("Alice")

Strong Static Typing with Type Inference

Ziv has a robust static type system that catches errors at compile time. It also supports type inference, allowing you to omit explicit type declarations when unnecessary.

Example:

# Explicit typing
let age: int = 25
name: string = "Alice"

# Inferred typing
let age = 25  # Inferred as int

# Compile-time error example
age = "Alice"

Pattern Matching

Ziv provides powerful pattern matching capabilities that allow you to match values against patterns and extract data from them.

Example:

fn is_even(n: int) -> bool:
    when n:
        0 => true
        1 => false
        _ => is_even(n - 2)

Modularity

Ziv supports modularity through the use of modules, allowing you to organize your code into reusable components.

Example:

# math.ziv
module math

fn add(a: int, b: int) -> int:
    return a + b


fn subtract(a: int, b: int) -> int:
    return a - b

end module
# main.ziv
import math

fn main() -> void:
    result: int = math.add(10, 5)
    print(result)

Concurrency and Parallelism

Ziv provides built-in support for concurrency and parallelism, allowing you to write code that can run concurrently and in parallel.

  • Concurrency: Ziv supports lightweight threads that can run concurrently when spawned.

    fn task(id: int) -> void:
        print("Task " + id + " started")
    
    fn main() -> void:
        spawn(task, 1) # Start task 1
        spawn(task, 2) # Start task 2
    
  • Parallelism: Ziv supports parallelism through the use of the parallel keyword, allowing you to execute code in parallel.

    fn task(id: int) -> void:
        print("Task " + id + " started")
    
    fn main() -> void:
        # Start task 1 and task 2 in parallel
        parallel:
            task(1)
            task(2)
    

Functional Programming

Ziv supports functional programming paradigms, including first-class functions, higher-order functions, lambdas, recursion, closures, and immutability.

Example:

  • First-Class Function

    # First-class function
    fn greet(name: string) -> void:
        print("Hello, " + name + "!")
    
    fn main() -> void:
        f: (string) -> void = greet
        f("Alice") # Output: Hello, Alice!
    
  • Higher-Order Function

    # Higher-order function
    fn apply(f: (int) -> int, x: int) -> int:
        return f(x)
    
    fn square(x: int) -> int:
        return x * x
    
    fn main() -> void:
        result: int = apply(square, 5)
        print(result) # Output: 25
    
  • Lambda Expression

    # Lambda expression
    fn main() -> void:
        result: int = apply(|x| x * x, 5)
        print(result) # Output: 25
    
  • Immutability

    # Immutable data structure
    !my_list: list[int] = [1, 2, 3]
    
    fn main() -> void:
        print(my_list) # Output: [1, 2, 3]
        my_list[0] = 4 # This will cause a compile-time error
    
  • Monads

    # Monad using >> operator
    fn add_one(x: int) -> int:
        return x + 1
    
    fn multiply_by_two(x: int) -> int :
        return x * 2
    
    fn main() -> void:
        result: int = 1 >> add_one >> multiply_by_two
        print(result) # Output: 4
    
  • Arrow Functions

    # Arrow function
    fn main() -> void:
        f: (int) -> int = |x| x * x
        result: int = f(5)
        print(result) # Output: 25
    
  • Currying

    # Currying
    fn add(a: int, b: int) -> int:
        return a + b
    
    fn main() -> void:
        add_five: (int) -> int = add(5)
        result: int = add_five(10)
        print(result) # Output: 15
    
  • Partial Application

    # Partial application
    fn add(a: int, b: int) -> int:
        return a + b
    
    fn main() -> void:
        add_five: (int) -> int = add(5, _) # Partial application
        result: int = add_five(10)
        print(result) # Output: 15
    
  • Map, Filter, Reduce

    # Map, filter, reduce
    numbers: list[int] = [1, 2, 3, 4, 5]
    
    # Map
    doubled: list[int] = map(numbers, |x| x * 2)
    print(doubled) # Output: [2, 4, 6, 8, 10]
    
    # Filter
    evens: list[int] = filter(numbers, |x| x % 2 == 0)
    print(evens) # Output: [2, 4]
    
    # Reduce
    sum: int = reduce(numbers, 0, |acc, x| acc + x)
    print(sum) # Output: 15
    
  • Lazy Evaluation

    # Lazy evaluation
    fn main() -> void:
        # infinite list of numbers
        numbers: list[int] = lazy:
            for i in 0.. :
                yield i
    
        # take first 5 numbers
        for n in take(numbers, 5):
            print(n)
    

Error Handling

Ziv provides robust error handling mechanisms that allow you to handle errors gracefully and recover from them.

Example:

fn divide(a: int, b: int) -> int:
    if b == 0:
        error("Division by zero")
    return a / b

fn main() -> void:
    result: int = divide(10, 0)

Generics

Ziv supports generics, allowing you to write code that is generic over types.

Example:

fn swap<T>(a: T, b: T) -> (T, T):
    return (b, a)

fn main() -> void:
    result: (int, int) = swap(10, 20)
    print(result)

Object-Oriented Programming

Ziv supports object-oriented programming features, such as classes, inheritance, and encapsulation.

Example:

  • Class Definition

    # Define a class with private, public, and protected members
    class BankAccount:
        public owner: string
        protected balance: float
        private account_number: string
    
        # Constructor
        fn init(account_number: string, owner: string):
            self.account_number = account_number
            self.owner = owner
            self.balance = 0.0
    
        # Destructor
        fn deinit() -> void:
            print("Account " + self.account_number + " closed")
    
        public fn deposit(amount: float):
            self.balance += amount
    
        # Methods are public by default
        fn withdraw(amount: float):
            self.balance -= amount
    
        protected fn get_balance() -> float:
            return self.balance
    
        private fn get_account_number() -> string:
            return self.account_number
    
  • Inheritance and Protected Access

    # Inheritance
    class SavingsAccount(BankAccount):
        public interest_rate: float
    
        fn init(account_number: string, owner: string, interest_rate: float):
            parent.init(account_number, owner)
            self.interest_rate = interest_rate
    
        public fn calculate_interest() -> float:
            return self.get_balance() * self.interest_rate
    
  • Instance Creation and Method Invocation

    # Instance creation and method invocation
    fn main() -> void:
        account: SavingsAccount = SavingsAccount("12345", "Alice", 0.05)
        account.deposit(1000.0)
        interest: float = account.calculate_interest()
        print(interest) # Output: 50.0
    
  • Polymorphism

    # Base Class
    class Animal:
        public fn speak() -> string:
            return "Animal speaks"
    
    # Derived Class
    class Dog(Animal):
        public fn speak() -> string:
            return "Dog barks"
    
    # Another Derived Class
    class Cat(Animal):
        public fn speak() -> string:
            return "Cat meows"
    
    fn main() -> void:
        dog: Animal = Dog()
        cat: Animal = Cat()
    
        print(dog.speak()) # Output: Dog barks
        print(cat.speak()) # Output: Cat meows
    
  • Abstract Classes

    # Abstract Class
    abstract class Shape:
        public abstract fn area() -> float
    
    # Concrete Class
    class Circle(Shape):
        public radius: float
    
        fn init(radius: float):
            self.radius = radius
    
        # Implement abstract method
        public fn area() -> float:
            return 3.14 * self.radius * self.radius
    
  • Interfaces

    # Interface
    interface Printable:
        public fn print() -> void
    
    # Class implementing the interface
    class Document(Printable):
        public fn print():
            print("Document printed")
    
  • Static Members

    # Static Members
    class Counter:
        public static count: int = 0
    
        public static fn increment():
            Counter.count += 1
    
        public static fn get_count() -> int:
            return Counter.count
    
    fn main():
        Counter.increment()
        Counter.increment()
        count: int = Counter.get_count()
        print(count) # Output: 2
    
  • Operator Overloading

    # Operator Overloading
    class Vector:
        public x: float
        public y: float
    
        fn init(x: float, y: float):
            self.x = x
            self.y = y
    
        public fn +(other: Vector) -> Vector:
            return Vector(self.x + other.x, self.y + other.y)
    

Metaprogramming

Ziv provides metaprogramming capabilities that allow you to generate code at compile time.

Example:

macro repeat(n: int, body: block):
    for i in 0..n :
        body

fn main():
    repeat(5):
        print("Hello")

Interoperability

Ziv provides seamless interoperability with other languages, allowing you to call functions written in other languages from Ziv code.

Example:

# Import a C function
extern fn c_function() -> int

fn main() -> void:
    result: int = c_function()
    print(result)

Testing Support

Ziv has built-in support for testing, enabling you to write and execute test cases directly in your code.

Example:

# This function adds two numbers
fn add(a: int, b: int) -> int:
    return a + b

# Test cases
test "Addition" :
    assert(add(1, 2) == 3)
    assert(add(0, 0) == 0)

Asynchronous Programming

Ziv provides built-in support for asynchronous programming, allowing you to write asynchronous code easily and efficiently.

Example:

async fn fetch_data(url: string) -> string;
    response: string = await http.get(url)
    return response

Advanced Features

Ziv provides a range of advanced features, such as decorators, and more, that allow you to write powerful and expressive code.

  • Decorators:

    Ziv supports decorators, which are functions that modify the behavior of other functions or methods.

    # Decorators
    @log
    fn add(a: int, b: int) -> int:
        return a + b
    
    fn main():
        result: int = add(1, 2)
        print(result) # Output: 3
    
  • Class Decorators:

    Ziv also supports class decorators, which are functions that modify the behavior of classes.

    # Class Decorators
    fn singleton(cls: class) -> class:
        instance: cls = null
    
        fn get_instance() -> cls:
            if instance == null:
                instance = new cls()
            return instance
        return cls
    
    @singleton
    class Database:
        fn init():
            print("Database initialized")
    
    fn main() -> void:
        db1: Database = Database.get_instance()
        db2: Database = Database.get_instance()
    
        print(db1 == db2) # Output: true
    
  • Module Versioning:

    Ziv supports module versioning, allowing you to specify the version of a module that your code depends on.

    # math.ziv
    module math version "1.0.0"
    
    fn add(a: int, b: int) -> int:
        return a + b
    
    end module
    
    # main.ziv
    import math version "1.0.0"
    
    fn main():
        result: int = math.add(10, 5)
        print(result)
    
  • Type Aliases:

    Ziv supports type aliases, allowing you to define custom names for existing types.

    # Type Aliases
    type Point = (int, int)
    
    fn distance(p1: Point, p2: Point) -> float:
        x1, y1 = p1
        x2, y2 = p2
        return sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
    
  • Import Aliases:

    Ziv supports import aliases, allowing you to import modules with custom names.

    # Import Aliases
    import math as m
    
    fn main():
        result: int = m.add(10, 5)
        print(result)``