Comparison with Other Languages

This is a comparison between Jai and other programming languages such as C++, Java, Rust, Go, Haskell, etc. This compares Jai and other languages in terms of language design, goals, and features.


C++

Similarities

Both Jai and C++ are statically typed, compiled languages, no garbage collection, and designed for performance oriented programs such as 3D games.

Both support generic programming, Jai does so with parameterized structs and C++ has templates.

Both support structs, unions, and enums in the same exact way.

Both support inline assembly.

Both support operator overloading.

Pointers

Just like C, Jai has pointers with the same exact functionality as C, just using different operators for getting the address of and de-referencing a pointer. You can do pointer arithmetic on pointers as well as compare pointers against each other. Unlike C however, arrays do not cast to pointers, but rather arrays in Jai are objects with a data pointer and a count that counts the number of elements in an array.

Differences

Arrays

Arrays in C are equivalent to pointers, and arrays in C do not come with a count. In order to add a count to a C array, you either need to create a struct and pass the count to an array struct or pass an extra count parameter to a function. In Jai, however, arrays are objects with a pointer to the data as well as a count of how many objects are in an array.

No Makefiles

C/C++ compilers do not have a way to specify how to build a program, and are reliant on outside systems foreign to the language to build the language, such as Makefiles, Ninja, and CMake. All these build systems are clunky, need to use a different system for different operating systems, and building a large program can be incredibly messy. In Jai, all you would ever need to compile your code is the compiler itself, no external dependencies.

Malloc, New, Placement New

In C++, new is a keyword indicating a call to a heap allocation routine. In Jai, New is not a keyword built into the language, but rather regular function that does heap allocation. In Jai, you can change the way memory is allocated by passing a different context to the function. In C++, you can do a placement new, i.e. overload the operator new in order to change the behavior of the new keyword. In Jai, there is no such thing as a operator new.

References

C++ has a concept for references (e.g. void function(int &a);). In Jai, there is no such concept as references. Operator overloading is implemented in this language without need for references.

RAII (Resource Acquisition is Initialization)

Jai does not have any RAII, while C++ has RAII (Resource Acquisition is Initialization). C++ is a “big idea language”, in that C++ dogmatically encourages RAII as the primary mechanism for handling everything from opening/closing files to mangaging memory. In C++, RAII is seen as fundamental dogma. Meanwhile, Jai has specialized mechanisms that handle specific cases well rather than have a “big idea” to solve everything.

Object-Oriented Programming

C++ code usually has object oriented programs with massive inheritance hierarchies, and virtual functions overloading member functions. Although Jai can do function pointers, virtual functions are not supported in the compiler at all. Jai supports struct inclusion with the using keyword, but you cannot automatically generate functions with a virtual keyword like in C++.

Jai is less dogmatic about the “correct way” to write a program, and tries to provide a series of broad tools to do whatever you want rather than enforce an object oriented hierarchy designed through UML diagrams.

Jai does NOT have member functions. There is no concept of functions “belonging” to a particular struct or datatype. All member fields of a struct are public by default and there is no built in feature to make a member field private.

const keyword

Jai has no concept of const. Littering your entire codebase with const everywhere just makes the code messier and more noisy. The concept of const can get confusing, and it does not help the compiler with anything.

Volatile Keyword

This keyword is NOT inside the Jai Programming Language.

Macros

C/C++ macros are merely textual substitutions. C/C++ macros are powerful, but heavily error-prone, play terribly with the debugger, and lack any coherent structure. Jai macros are hygenic macros, meaning macros are better structured and checked by the compiler.

For Loop Custom Iteration

In C, you can make a for loop through macros. However, C macros cause tons of problems due to its lack of proper structure, and using a macro in C are bad practice. C++ requires you to create 7+ different functions and/or data structures to create a custom for loop iteration. This can be tedious and painstaking for such a simple idea. In Jai, custom for loops are simple and clean, just create a for_expansion macro.

Metaprogramming

C++ uses a mixture of object-oriented programming, template metaprogramming, macros, and C++ concepts to do metaprogramming. All these features are sloppily and incoherently put together, creating a giant mess of contradictory design problems for C++. The combination of all these features drastically slow down C++. In Jai however, arbitrary compile-time metaprogramming execution has been built into the language from the start. Metaprograms can modify the program in arbitrarily complex ways easily.

Bitfields

This feature is NOT in the Jai Programming Language.

Exceptions

There are no exceptions in Jai. Although C++ allows exceptions, they are strongly discouraged. Jai does not have exceptions at all, and they are not a language feature.


Java

Similarities

Both Jai and Java are statically typed.

Both support generic programming, Jai does so with parameterized structs and Java has generics.

Jai and Java have notes and annotations, respectively. Java annotations, however, can be parameterized.

Differences

Interpreted

Java code is translated into Java byte code, which then is run by the Java virtual machine. Jai is a compiled language that translates code directly into a binary executable. Jai can run programs in bytecode during compilation, but only at compile-time. At runtime, a Jai executable is executing machine code directly.

Garbage Collection

