Erg: a Python-Compatible Statically Typed Language
Tags: python, rust, news
Published: 2022-08-14 09:57:00

I have been developing a programming language for a few years and this week I published it on [GitHub](https://github.com/erg-lang/erg).

The name of the language is Erg, think of it as a Python version of TypeScript (but more elegant than TS, I think).

Python is a widely used language, but its dynamic typing has made it difficult for large-scale development. My ambition is to solve this problem with Erg.

## Features:

> Note: some features are not yet implemented.

### 1. Robustness

Erg has a smart & powerful type system. For example, Erg can do null checking (Option type), division by zero and out-of-range addresses in arrays at compile time.

```python
rand = pyimport "random"

l = [1, 2, 3]
assert l in [Nat; 3] # type checking
assert l in [1..3; 3] # more detailed
l2 = l.push(rand.choice! 0..<10)
assert l2 in [0..9; 4]
assert l2 + [3, 5, 7] in [0..9; 7]
# This causes an IndexError, Erg can detect it at compile time
l2[10] # IndexError: `l2` has 7 elements but was accessed the 11th element

2.times! do!:
    print! "hello, ", end: ""
# => hello, hello, 
-2.times! do!:
    print! "hello, ", end: ""
# TypeError: `.times!` is a method of `Nat` (0 or more Int), not `Int`
```

### 2. Simplicity

Erg consists of a very simple syntax, which can significantly reduce the amount of code compared to other languages. However, its functionality is not inferior to them.

Since the type inference system is powerful, you can code like a dynamically typed language.

```python
fib 0 = 0
fib 1 = 1
fib n = fib(n - 1) + fib(n - 2)
assert fib(10) == 55
```

In Erg, there are very few things that are treated as special; there are no reserved words.
Even `for` and `while` expressions are just one of the subroutines, so this is possible.

```python
loop! block = while! True, block

# equals to `while! True, do! print! "hello"`
loop! do!:
    print! "hello"
```

### 3. Functional & Object-oriented

Erg is a pure object-oriented language. Everything is an object; types, functions, and operators are all objects. On the other hand, Erg is also a functional language.
Erg requires some kinds of markers to be placed on code that causes side effects or changes internal state, which can localize the complexity of code. This will greatly improve the maintainability of your code.

```python
# Functional style (immutable), same as `sorted()` in Python
immut_arr = [1, 3, 2]
assert immut_arr.sort() == [1, 2, 3]
# Object-oriented style (mutable)
mut_arr = ![1, 3, 2]
mut_arr.sort!()
assert mut_arr == [1, 2, 3]
i = !1
i.update! old -> old + 1
assert i == 2
```

### 4. Interoperability

Erg can use Python APIs at zero cost. Besides, they are well typed!

```python
# using a built-in Python module
rand = pyimport "random"

print! rand.randint!(0, 10) # 7
print! rand.randint!(0, 1.0) # TypeError: the type of rand.randint!::b is mismatched:
# expected:  Int
# but found: {%v16: Float | %v16 == 1.0}
```

And more features are planned to be implemented.

## FAQ

### Q: If Erg is type-inferrable, how can Python functions be called?

A: Erg has a feature called `assert casting`, which delays compile-time unverifiable type decisions until runtime (this is the same flavor of `declare` in TypeScript, but more powerful).

```python
o = eval("1 + 1")
print! Typeof(o) # Object
assert o in Int # From this point on, o can be regarded as Int.
print! Typeof(o) # Int
print! o + 1 # 3
```

Functions whose arguments change the return type are typed using the `or type`(Union).

```python
parse_int(x: Str): Int or IntParseError
```

Erg also has a structural type system, so unwilling functions that access the attributes of their arguments out of the box without assertions can also be typed.

```python
get_name(named: Structural {.name = Str}): Str =
    named.name
```

Using these features, most Python functions can be typed.
A few functions, such as `exec`, are still in principle untypable (I say that easy calls to them are a bad practice and should be prohibited), but a limited version of `eval` functions are available without compromising type safety.

Python built-in functions are specially typed by the compiler and can be called at zero cost. Functions from the built-in library will be supported in due course.

## Q: Is Erg a transpile language?

A: At this time, yes. My original plan was to develop even a Python processor (VM) and create a statically typed upward-compatible Python language (that's why the ownership grammar is there, and we planned to make it GC/GIL-less). The VM will be named "Dyne" and will be developed as a subproject.

## Q: You say it's Python-compatible, but the syntax doesn't seem to be compatible.

A: There is no syntax compatibility like JS/TS (although I have tried to make it reasonably similar for ease of transition). As mentioned in the previous question, I mean compatibility of processing systems.

## Q: Attach to procedure `!` mark makes the syntax ugly. Why did you choose this syntax?

A: If you feel that way, you are right and exactly what I intended.
The large number of `!` in the code is what is called a code smell. The code is likely to have many side effects and low maintainability.

## Q: Can I call APIs such as TensorFlow and NumPy from Erg?

A: I plan to make it possible to type and call them on the Erg side, like `DefinitelyTyped` in TS.

---

If you like this project, please star it on [GitHub](https://github.com/erg-lang/erg).