-
-
Notifications
You must be signed in to change notification settings - Fork 653
Odin vs Jai
Time of writing: June 2022 (previously November 2021, February 2020)
Jonathan Blow's language talk was a minor inspiration, and thus his language Jai, of which Ginger Bill is quite open about. One of the main reasons people compare the two languages is purely regarding the similarity of the declaration syntax. From a semantic standpoint, the programming languages are quite different (Jai being very C++ like, and Odin being more Pascal/Go like). It is regularly asked about it which is why the minor table below was produced for people to understand the differences at a glance.
The declaration syntax is similar to Jai's but Blow didn't invent it, and in fact took it from Sean Barrett. And with a little research, you can find that it was Rob Pike who first invented that syntax back in the early '90s for Newsqueak and Limbo.
Some of the similarities that Odin and Jai hold are not unique to either and can be found in earlier languages. using
is a good example of this in that Ginger Bill was originally going to have with
from Pascal, but seeing how Jon applied that idea to "live variables" was pretty clever. And the uninitialized value ---
syntax is copied from Jai but it turned out to be a life saver because it was reused as the declaration syntax for (foreign) procedures without a body. The declaration syntax of Odin was changed for a week to a more conventional proc main()
syntax because it was thought the problem was unsolvable until it was realized this token could be used for that purpose. Hypothetically if Odin was to change its declaration syntax to a more qualifier-focused, it could be made to look more like Go or Rust in its declaration syntax without changing the AST layout whatsoever, and many of the comparisons to Jai would completely disappear.
Other than that, Odin and Jai are very different languages with very different philosophies behind them.
- Named-Focused Declaration Syntax
using
statementdefer
statement- Parametric Polymorphic name syntax with
$
- Implicit
context
System -
any
(Odin) type /Any
(Jai) type -
when
(Odin) statement /#if
(Jai) statement -
typeid
type (Odin) /Type
type (Jai) - Default procedure parameter values
- Named procedure results
- Default initialization on variable declarations
- Explicit uninitialization on variable declarations with
x: T = ---
Odin | Jai |
---|---|
Publicly Available | Private Beta Only (Currently) |
— | Arbitrary Compile Time Execution |
— | Compile Time AST modification (Outdated video: https://www.youtube.com/watch?v=59lKAlb6cRg) |
Strong Typed with virtually no implicit conversions | Many implicit conversions similar to C++ |
Pascal-family Type System | C-family Type System |
Modula/Go style directory-based package system | File-based library system |
Discriminated union type |
— |
bit_set |
— |
cstring |
*u8 (not semantically equivalent because it is not denoting a string type nor is it stating the value is NUL terminated) |
distinct type declarations |
— |
Built-in map type
|
(User-level type) |
Slicing notation like Python/Go [lo:hi]
|
Use of pointer arithmetic and wrapper procedures |
where clauses for procedure and record types |
#modify metaprogramming |
switch statements which allow for multiple cases, ranges, and any /union types |
if cond=={ case x: |
Explicit parameter declaration with for val, idx in array{}
|
Implicit parameter declaration with for array { val, idx := it, it_index; } ,as well as explicit for val, index : array {}
|
Extensive constant system which "just works" reducing the need for implicit conversions | Basic constant system which can be extended with the compile time execution features |
rune type for Unicode Codepoints |
s32 (signed 32-bit integer) (No default character type) |
Unicode identifiers | ASCII identifiers (currently) |
Array programming | Available explicitly through operator overloading |
matrix type |
Available explicitly through operator overloading |
— | Operator overloading |
Explicit procedure overloading | Implicit procedure overloading (Implicit Poylmorphism) |
Zero is initialized | Default struct fields |
Built-in complex and quaternion types | (User-level type) |
rawptr |
*void |
ptr: ^int; i := ptr^; x := &i; |
ptr: *int; i := <<ptr; x:= *i; |
p: [^]int; q := p[i:] (multi-pointers) |
p: *int; q := p + 1; (pointer arithmetic) |
proc(T) -> U |
(T) -> U (to see proof of the ambiguity: https://gist.github.com/gingerBill/27aec0cd434f2be58d024dccef6e8d13) |
proc(a, b: int, c: string) |
(a: int, b: int, c: string) |
#soa data types |
(User-level type through metaprogramming and operator overloading) (Video: https://www.youtube.com/watch?v=zgoqZtu15kI) |
Enumerated arrays | — |
Iterators through procedures | Iterators through macros |
Ranged Fields for array compounds literals | — |
Implicit Selector Expressions .A
|
Implicit Selector Expressions .A (originally did not) |
#partial switch |
#complete if cond == { |
— | Hygenic Macros |
— | #run_and_insert |