Unlike Java, Jai does not have garbage collection. However, Jai takes a context-based allocation scheme in which the memory allocator is implicitly passed to all functions (unless otherwise specified with #c_call). The context can be overloaded with a custom allocator, and shifts the burden of memory management away from ambiguity towards being coordinated between the compiler and the user.

Operator Overloading

Java does not have any operator overloading outside of string concatenation. Jai supports operator overloading in general for all sorts of different operations.

Object-Oriented Programming

Java code usually has object oriented programs with massive inheritance hierarchies, and Java encourages overloading member functions. Although Jai has function pointers, Java-like member functions are not supported at all. For example, you cannot overload a toString function in order to print out a struct to the console.

Unlike Java, there is no base Object class in which all objects inherit from.

Jai is less dogmatic about the “correct way” to write a program, and tries to provide a series of broad tools to do whatever you want rather than enforce an object oriented hierarchy designed through UML diagrams.

Exceptions

Java regularly uses and requires exceptions to handle files, read from a network socket, etc for flow control. Jai does not have exceptions at all. Exceptions are not a Jai language feature.

Volatile Keyword

This keyword is NOT inside the Jai Programming Language.


Rust

Similarities

Jai and Rust are both statically typed, compiled languages with no garbage collection. Both are designed for performance critical applications, although Rust is not often used for designing games.

Both support generic programming, Jai does so with parameterized structs and Rust has generics.

Both support structs and enums in the same exact way.

Both support operator overloading.

Differences

Mutable Variables

Rust strongly encourages people to defined variables as constants: they can only be set once, and from there only read. In Rust, declaring a variable x: int is constant by default, and you need to declare the variable x: mut int to be able to modify the variable. Jai does not do this, it rather follows the C scheme of all variables being mutable by default.

Borrow Checker

Rust is a “big idea” language that uses static compile-time formal verification where the borrow checker attempts to prevent all memory-related bugs. While this can be useful in some fields of software, the borrow checker seriously conflicts with Jai arena allocation, context-based allocation and temporary storage schemes. Jai does not have a built in borrow checker, however, the metaprogramming features allow one to create arbitrary code inspection and analysis tools appropriate for whatever problem one will personally face.

Unsafe

Rust allows programmers to deliberately turn off some safety features to temporarily bend the rules in order to do what you want. To deliberately turn off some safety features, you need to mark up and liter the code with unsafe blocks. This method can be terrible when producing software such as video games, in which you may need to mark up large amounts of your program as unsafe and throw out a large portion of Rust safety features. Jai does not have this feature, since Jai encourages context-based allocation and temporary storage.

Pointers

Rust allows raw pointers, but only in unsafe blocks or only when using smart pointers or reference counted pointers. Jai follows the C pointer model which allows pointers all the time.

Package Manager

Cargo is the package manager for Rust. Jai does not have a package manager.


Go

Similarities

Both Jai and Go are statically typed, compiled languages. Both do full rebuilds with no incremental compilation.

Both languages have a defer keyword that defers execution of a piece of code until the end of a scope.

Differences

Garbage Collection

Unlike Go, Jai does not have garbage collection. However, Jai takes a context-based allocation scheme in which the memory allocator is implicitly passed to all functions (unless otherwise specified with #c_call). The context can be overloaded with a custom allocator, and shifts the burden of memory management away from ambiguity towards being coordinated between the compiler and the user.

Coroutines (Go Channels)

Jai does not and will not support coroutines. These concurrency structures deal with trivial concurrency problems, but do not help in more complex situations.

Panic

While Go supports exception handling through panic, Jai does not have exception handling at all.


Functional Languages (Haskell, Scheme, etc.)

Similarities

Metaprogramming

Both Jai and Lisp-like functional programming languages have powerful, robust metaprogramming features capable of arbitrary unlimited functionality. The only limitation of Jai metaprogramming is that all metaprogramming is limited strictly to compile-time execution. Meanwhile, Lisp-like functional programming languages can do arbitrary metaprogramming at both the runtime and compile-time level, but as a result, suffer serious performance issues.

Function Currying

Functional programming languages have the powerful ability to curry arbitrary functions at compile and runtime, and create new functions by currying values together. Jai has function currying through #bake_arguments, except function curry only happens at compile time. There is no runtime function currying in Jai.

Differences

Linked Lists

In Functional Programming Languages, linked lists are the fundamental data structure. In Jai, arrays and looping over arrays is the most part of Jai. Linked lists are defined as a struct.

Algebraic Data Types

Functional Programming Languages have algebraic data types and tagged unions built into the language. This feature is not supported by the compiler. One can simulate such functionality by using unions, structs, and #place directives.

Pattern Matching

Functional Programming Languages use pattern matching to pattern match statements to the correct control flow. This feature is not be in Jai. Jai is based on traditional imperative structured programming languages with while loops, if statements, and for loops. The closest thing to pattern matching would be if case statements.

Lazy Evaluation

This will not be in Jai. Lazy evaluation makes no sense in an imperative programming language where adding two number together generates literal machine code that adds two numbers together. Jai is about generating high-level code that has a close as possible mapping to machine code.


Scripting Languages (PHP, JavaScript, Ruby, Python, etc.)

Feature Jai Scripting Languages
Garbage Collection Jai does not not have garbage collection. However, Jai takes a context-based allocation scheme in which the memory allocator is implicitly passed to all functions (unless otherwise specified with #c_call). The context can be overloaded with a custom allocator, and shifts the burden of memory management away from ambiguity towards being coordinated between the compiler and the user. Also see #memory-management PHP, JavaScript, Ruby, Python all use Garbage Collection.
Generator Functions Jai does not have generator functions. These are high-level language features that do not compile down to fast code. The closest Jai language feature to generator functions is writing a custom for_expansion macro for a for loop. Python, Ruby, Perl, Javascript
Dynamic Typing Jai is a statically compiled language, meaning all variables must be labeled and defined at compile time through a type system. Unlike scripting languages which allow you to randomly create new structs at runtime, Jai requires you to define every struct at compile-time. Python, Ruby, Perl, Javascript
1 Like