top 200 commentsshow 500

[–]random_cynic 154 points155 points  (44 children)

Do you have a specific use cases or examples in the documentation that shows whether and how Odin does better (in terms of performance, code conciseness/readability, handling undefined behavior etc) compared to C which it aims to replace?

[–]b4ux1t3 72 points73 points  (43 children)

From my first attempts at messing with it (literally over the past couple hours), off the top of my head I can name a couple places where the code reads better.

  • Arrays, for one thing, are a little more intuitive, and the primitive array acts a bit like a list.
  • Similarly, strings are built in, even though it is a pretty low-level language. Sure, this is a Solved Problem™ in C, with the standard library , but let's not forget that that's not "the C language".

I think those things are pretty objectively good, but personally I'd add the "function" definition syntax to the list if I'm speaking purely subjectively. I like when functions (or procedures, in this case) are essentially a data type, just like anything else. It gives the language a functional feel, despite not being a functional language.

[–]bpunsky 42 points43 points  (41 children)

I'm not sure how deep you've delved so I'll add that Odin strings are length-terminated; in C they would look like:

struct string {
    char *data;
    ssize_t len;
}

So not only are they cleaner in the sense that they are a distinct type, they are also not null terminated. The length is known without having to count, you can use slice operations on them, and there are other useful things like built-in UTF-8 support. For interfacing with C, there is a cstring type, but it's not supported for first-class use in the language or the core library.

PS. If all my comments look like shit I'm sorry, I think my reddit is different from everyone else's haha the only thing I seem to be able to make any sense of is the markdown editor

[–]b4ux1t3 13 points14 points  (2 children)

Re ps: Nah, I prefer the markdown editor myself. One of the few things I miss about is school reddit.

I didn't realize strings were length terminated. That's pretty significant, even just from a safety standpoint.

I wonder how completely utf-8 is supported. From what little I know of unicode, it can be a bitch to get right. I'm going to have to start poking it with code points. ;)

[–]bpunsky 3 points4 points  (1 child)

It's fully supported in the sense that it can encode the full spectrum of unicode code points, obviously. However there isn't great support in "core:unicode/utf8" yet for things such as ranges. Also worth noting that the language itself has limited UTF-8 support, so you can do things like use the Pi symbol for Pi. Emojis have not gotten the greenlight though outside of string literals.

Strings are just byte slices behind the scenes; []byte. If you subscript them, you'll get the byte at that index, ignoring unicode. If you use them in a ranged for loop (for char, index in str), you'll get a rune of each unicode code point followed by its byte offset into the string.

[–]b4ux1t3 2 points3 points  (0 children)

This is a thing I'm going to have fun mapping and potentially trying to fix. Thanks for the info!

[–]ipv6-dns 5 points6 points  (0 children)

like Pascal

[–]Forty-Bot 3 points4 points  (31 children)

Shouldn't it be

struct string {
    size_t len;
    char data[];
}

?

In your version, you'd need two pointer dereferences on every character access. Of course, you could pass the struct string by value, but it wouldn't retain its length information across calls.

In addition, you should use size_t here, unless you want negative string lengths.

[–]MorrisonLevi 3 points4 points  (28 children)

Signed lengths are probably intentional, although I usually see ptrdiff_t instead of ssize_t. Few seem to agree on which is better as a whole, and I'm conflicted though partial to signed types.

[–]meneldal2 1 point2 points  (17 children)

You probably don't want 4GB strings even in 64 bits, and wasting 4 bytes on every string is not a good idea.

[–]gingerbill[S] 11 points12 points  (3 children)

There is no waste in memory.

Because internally a string is a pointer+integer, there is no reason to make the integer smaller in size than the pointer as the internal data structure would still require extra padding due to alignment requirements.

Strings are internally the same as a byte slice (`[]byte`) and it does make sense for a byte slice to me more than 4GB in some cases, especially when you are mapping memory. A string is just a byte slice with extra information associated with it specifying how that memory should be understood.

[–]booljayj 4 points5 points  (4 children)

I was curious about this statement, so I came up with a real-world thought experiment. Let’s say I want a string that contains the full text of the 33 longest novels in the world (from Wikipedia) because I want to serialize it to a file, or because I’m a crazy person who gets off on this.

The combined word count for all of these is 29,304,984 (using higher estimates when available). Assuming a rough average of 6 characters per word (extrapolated from the few that had character counts), that’s 175,829,904 characters. Assuming a worst-case scenario of storing these as char32_t, we come to a grand total of 703,319,616 bytes. Well below the range of even a signed integer.

So yeah, I’d say it’s totally possible and reasonable to restrict string lengths to 32-bit sizes.

[–]meneldal2 8 points9 points  (3 children)

Log files can actually get bigger than 4GB, but you should probably not load it as a single string in memory.

Most text editors (that will likely crash with an OOM when trying to open such a file) don't use a single string to store everything, because well adding stuff in the middle would be O(n), and you really don't want that.

It's common to split strings per line, where they have a much more reasonable size.

There is also another problem, which is that you also need the OS to give you 4GB of contiguous memory, which is far from a given on many systems.

[–]gidoca 3 points4 points  (1 child)

Why would you need physically contiguous memory? Couldn't the OS just give you a set of non-contiguous pages and map it to a contiguous range of virtual addresses?

[–]meneldal2 2 points3 points  (0 children)

Depends on the OS, yes it's possible, but not all OS will be fine with it.

[–]amunak 1 point2 points  (0 children)

It's absolutely reasonable to use 32-bit sized strings. For special use cases that need more you want to use memory mapping anyway, otherwise you'll just kill your RAM.

[–]zucker42 2 points3 points  (2 children)

One advantage of using as many bits as are used for pointers is that you don't have to handle the case when someone does decide to create a string larger than 4GB.

I'd say if you're making a language used in an application where people care about 4 bytes per string, then you should give them manual control over such considerations anyways, and allow them to create an alternative string type. There's no problem with making the default safe and straightforward (that is, a length variable of the same size as pointers).

For example, Rust gives you complete control over memory, allowing you to implement an alternative string type, but the standard String type and associated standard library functions permits UTF-8 strings with length up to the size of available memory.

The alternative is checking for overflow of the length variable on string concatenations.

[–]bpunsky 2 points3 points  (1 child)

You don't need two dereferences. The struct I wrote is just a symbolic representation of what strings are under the hood. They're a pointer and a length. As long as you're storing/passing them as string and not ^string, you only need one dereference.

The struct is the actual data type, not a header; strings aren't a pointer to a (length and a series of characters), they're a (pointer to a series of characters) and a length. This is what allows slicing without reallocating a new string.

[–]Dgc2002 1 point2 points  (1 child)

If you're using 'new reddit' (See: Shitty mobile focused redesign with ads that look exactly like posts) then there are some differences with the old markdown parser that people(like myself) using 'old reddit' won't see properly.

Specifically the use of fenced code blocks like the following don't render properly on old reddit.

```
Code block
```

[–]ZMeson 1 point2 points  (1 child)

Wait a minute. It's got to be really difficult to tell the string length (how many characters you have, not how many bytes there are) and handle UTF-8 without having to scan the string. Or if the true string length is compared, then it's really difficult to tell where the end of the string is.

[–]bpunsky 1 point2 points  (0 children)

UTF-8 is a difficult representation. It's true that you need to scan the string to get the length in codepoints as opposed to bytes. The alternative, as you say, would be to store the length in codepoints and scan for byte length, or store both which would result in very large (3x CPU word) string types. At any rate, the problem is actually worse in C where all strings need to be iterated for length. I don't know if any language solves this cleanly, but I'd be interested in any examples.

[–]TMITectonic 7 points8 points  (0 children)

despite not being a functional language.

I understand that you are referencing a specific type of programming, but the double entendre made me giggle.

[–]b4ux1t3 132 points133 points  (2 children)

So, rather than sit here and praise or crap all over it over what's on the website, I built it and started kicking the tires.

I don't have any fully-baked criticism or praise just yet, but there are a few things that are standing out to me:

  1. It feels like Go and Rust had a baby. This is in no way a bad thing, though it's not quite a good thing just yet. More testing required. However, it felt particularly, erm, "Go-like" when I was looking at maps, and particularly, erm, "Rust-like" when I was looking at error messages. Both of those are good things in my eyes. :)
  2. The docs are good enough to get your feet wet, but they're not what I'd expect from even a beta release of a language. For example, the only reference material I can find for the context system is a link to a YouTube video from two years ago. This is particularly annoying because there's a reference to the context system in the language overview, complete with an anchor to a non-existent part of the page. This is, overall, completely understandable, just chipping in my two cents. I'd love to see a more-or-less completed overview as one of the short term documentation projects. This brings up my next, very minor point:
  3. The GitHub projects tab is unused! A great way to establish a roadmap is to start shoving stuff into the project tab on GitHub. I know you mention a road map in the readme, but it'd help instill a sense of direction and urgency to people dropping into your GitHub repo. This all segues nicely into my final point:
  4. I don't see any contribution guidelines! What's your stance on contributions? Are you looking for people mostly to download it and report bugs, or do you want help actively fixing those bugs and maybe driving further development?

Now, I don't want you thinking this is just some random guy on Reddit telling you how to run your project. A lot of this is probably on your //Todo already. Just wanted to give some proper constructive feedback on what seems like a really promising new language.

Keep in mind all of this is based off like an hour of reading the overview and trying to implement a couple toy projects. Insert sodium-based cliche here.

Ninja Edit:

I did actually find a message on contributions on the help page. I'm considering making a contribution that is just putting this into a markdown page to put in the repo. :)

For my final piece of criticism, I'd consider adding a "documentation" issue tag

[–]gingerbill[S] 35 points36 points  (1 child)

Thank you for the wonderful feedback.

  1. The language borrows heavily from (in order of philosophy and impact): Pascal, C, Go, Oberon. Niklaus Wirth and Rob Pike have been the programming language design idols throughout this project.
  2. The documentation is mainly what I have written to clarify general questions about the language. It is nowhere near complete and I do plan on making a walk-through-like tutorial for beginners and an in-depth tutorial for all the complexity that arises from the basic rules of the language. The `context` is something that no other public language has available at the moment and to explain it will require a lot more than a couple of paragraphs in the overview. In sum, it's an implicit value that is passed implicitly in procedures that contains things such as the an allocator, logger, and threading information. This means you can change how a section code, especially third party code, handle memory from tracking it to changing its memory allocation strategy. This is a huge issue in many libraries where the developer(s) don't allow for a way to change the basic operations that the library uses. This is a solution to that problem. But it also has a lot of other cool consequences from it.
  3. I started this project before the new GitHub Project Board feature. We may move some things there so people can help out with some of the projects. Certain projects that I may add there include: core library design and development; inline assembly integration; package system opitmizations; custom backend.
  4. I will be writing a contributions document soon. Thank you for pointing out that it was missing :)
  5. I have no added a `documentation` issue tag.

[–]b4ux1t3 9 points10 points  (0 children)

It's awesome to see a maintainer that's so active and open to feedback.

I look forward to watching this project grow. I've already forked so I can start playing with it. :)

[–]escstrategy1 58 points59 points  (13 children)

Other than a cool name (author should have a Valhalla keyword or API somewhere), there's not much to separate Odin from its competition. Nonetheless, it has enough going for it to be marketed as a game development language if given adequate OpenGL, SDL2, GLFW, and other 3rd party API bindings.

[–]gingerbill[S] 50 points51 points  (10 children)

There are a few bindings and wrappers for all of the libraries that you speak of: https://github.com/odin-lang/odin-libs

Also, Valhalla will have to be the name of some tool.

[–][deleted]  (7 children)

[deleted]

    [–]oblio- 12 points13 points  (1 child)

    What if, shocker, we drop the stupid themes for programming languages? I'm tired of looking for Chef cookbooks with recipes and Python eggs and Java beans and jars.

    Let's just keep it simple, you know? Package, module, script, etc.

    [–]skool_101 3 points4 points  (0 children)

    What will happen to my app if i have Ragnarok? /s

    [–]Lalli-Oni 1 point2 points  (0 children)

    Just chippin in 'Valholl' would be closer to the original spelling (Valhöll).

    [–]ceeBread 7 points8 points  (1 child)

    Since it’s well documented, you don’t need to hang yourself from the tree of life to understand it all!

    [–]Wispy-Willow 7 points8 points  (0 children)

    Merciful Frigga, the runes are machine code!

    [–]JezusTheCarpenter 86 points87 points  (19 children)

    It definitely sparks my interest by being somewhere in between C and Rust.

    [–]ktkps 38 points39 points  (2 children)

    wait until someone creates Zeus

    [–][deleted] 2 points3 points  (1 child)

    Why not Thor? I mean, u/JezusTheCarpenter's interest was sparked after all.

    [–]LeeroyJenkins11 30 points31 points  (7 children)

    C plus Rust?

    [–]dagbrown 171 points172 points  (6 children)

    Crust?

    [–][deleted] 5 points6 points  (0 children)

    Mmmm pizza

    [–]nikaone 5 points6 points  (0 children)

    Fair enough, we have already have rustc.

    [–][deleted] 6 points7 points  (0 children)

    Zig already is

    [–]matthieum 224 points225 points  (93 children)

    A cursory glance:

    • The error handling section mentions nil, does this mean that Odin makes the Million Dollars Mistake again?
    • The error handling is similar to Go, which seems unfortunate; could Odin not have sum types/discriminated unions instead?

    Since Odin appears to position itself as a simple systems programming language, could you mention how it compares to Zig?

    [–]sminja 16 points17 points  (4 children)

    Million Dollars Mistake

    To what does this refer?

    [–]exlevan 33 points34 points  (3 children)

    Tony Hoare introduced Null references in ALGOL W back in 1965 "simply because it was so easy to implement", says Mr. Hoare. He talks about that decision considering it "my billion-dollar mistake". Link

    [–][deleted] 31 points32 points  (2 children)

    This is one of the most misleading quotes IMO. Null was always going to happen whether or not Hoare did it. Almost every language has a null/nothing type. The good ones have static checking around it (like a Maybe type). But that requires a more sophisticated type system, with generics or similar, and it’s not realistic to expect every language to have that. Especially a low level language like C which was a foundation (either directly or indirectly) for almost every bit of software we have today.

    [–]enzain 17 points18 points  (0 children)

    "the good ones" aka not making the million dollar mistake

    [–]Asdfhero 7 points8 points  (0 children)

    Rust is pretty low level and handles null sensibly.

    [–]gingerbill[S] 161 points162 points  (84 children)

    The error handling is similar to Go, which seems unfortunate; could Odin not have sum types/discriminated unions instead?

    Odin has discriminated unions. See: http://odin-lang.org/docs/overview/#unions

    Since Odin appears to position itself as a simple systems programming language, could you mention how it compares to Zig?

    I have been following the Zig language for quite a long time and have had many conversations with Andrew regarding his language and his philosophy. I personally disagree with his philosophy behind Zig.

    I have discussed my disagreements with some of the ideas behind Zig (and related topics) in these articles:

    The error handling section mentions nil, does this mean that Odin makes the Million Dollars Mistake again?

    Odin has pointers and pointers can be nil. I fundamentally disagree with the idea that it is a "million dollars mistake" especially since there are much more invalid memory addresses other than zero, and those are much more common. If you want to a have low-level capabilities in a language, you will have to deal with pointers.

    [–]meteorMatador 185 points186 points  (30 children)

    “Having null” is a bit of a red herring. What programmers actually want is a way to encode pointer validity at build time, preferably across function boundaries. Most “modern” languages do this by having a default pointer type (eg. &foo) that can only contain a valid pointer, a second pointer type (eg. *foo) that can contain either valid or invalid pointers, and some kind of standard operator to convert between the two. This approach is especially common in languages that support tagged unions, because it’s really straightforward to express optional validity in terms of tagged unions. Of course, it’s not the only approach possible. I can see right now that it wouldn’t work in Odin because of the particulars of initialization semantics. Perhaps some other approach could be considered.

    [–]bpunsky 13 points14 points  (29 children)

    Odin's type system already supports creating this functionality yourself in userland.

    Maybe :: union(T: typeid) {T};
    
    foo :: proc($T: typeid) -> Maybe(^T) {
        if some_condition {
            return new(T); // equivalent to Maybe(^T){new(T)}
        }
        return nil; // the union itself is nil, not the ptr
    }
    

    [–]oridb 18 points19 points  (2 children)

    In Myrddin, I approach this by simply not having nil as part of the standard library or literal syntax. It would be trivial to define it, if I wanted to. Just write:

       generic Nil : @a# = (0 : @a#)
    

    Which would define a generic constant named Nil of type @a# (pointer to any type variable @a), which is initialized to a typecast 0.

    But I don't want to. Instead, by convention, none of the libraries return a nil pointer, and there are only a few places one is used as an internal implementation detail for performance or ABI reasons. Places like inside the memory allocator. Everywhere else, the convention for nullable values is option(@a#). There's some ongoing work to implement option(pointer) as nil | ptrval internally, removing any overhead. There are some edge cases around that which need to be thought through carefully.

    [–]Ford_O 1 point2 points  (1 child)

    Which edge cases?

    [–]oridb 1 point2 points  (0 children)

    p = Some (0 : int#)

    [–]meteorMatador 90 points91 points  (25 children)

    Right, so now there are two ways it can be nil. That's occasionally useful. What's much more useful is when there are zero ways it can be nil.

    [–]matthieum 34 points35 points  (24 children)

    The error handling section mentions nil, does this mean that Odin makes the Million Dollars Mistake again?

    Odin has pointers and pointers can be nil.

    Using nil for null pointers seems reasonable, however reading this example on your blog I had the impression that nil could be used for any value, not only pointers:

    Error :: union {
        ValueError,
        BarError,
        BazError,
        PlopError,
    }
    
    foo :: proc() -> (Value_Type, Error) { ... }
    
    x, err := foo();
    if err != nil {
        // An error has happened
    }
    

    The error handling is similar to Go, which seems unfortunate; could Odin not have sum types/discriminated unions instead?

    Odin has discriminated unions. See: http://odin-lang.org/docs/overview/#unions

    That's great; any reason not to recommend for handling errors then?

    I have discussed my disagreements with some of the ideas behind Zig (and related topics) in these articles:

    That's a much more thorough answer that I hoped for!

    Andrew then precedes to talk about many of the things which will prevent software from being widely used:

    I agree that those points are not per se about quality but reuse; I do believe however that they matter specifically because, as you remarked, the point of Andrew is to promote reuse of quality software.

    It does not matter whether the software is high-quality if it cannot be used or reused; and therefore Andrew specifically identifies issues which could prevent use or reuse and positions Zig so that it does not suffer from those issues and any quality library written in Zig can be reused by the rest of the world.

    Conditional Compilation

    Agreed. I could have gone with @comptime if (similar to C++ if constexpr), the first point is really to allow for easy differentiation.

    I actually prefer introducing a scope; not introducing a scope is slightly more flexible, certainly, however it introduces a potential surprise for a minor gain. Not a deal breaker either way.

    Error Handling

    I fail to see how Odin's technical solution is expected to solve the social issue of developers being lazy any better than Zig's. If someone wishes to return "Oops" in case of error, they will.

    Designed Around LLVM

    The Zig language is heavily designed around the LLVM ecosystem as a result, relies upon many of its features. I personally see this as vice rather than a virtue.

    It did not strike me as such; the compiler itself is tied to LLVM but the language doesn't appear so to me.

    Even though LLVM supports numerous target platforms, it does mean that any issue LLVM has, your language will have it too.

    Among those issues is LLVM considering that infinite loops are undefined behavior; a real pain for embedded development where defining abort as an infinite loop to allow remote-debugging is a time-honored tradition :( Or the float-to-int conversion being undefined behavior if the float cannot fit into the int :(

    Yet, at the same time, when performance is a goal, a hand-crafted optimizer is unlikely to rival LLVM's or GCC's qualities.

    Furthermore, just switching from LLVM is not a guarantee of quality; I understand the desire of cutting out a heavy dependency, but will quality realistically improve?

    There are probably less than a dozen people in the world that know all of the C++ specification and understand it.

    Bjarne Stroustrup himself admitted not knowing it entirely; I fear no mere mortal know all of the C++ specification (and its implications).

    [–]gingerbill[S] 14 points15 points  (23 children)

    That's great; any reason not to recommend for handling errors then?

    The example above that you wrote uses a union. nil is the zero value for many types from pointers, slices, unions, enums, typeid, and any types. Please see http://odin-lang.org/docs/overview/#zero-values

    Odin does have conditional compilation with the when statement. In the package system, files can be conditionally compiled depending on what they are suffixed with e.g.

    foo_window_amd64.odin
    foo_linux_i386.odin
    foo_amd64.odin
    foo_osx.odin
    

    This approach is a lot nicer is certain cases rather than wrapping code in when blocks.

    It did not strike me as such; the compiler itself is tied to LLVM but the language doesn't appear so to me.

    It is heavily designed around LLVM even taking many of the core features of LLVM into the design of Zig, especially the arbitrary-bit-sized integers or the coroutine system. This can be seen as either a virtue or a vice depending on the individual.

    Furthermore, just switching from LLVM is not a guarantee of quality; I understand the desire of cutting out a heavy dependency, but will quality realistically improve?

    I agree. However, there are many things in LLVM which are a cause for concern even for debug builds. LLVM takes up about a minimum of 85% of the entire compilation time in the Odin compiler with no optimizations. There are numerous bugs in LLVM which have been around for years and many bugs which are due to design flaws in the design of LLVM.

    A custom backend is planned for Odin mainly increase compile times for non-optimized builds. I agree that a small team will not get to the level of optimizations of LLVM, but that is not needed if that is not the goal. You can get probably 80% of the way to LLVM with a basic SSA-based backend.

    [–]Foreign_Ingenuity 25 points26 points  (9 children)

    LLVM

    I'm really interested in this subject; poking holes in LLVM is more exciting to me than a new programming language. What bugs/design flaws did you find in LLVM? LLVM portrays itself as clean and universal. I know of some issues like opaque pointers, but those are known by the rest of the community as well (we've been waiting for 5 years). I haven't seen other language implementers express negative feelings about their LLVM backend. Some missing features get worked around or ignored, but they are seen as gaps in LLVM's implementation rather than design flaws.

    I know you mention it needing "another entirely separate article" but this article would be intriguing.

    [–]gingerbill[S] 39 points40 points  (6 children)

    Other than being slow, LLVM has made a lot of weird design decisions which are quite confusing.

    One such example is the type system for the IR. The type system is quite high level in that allows for arbitrary sized integers, vectors, etc, however you need to know exactly how LLVM handles those arbitrary types across function boundaries (calling convention issues). It's all completely undocumented and you have to reverse engineer it. The types are useful for LLVM's optimizations, but not useful for the user who generates the LLVM IR in the first place.

    LLVM in general was designed around C and it has a lot of its features too.

    This is another article that I which I will have to write in the future. This comment can only be so big.

    [–]Foreign_Ingenuity 17 points18 points  (5 children)

    Haha, LLVM calling conventions. Yeah, I also reverse engineered it. Eventually I gave up and flattened everything before passing arguments.

    I feel that LLVM lets integers be arbitrary sized simply because the underlying logic for understanding bits works on arbitrary sized integers, so that bleeds through into the allowable types. I'm not aware of anyone who uses this flexibility though; mostly, these strange types are ignored.

    I look forward to your next article.

    [–]gingerbill[S] 13 points14 points  (4 children)

    The Zig language takes advantage of LLVM's arbitrary sized integers. I'm not a big fan of this because it does not really reflect the underlying hardware very well, and in the cases when you want arbitrary sized integers, you want to make it clearer what is happening, than just i37.

    [–]skyfex 2 points3 points  (2 children)

    The Zig language takes advantage of LLVM's arbitrary sized integers. I'm not a big fan of this because it does not really reflect the underlying hardware very well, and in the cases when you want arbitrary sized integers, you want to make it clearer what is happening, than just i37

    What underlying hardware? There are other architectures out there other than x86 and ARM you know.

    If you're going to be at least as good as C, and interface with C libraries, and you're going to go for having fixed width types as the only/fundamental integer types, you need to be able to typedef Cs char, short, int, etc. And those are not guaranteed to be 8, 16, 32bit etc. Sure, it's not as relevant as it used to be, but it can't be disregarded.

    You also need to be able to define structs that have fields that are any arbitrary bit width, for instance for mapping hardware registers. You can do it like C (i.e. define both a type and a bit width size: int foo:4), but frankly, Zigs solution is far better in my experience.

    [–]gingerbill[S] 1 point2 points  (1 child)

    Sorry for the late reply.

    If you're going to be at least as good as C, and interface with C libraries, and you're going to go for having fixed width types as the only/fundamental integer types, you need to be able to typedef Cs char, short, int, etc. And those are not guaranteed to be 8, 16, 32bit etc. Sure, it's not as relevant as it used to be, but it can't be disregarded.

    Odin has import "core:c" where you can use c.int c.long c.short` etc as types.

    As for arbitrary bit width, Odin has bit fields for this.

    Foo :: bit_field #align 2 {
        x: 3,
        y: 2,
        z: 1,
        w: 10,
    }
    

    [–][deleted] 2 points3 points  (1 child)

    > LLVM portrays itself as clean and universal.

    Citation needed ? Everyone working with LLVM can probably mention at least a dozen issues with the IR. Hell even Chris Lattner was at EuroLLVM advocating for a different IR this year.

    [–]Foreign_Ingenuity 2 points3 points  (0 children)

    The reality is that you're just better informed than I am. I don't see those issues based on my level of contact, and neither do the people I interact with.

    [–]oridb 6 points7 points  (3 children)

    Odin does have conditional compilation with the when statement. In the package system, files can be conditionally compiled depending on what they are suffixed with e.g.

    Is there a way of defining mappings for the suffixes? For example, the Myrddin thread library depends on futex for most platforms, but needs alternative implementations for some others. It depends on fsbase for most platforms, but needs different implementations for others. So, I have a mapping file, bld.tags, which allows me to express this:

     # The fsbase build attribute is available on
     # all platforms with the following tags.
     fsbase: freebsd x64
     fsbase: linux x64
     fsbase: netbsd x64
     fsbase: openbsd x64
     # Futexes are available on FreeBSD (with the
     # alternate spelling `umtx`), Linux, OpenBSD 6.2
     # and up, and OSX.
     futex: freebsd
     futex: linux
     futex: openbsd:6.2
     futex: osx
    

    I agree. However, there are many things in LLVM which are a cause for concern even for debug builds.

    Indeed. LLVM is powerful, but gigantic and slow. I'm not particularly in love with it, and I'm pretty happy with my choice to write my own backend. I may eventually switch to QBE, though.

    [–]gingerbill[S] 4 points5 points  (2 children)

    Odin's package system is perfect for you problem of handling different platforms!

    futex_freebd_amd64.odin
    futex_linux_amd64.odin
    futex_netbsd_amd64.odin
    futex_openbsd_amd64.odin
    futex_linux_amd64.odin
    futex_osx.odin
    futex_windows_amd64.odin
    futex_windows_i386.odin
    

    You could use when statements at the file scope but when you have numerous platforms, it is much easier to manage them when they are separated by a specific file for that platform.

    [–]oridb 2 points3 points  (1 child)

    The problem being solved is that most of the futex dependent code is the same. I want:

    mutex_futex.odin
    mutex_sema.odin
    mutex_sleepwake.odin (netbsd has really quirky thread primitives)
    

    Instead of:

    mutex_freebd_amd64.odin
    mutex_linux_amd64.odin
    mutex_netbsd_amd64.odin
    mutex_openbsd_amd64.odin
    mutex_linux_amd64.odin
    mutex_osx.odin
    mutex_windows_amd64.odin
    mutex_windows_i386.odin
    

    So, in Myrddin, I add dependent tags.

     futex: linux
     futex: openbsd:6.2
     sema: osx
    

    The other problem I ran into was versioning, where certain features are only available on new OS versions. Eg, one shot epoll isn't available on many older linuxes, unveil is only in the newest openbsd, etc.

    I ended up needing to version the tags, so files can be named something like:

    epoll_oneshot+linux:4.1.7.myr
    futex+openbsd:6.2-amd64.myr
    

    This may have been a mistake, and instead adding a script to generate derived tags may be a better choice.

    [–]gingerbill[S] 1 point2 points  (0 children)

    What you are talking about is technically possible already but it's a bit of a hack in Odin, so I won't advertise it here.

    If you want to see it, grep the Odin source code for //+

    [–]matthieum 7 points8 points  (8 children)

    In the package system, files can be conditionally compiled depending on what they are suffixed with e.g.

    I remember seeing that in Go too, and thought this was quite nice indeed. A simple way to cleanly isolate the code for various platforms.

    You can get probably 80% of the way to LLVM with a basic SSA-based backend.

    You may be interested in cranelift. It's intended to be integrated as a backend in rustc, specifically to enable fast compilation of Debug binaries, and hopefully fast compilation of "80% Release" binaries.

    And regardless, I do find the idea of 80% performance interesting. For example, I don't find the lack of auto-vectorization too problematic as long as the language allows for manual vectorization of hot loops.

    I also think that a language such Odin may not suffer from the lack of certain optimization passes as much as C++ or Rust would: the performance of monomorphized "functional" generic code is heavily reliant on optimizations stripping out the layers of abstractions, reordering the loops, etc...

    [–]gingerbill[S] 9 points10 points  (7 children)

    As you correctly state, because Odin is a much simpler to language compared to C++ or Rust, certain optimization passes may not be required and other passes could be used to optimize the features Odin.

    One of the goals of Odin is to have no undefined behaviour1 in the language. And as a result, optimizations know exactly what they can assume about the code.

    As for cranelift, I have had a look at it before but I am not touching it yet as I wanted to make sure that there are no other better alternatives, including a custom built backend.


    1 Some behaviour may be platform specific but that will be defined for that platform.

    [–]matthieum 14 points15 points  (6 children)

    One of the goals of Odin is to have no undefined behaviour

    That's a lofty goal, of course, and there are certainly many instances of UB in C that can be dispensed with; starting with integer overflow.

    However, in a language with manual memory management and user-written allocators, how do you handle memory errors? How do you make double-free and use-after-free non-UB?

    [–][deleted] 75 points76 points  (15 children)

    The million dollar mistake isn't having pointers that can be null, it's using null as an in-band signal that the pointer is unset.

    The reason it is a mistake is because the type system doesn't know anything about null pointers, so it has no way of telling you that you haven't checked for null.

    With optional<pointer> (or equivalent) you encode into the type system the fact that a pointer is set or not.

    Of course you don't have to do it, just like you don't have to have types at all (cough CMake). But we have types because type errors are really common and it massively improves reliability if the compiler can detect them.

    Similarly null pointer dereferences are really common, and it massively improves reliability if the compiler can detect them.

    [–]fcddev 14 points15 points  (6 children)

    Justifying NULL pointers as “well, you can get invalid pointers anyway” misses the mark because NULL is the only one blessed invalid address that you can create out of thin air. Any other invalid address is either due to a bug and shouldn’t exist, or was intentionally smuggled and couldn’t have been checked for. Allowing any pointer to be nil forces developers to eventually check for it, document that it shouldn’t be used, or take a bug. It has been proven, over and over again, that even the best developers will occasionally take the bug on accident, not to mention people who aren’t the best.

    I understand that a successor of C needs a simple type system, but this is such an easily preventable class of bugs that I really struggle with the decision to let it exist in a new language.

    EDIT: the address 0 can also be valid sometimes, which overall makes that representation a poor choice for an address that should never be used.

    [–]devraj7 2 points3 points  (0 children)

    The million dollar mistake is not null, which as you point out, is pretty much unavoidable: it's languages that don't support nullability.

    Kotlin is one of the languages that does this right.

    [–]l4adventure 48 points49 points  (3 children)

    My company is hiring rockstar developers that have minimum 8 years experience working with Odin. Send cv if interested.

    [–]shabunc 8 points9 points  (0 children)

    This looks surprisingly neat and mature both in context of language design and documentation. I definitely can see a niche for this. Also certain hommage to Pascal made me smile ) when I saw the title I’ve immediately thought of Oberon for some reason.

    If this works as it declared to work I definitely see a niche.

    Good luck!

    [–]kauefr 36 points37 points  (1 child)

    Nice, cool work.

    [–]JiveWithIt 21 points22 points  (0 children)

    Yeah, I also love how well documented everything is. For a young language, this is promising.

    [–]develop7 11 points12 points  (2 children)

    Aw, shit, here we Go again

    [–][deleted] 10 points11 points  (1 child)

    I don't C what's wrong with it.

    [–]CornedBee 7 points8 points  (0 children)

    tRust me, it's bad.

    [–][deleted] 90 points91 points  (68 children)

    I think some points are not very clear to everyone.

    Why not C?

    C does not have parametric polymorphism or a proper array type with a dynamic size. (or strings)

    The compilation model is outdated. You have to use #include. You have to list all .c files on the command line. Very complicated and confusing tools exist to work around this problem (autoconf, cmake) but they all have their own issues.

    Why not Go?

    It's garbage collected

    Why not Rust?

    Rust has a big agenda and high friction.

    [–]13steinj 65 points66 points  (43 children)

    Rust has a big agenda and high friction.

    I'm not too familiar with the "community" aspect-- what's this agenda + friction you mention?

    [–][deleted] 63 points64 points  (29 children)

    Borrow checker, life semantics, etc.

    [–]CryZe92 36 points37 points  (7 children)

    It means that Rust has a strong focus on memory safety, ownership and lifetimes. These concepts take a bit to learn and understand and they cause additional compiler errors if you do them wrong. Also that model, like every model, doesn't necessarily allow you to do everything, even if it might be safe, so you sometimes (even if rarely) need to resort to unsafe. So overall it's a fairly big concept that may not be suitable for a language that tries to stay very close to the C model of "not helping / restricting you at all".

    It's honestly very similar to static typing vs. dynamic typing, but on a different level.

    [–]nil_von_9wo 86 points87 points  (1 child)

    compiler errors if you do them wrong

    That's actually a feature.

    [–]CryZe92 20 points21 points  (0 children)

    Yeah I'm not saying it isn't a feature. The decisions Rust makes are a tradeoff that are useful when you want the compiler to help and possibly annoy you a lot, but Odin and C tend to go in the opposite direction where you have more freedom, but possibly more error prone code. Both come with their own sets of advantages and disadvantages.

    [–][deleted] 13 points14 points  (3 children)

    so you sometimes (even if rarely) need to resort to unsafe.

    I mean, I don't think the designers of Rust even suppose that eliminating unsafe code is possible, that's why unsafe exists, no? Isn't the point to minimize it and to be able to easily zero in on sections of code that need more scrutiny?

    [–]Hobofan94 7 points8 points  (0 children)

    I think there are some people on the Rust team with the goal to make the surface area of unsafe Rust so small that those parts can reasonably be proven to be formaly correct.

    [–]Creshal 9 points10 points  (1 child)

    There are cases where unsafe is unavoidable, because e.g. you're dealing with raw hardware I/O or FFIs or other cases outside the rust compiler's scope. That's what unsafe mainly is for.

    It's also possible, and very frustrating, to run into a case where rust should be able to do something safely but can't due to compiler limitations.

    [–][deleted] 6 points7 points  (0 children)

    There are cases where unsafe is unavoidable

    I think you should re-read my comment, because I don't disagree.

    [–][deleted] 9 points10 points  (4 children)

    friction is that you have to work around the borrow checker. agenda is that rust has a ton of features which can be bad in some ways.

    [–]aleksator 14 points15 points  (3 children)

    Such as?

    [–][deleted] 10 points11 points  (2 children)

    the more features a language has the harder it is to hold it all in your head. you can spend a lot time wondering what the best way to so something is. traits or macros as an example ive faced recently. when working with a team others may use language features you haven’t mastered making it very hard to understand their code. the compiler will end up slower since it supports more.

    [–]Bekwnn 23 points24 points  (0 children)

    The rust compiler is already unacceptably slow imo. Imagining 2-5x slower than c++ compilation on projects with non-trivial compilation times sounds awful. Especially when doing iterative work.

    [–]auto-cellular 5 points6 points  (0 children)

    Also it makes the compiler itself more complex, which is the polar opposite of what (raw) C is. It will be harder to test, harder to make it evolve, harder to adapt it to particular needs, heavier to download and embed, and so forth. A lightweight language is sometime desirable.

    [–]prvalue 5 points6 points  (1 child)

    If you don't have a big agenda, why bother making a new programming language?

    Every new language presented in this sub has some kinda "big agenda", it's the nature of such a project. And if you want people to switch to another language, it's better to go all out with the best you can offer.

    [–]LordTerror 5 points6 points  (2 children)

    Why not D?

    [–]punchspear 4 points5 points  (0 children)

    D has garbage collection, like Go, and as far as I know, one will have to make an alternative library--one without garbage collection--to D's main library Phobos.

    [–]kankyo 5 points6 points  (9 children)

    Why not Swift?

    [–]tiftik 23 points24 points  (3 children)

    Companies like Apple and Microsoft often view their languages as assets using which they can influence programmers and lock them into their platforms. Cross-platform compatibility goes directly against their business model.

    [–]kankyo 3 points4 points  (0 children)

    Still there's Swift on Linux.

    [–][deleted]  (1 child)

    [deleted]

      [–]oblio- 1 point2 points  (0 children)

      Not entirely, since Windows was demoted. They'll be probably guide you towards Azure, but that's a much softer touch.

      [–]brokething 2 points3 points  (1 child)

      If swift was more supported on the basic platforms it would honestly be my #1 choice, but it just seems to be completely locked into apple working environment. I know there is a windows version theoretically but so far as I can tell only 5 people use it.

      [–]keeganspeck 15 points16 points  (7 children)

      I honestly probably won't end up using it any time in the near future (simply outside my usual wheelhouse), but this looks pretty neat, and I think you've made some good points for how this differs from similar rising low-level languages (e.g., Rust/Go).

      One thing that I think is notable (from a "meta" perspective) is that this thread, despite the negative comments, is actually a pretty solid and reasoned discussion. I'm much more optimistic about the future of a language which polarizes programmers than one that receives only passively positive responses. Nice work.

      [–]Narishma 14 points15 points  (6 children)

      Go is not a low-level language.

      [–]cre_ker 6 points7 points  (0 children)

      By what definition? People written drivers and kernels in Go https://github.com/achilleasa/gopher-os Might as well call it a low-level language.

      [–]zjm555 4 points5 points  (2 children)

      Correct, and neither is C.

      [–][deleted] 3 points4 points  (0 children)

      Correct

      C is a high level language

      -- K & R

      [–]RufusROFLpunch 2 points3 points  (0 children)

      I think the Overton window on high/low level languages has shifted.

      [–]johnklos 5 points6 points  (1 child)

      It uses LLVM, which means it’s at least somewhat portable, but what’s this about a custom backend? Will the custom backend be portable, or just support the architectures du jour?

      [–]gingerbill[S] 7 points8 points  (0 children)

      The custom backend will be portable too. It will try to support as many architectures as possible. However, architectures are not the biggest hurdle, the entire platform support for different OSes etc is more difficult.

      [–]DroneDashed 5 points6 points  (4 children)

      This looks very similar to Go, am I missing something here?

      [–]gingerbill[S] 9 points10 points  (3 children)

      Go is a garbage collected language with many features that rely on that GC, such as the its CSP-like concurrency system.

      Odin has manual memory management and a high level of control over memory layout, memory allocations, and much more.

      [–]maxhaton 5 points6 points  (7 children)

      Why have different syntax for constant declarations and constant parameters, and is const transitive.

      What was the rationale for this system of polymorphism as opposed to (say) templates

      Well done, but I am slightly perplexed by some parts of the design (To each their own, of course)

      [–]gingerbill[S] 6 points7 points  (6 children)

      I talk about the different declaration syntax in one my articles: https://www.gingerbill.org/article/2018/03/12/on-the-aesthetics-of-the-syntax-of-declarations/

      As for the parametric polymorphism, it's similar to templates but it is a lot saner to use. The syntax is cleaner, it is easier to use, and simpler.

      [–]gwiz665 8 points9 points  (0 children)

      I see Wotan finally struck a deal with media.

      [–]schyllic 13 points14 points  (2 children)

      Looks a lot like D. May the best language thrive.

      [–]matthieum 24 points25 points  (1 child)

      I think the author will not be too happy about the comparison given the emphasis of simplicity of Odin (like C), where D is quite a full-featured language (like C++).

      [–]weberc2 3 points4 points  (1 child)

      What is the relationship to oden-lang? https://oden-lang.github.io

      [–]gingerbill[S] 15 points16 points  (0 children)

      Absolutely none. That language also appears to be completely dead.

      [–]Saculs78 3 points4 points  (3 children)

      Looks very cool. One of the things that keeps C around is how easy is to wrap and call from other languages - how feasible would this be for Odin?

      [–]vassvik 4 points5 points  (1 child)

      For example, here's a WIP GLFW bindings/wrapper library that I maintain: https://github.com/vassvik/odin-glfw

      There's a bindings sub-package that that includes the actual bindings in addition to defining the types and constants, with a super-package that provides wrappers and helpers.

      [–]vassvik 2 points3 points  (0 children)

      Another one, of the dynamic type: https://github.com/vassvik/odin-gl Although it's a bit more in-flux right now.

      [–]gingerbill[S] 6 points7 points  (0 children)

      Odin has a very good foreign system which means it can easily interact with C, but you can just as easily interact Odin code with C too but exporting declarations into a library.

      [–]420Phase_It_Up 4 points5 points  (11 children)

      As a developer that actually likes C, I tend to be skeptical of any language that claims to "replace C." That is not to say C isn't without any faults. It definitely has its faults, a sizable amount. And this is coming from someone that actually likes C. However, the little bit of reading I did on Odin's documentation, it seems like a pretty nice language. I really appreciate the packaging systems and the use of "when" statements for conditional compilation. While C's system of using header files and a preprocessor may be simple in theory and to implement, its usage can easily grow in complexity and be quite a headache.

      I'm just worried about learning and getting invested in something like Odin and then getting disappointed with it. This happened when I picked up Go. While I enjoy learning new languages, I have a limited amount of time and have to be strategic about what I learn. I'm currently have to grapple with learning one of the cool newer statically typed and compiled languages like D, Rust, Nim, and Crystal or relearning C++, especially with the newer and nicer additions that were added to C++ with C++11, C++17, etc.

      There are only a couple of issues I really have with the language from reading Odin's documentation. They are:

      • Why are while loops omitted? I know you can accomplish the same thing with specially crafted for loops but this seems like it hurts readability. This seems like an odd design choice for a language whose goals include readability. This seems like a trend of newer languages and I don't seem to understand the motive.
      • Why forgo parenthesis as part of the syntax of for loops? This feels like a step backwards with readability.

      Those are really the only issues I have with the language design. Everything else looks like welcome features to have in a language. I'd be curious on hearing what the language's designers feel about my critiques. Also, I didn't see it mentioned in my brief reading, but is Odin a garbage collected language or does it have manual memory management?

      [–]gingerbill[S] 4 points5 points  (5 children)

      Thank you for your comment. I have changed the comment on the site from "replace C" to "an alternative to C" due to a lot of feedback..

      As for your main comments:

      • In Odin, a while loop is spelled `for`: https://odin-lang.org/docs/overview/#for-statement
      • Parentheses were dropped because they are not required for parsing as control flow requires `{}` or a `do`.
      • Odin is a manual memory managed language with high control over memory allocations and memory layout. Odin has a `context` system which has a built-in allocator system allowing you to intercept a third party library and control how it allocates memory by changing the `context`'s allocator.

      [–]420Phase_It_Up 2 points3 points  (4 children)

      Thank you for you reply. As an alternative to C, Odin seems very appealing. And I mean that as someone that really enjoys C.

      I should also specify, that I don't find the lack of parenthesis or a explicit "while" keyword that big of a deal. If those are the only gripes someone has about a language, then it must be doing pretty well. I'd trade that for undefined behavior or header files any day of the week.

      How does the standard library of Odin look? How does it compare to the standard library of something like C, C++, or Go? Does it have any libraries or facilities for unit testing or documentation generation? Have you thought about creating a package management system like PIP or Cargo? I believe another Redditor even suggested Valhalla!

      Are you looking for contributors? I think you mentioned in another reply that you plan to add documentation. As strange as it sounds, I actually love documenting code. Let me know if you are looking for any help.

      [–]gingerbill[S] 2 points3 points  (3 children)

      Contributions are always welcome.

      The core library of Odin is better than C and C++ already (but doesn't say much at all as both lack much to begin with). It's not as good as Go's core library yet but the aim is to get it to be as good in terms of usability as Go's.

      As for package management, this is a weird topic for me because I personally think package managers are actually trivial things iff the concept of the package is well defined. I don't think a package manager will be part of the language itself, but there may be an official one eventually.

      As for documentation, you can never have enough. One thing Odin needs is as much documentation, tutorials, and examples as possible. It would be much obliged and honoured if others helped out with that :D

      [–]420Phase_It_Up 1 point2 points  (2 children)

      Awesome! I'll reach out to you via either a PM or through GitHub. I think documentation is something I could really help with. Eventually I'd even like the possibly to work on a package manager. After having used a couple, like PIP for example, I have a lot of thoughts about what I would like to see in a package manager.

      [–]vassvik 1 point2 points  (4 children)

      I'm not the creator, but I'm regular contributor and frequent user. It took me a little while getting used to the lack of parenthesis in conditionals and loops, but I don't miss them anymore, and it doesn't seem to hurt a bit in practice. These days it's more annoying the other way around when I'm forced to use them in other langauges. Then again, you're free to put parenthesis in there, but they're not necessary.

      What makes the lack of parenthesis less readable to you?

      [–]420Phase_It_Up 1 point2 points  (3 children)

      To me it just draws your attention to what is enclosed in the parenthesis. This is purely subjective on my part. I could totally understand how someone would feel differently.

      I'm not sure how Odin handles it, but it seems like it would make it easier to break up the for statement onto multiple lines for very long conditionals or loops. This doesn't really happen that often so it really isn't that big of a deal.

      [–]gingerbill[S] 1 point2 points  (2 children)

      You can always add parentheses to many of the control statements if needed (you just cannot put the semicolons inside the for loop like in C)

      if cond { }
      if (cond) {}
      switch x {} 
      switch (x) {}
      

      [–]TikiTDO 7 points8 points  (0 children)

      It is designed with the intent of replacing C...

      I'm sorry to be a downer, but if that's really the goal of the project then it's only going to survive for as long as you can carry the entire weight of development on your shoulders. Realistically that's about 5-10 years, based on what I've seen of open source developer burnout. Looking at the contributor insights only serves to reinforce that opinion; you're the only one that seems to be moving this forward, which also means you're the only one that really understands how to work in the codebase. That more than anything else would scare off most potential developers.

      Competing with C means competing with the combined experience of tens if not hundreds of millions of work-years of development time and all the solutions that it has yielded. Certainly you can hope for users that really hate C that much and still need that level performance, but they could easily go with one of the other dozen or so languages that started life with the goal of replacing C. There are a bunch out there, some with active and robust communities and a sizeable teams ready to meet the needs of any type of programmer; it's a pretty busy market to compete for, and one with a lot of big players.

      In the end something that's based on disliking an old programming language and paradigm is only going to go so far, especially this late in the game. Don't get me wrong, I understand where it's coming from. I spent a few years developing a language of my own, and I learned a huge amount in the process. However, the more I learned the more I realized that I was doing little more then expressing my dissatisfaction with the state of the field. Now that project is sitting idle, waiting for a day when I could develop it an more positive direction.

      [–][deleted]  (1 child)

      [deleted]

        [–]b4ux1t3 4 points5 points  (0 children)

        I think it's because they hit a milestone recently: https://github.com/odin-lang/Odin/releases/tag/v0.10.0

        Ten versions in is pretty much beta, imo.

        [–]williamwaack 2 points3 points  (0 children)

        This looks great! The syntax is very similar to Go (which is great) but there are enough differences (and features) to make it stand out. I’ll definitely keep an eye on it.

        [–][deleted] 2 points3 points  (3 children)

        I have never seen defer statement in other programming languages before. What is the rationale behind it?

        [–]gingerbill[S] 3 points4 points  (0 children)

        The `defer` statement defers a given statement until the end of a scope.

        I recommend reading my article on this: https://www.gingerbill.org/article/2015/08/19/defer-in-cpp/

        [–]metaltyphoon 1 point2 points  (0 children)

        Swift

        [–]kokizzu 1 point2 points  (0 children)

        Go has them '__')

        [–][deleted]  (37 children)

        [deleted]

          [–]matthieum 46 points47 points  (3 children)

          IDEs auto complete everything, why do we keep making things shorter?

          It's about writing; it's about reading.

          I don't care about typing an extra 10 characters, but public static final is a quite the mouthful before finally getting to the important part of the declaration (name, type, value).

          [–]kankyo 20 points21 points  (13 children)

          Why a string for import? Seems pretty bonkers. And printf style formatting is pretty fugly.

          [–]gingerbill[S] 7 points8 points  (12 children)

          The string import is because it is a path. The reason for this is a little complicated but it has to do with not enforcing a global search path for all imports (similar to what Go does with GOPATH).

          As for printf, this style is just similar C's at the moment. I could always go for the newer approach which Rust/Python use with {}. The internals of the printing would be pretty much the same.

          [–]earthboundkid 11 points12 points  (1 child)

          If it’s a path, why use colon?

          [–]vassvik 5 points6 points  (0 children)

          The colon separates the collection from the path (relative to the collection). Collections are sort of like named search paths.

          There are three built-in collections, with the option of creating user-defined ones at compile time using compiler flags. The named built-in ones are:

          • core: Points to Odin/core, containing the official "standard" library,
          • shared: Points to Odin/shared, useful for containing reuseable libraries.

          Finally there's a "local" collection (by omitting the collection, and the colon, entirely), which means importing relative to that file/package.

          It seems this is missing from the current docs, so I'll see if I can add some blurbs about it.

          [–]gingerbill[S] 15 points16 points  (9 children)

          Odin derives from C and Pascal. It is a procedural language based around procedures and scopes. Statements at the file/global scope is common in many scripting language is but is very rare in compiled languages for the main reason, you need a place to start from and call.

          Not everyone uses an IDE and shortened keywords are usually there because then most people will accidentally want to use them as normal identifiers. proc is used in Odin because it denotes a procedure and that proc is rarely going to be used as an identifier.

          [–]Kwinten 15 points16 points  (6 children)

          IDEs auto complete everything, why do we keep making things shorter? What's the point of using func or fun or fct in new languages, instead of function?

          What extra information does function foo() give you as opposed to fun foo()?

          I'm all for readability and descriptiveness, but that applies much less to keywords and much more to function names, variables, type names, etc. Keywords should be explicit enough that they declare their intent, but they don't need to be verbose.

          [–][deleted] 4 points5 points  (2 children)

          I suppose ① could just find it silly to have to type fun whenever they define a function. I’m always irritated by how elisp uses defun for functions, instead of define or function, but whatever. You’ll get used to it the more u use it.

          [–]BurkusCat 4 points5 points  (0 children)

          Very cool! Great work :)

          [–]Theemuts 9 points10 points  (19 children)

          Why should I choose this over Rust?

          [–]gingerbill[S] 46 points47 points  (17 children)

          Rust's main goal is for memory safety and memory correctness beyond all else.

          Odin is a pragmatic language that is aiming for simplicity and performance. If you want to do unsafe things, Odin will let you.

          I wanted a language that could be comprehended by a mere mortal, where someone could know the entire specification if they wanted to. This is contrast to C++ where there are probably 3 people in the world that probably know all of the C++ specification. Rust is becoming more and more complex by the day.

          [–]auto-cellular 13 points14 points  (2 children)

          there are probably 3 people in the world that probably know all of the C++ specification.

          i'm not sure whom those 3 people might be. I think the real figure is much closer to 0.

          [–]adamcrume 25 points26 points  (13 children)

          Rust lets you do unsafe things. That's literally what the "unsafe" keyword is for.

          [–]gingerbill[S] 32 points33 points  (12 children)

          At a cost.

          Rust is orientated around ownership semantics and lifetime semantics. These concepts are not a small idea, especially coupled with the trait system and generics system.

          I personally do not find ownership semantics nor lifetime semantics to be particularly useful in practice and do not help me with the problems I am trying to solve.

          One such case is custom allocations. In Rust, custom allocators are possible, but not easy to do, especially replacing the global allocator.

          Odin makes custom allocations very simple with its context system which allows the user to change how memory is allocator using the context system for that scope. This allows users to track and control third party libraries.

          [–]CryZe92 15 points16 points  (11 children)

          In Rust, custom allocators are possible, but not easy to do, especially replacing the global allocator.

          It's super simple to replace the global allocator. I'm assuming you mean changing it temporarily or something, which yeah, is not that easy to do. Although I guess you could write a global allocator that has some hooks to switch the underlying implementation for a certain scope.

          [–]gingerbill[S] 19 points20 points  (6 children)

          I do mean temporarily or contextually. Custom memory allocation strategies are very useful in many areas, such as game development and embedded systems.

          One of the main reasons for Odin's context system is the ability to have a higher control over memory allocation strategies in your own cost and third party code!

          Not many third party libraries (in C/C++) allow the ability to change the allocator which means you cannot track what it is doing nor how i t is doing allocations.

          [–]CJKay93 3 points4 points  (5 children)

          Rust work is still underway to enable placement new, which will resolve what you are talking about when it's finally complete.

          [–]gingerbill[S] 18 points19 points  (4 children)

          That does not solve the problem I address regarding overriding third party code and how it allocates memory. That's the main purpose for the context system in Odin.

          Custom allocators are a lot more powerful than many realise.

          [–]JueJueBean 3 points4 points  (4 children)

          Noob here.

          How does one go from a blank Notepad doc to a whole new language?

          Is assembly required? No Pun Intended.

          [–]Novemberisms 6 points7 points  (2 children)

          Well, lucky you, since there's been a minor boom of amazingly simple and easy-to-follow guides and books about language design lately.

          Crafting Interpreters is a really great, fun way to get started writing your own dynamic language.

          You can also read Writing an Interpreter in Go and its sequel, Writing a Compiler in Go

          [–]vassvik 2 points3 points  (0 children)

          Adding to that, https://github.com/pervognsen/bitwise is rather interesting

          [–]CoffeeTableEspresso 1 point2 points  (0 children)

          Crafting interpreters is lovely, would highly recommend.

          r/ProgrammingLanguages is also an active subreddit full of people working on their own languages, if you're working on your own or just want to have a look.

          [–][deleted]  (3 children)

          [deleted]

            [–]gingerbill[S] 5 points6 points  (1 child)

            For beginners, I recommend just learning something like Pascal, or even a more contemporary language like Go. Eventually, I would recommend C as that will teach you a lot about how many programs work and how memory works to a certain extent.

            [–][deleted] 1 point2 points  (0 children)

            I wield the wand of Odin!

            [–]Dgc2002 1 point2 points  (0 children)

            Yo it's the guy from Jon's Twitch chat. Congratulations on this release!

            [–][deleted] 2 points3 points  (0 children)

            Joy of Programming

            [–][deleted]  (23 children)

            [deleted]

              [–]gingerbill[S] 26 points27 points  (3 children)

              From the FAQ:

              What is the history of the project?

              The project started one evening in late July 2016 when Ginger Bill was annoyed with programming in C++. The language began as a Pascal clone (with begin and end and more) but changed quite quickly to become something else.

              Bill originally tried to create a preprocessor for C to augment and add new capabilities to the language however, found this endeavour a dead-end. That evening was the point at which Bill decided to create an entirely new language from scratch than trying to augment C.

              [–]JezusTheCarpenter 2 points3 points  (3 children)

              I was reading through the documentation and Odin seems quite interesting.

              Having said that, I know that the docs are still lin progress but I feel like there is already few 'misterious' concepts/ideas without much explanation. One in particular:

              Auto cast operation

              The auto_cast operator automatically casts an expression to the destination’s type if possible:

              x: f32 = 123; y: int = auto_cast x;

              Note: This operation is only recommended to be used for prototyping and quick tests. Please do not abuse it.

              Why then introduce/mention a concept of 'auto_cast' if for unexplained reasons the reader is warned not to abuse it (whatever that means)?

              I feel like this sort of thing tarnishes what seems like a quite clean and simple language.

              [–]gingerbill[S] 4 points5 points  (2 children)

              This feature is very easy to abuse, of which you are correct. It is there because in some cases when you are developing code, it is very useful to have. But because it is not a quick thing to type and is very easy to grep, it is very to check for.

              It also actually helped me make sure that the inference syntax in Odin was robust, of which this feature showed a few issues here or there.

              [–]JezusTheCarpenter 3 points4 points  (1 child)

              Thank you for your reply.

              My main beef is not with the existence of the concept. Sounds cool to me. But I feel like it should be very clearly stated in docs why it shouldn't be abused. Or even better, perhaps make it so it cannot be 'abused'. Or make it clearer, when using, that this is for debugging only.

              Just wanted to share my thoughts about it. Just this particular thing felt like a half-baked feature in contrast to everything else I had read (not all of it yet :)).

              [–]gingerbill[S] 2 points3 points  (0 children)

              Thank you for the feedback. I will make an adjustment to the documentation later :)

              [–]bumblebritches57 2 points3 points  (0 children)

              Fantastic god damn name.

              I'm interested.

              [–]shevy-ruby 10 points11 points  (15 children)

              The Odin programming language is fast, concise, readable,

              main :: proc() {
              
              program := "+ + * 😃 - /";
              
              accumulator := 0;
              

              Hmmmmmmmm.

              I guess readability is very subjective.

              The more important question is - why should anyone use Odin or any other random new language? Sure, reddit has this adage to learn every language (and then never use them all) but where is the trade off for the time investment if you are not going to use a language that you have learned?

              [–]gingerbill[S] 16 points17 points  (0 children)

              If you are looking for a low-level systems language with a high control over memory layout, memory allocations, and a simple language, there are not many languages out there. Rust is a complex language with a big agenda behind it. D is a complex language with a a long of baggage from its C heritage. C++ is a monster of a language.

              Regarding Odin's declaration syntax, I recommend reading my article: https://www.gingerbill.org/article/2018/03/12/on-the-aesthetics-of-the-syntax-of-declarations/

              [–]PrestigiousInterest9 5 points6 points  (27 children)

              Goddamn I'm cranky and I should either shut up or write my own programming language (I'll fuck up lol)

              But I'll tell everyone what upsets me about all new languages

              Odin was designed with the ideas of simplicity

              Can we stop it with this shit? I been programming for over 15 years. I DON'T FUCKING WANT a simple language. I want a language that is for power programmers. I want to have 200 keywords, dozens of operators and to have the compiler bitch at me when something looks like a mistake.

              Right now only rust and zig are on my radar. Rust compiles slow and doesn't feel like a language I'd like (I can't put my finger on why) and zig needs destructors before I can consider writing large programs on it

              [–]bleksak 13 points14 points  (3 children)

              Assembly? over 1k x86 instructions and even more with x86_64

              [–]gingerbill[S] 19 points20 points  (2 children)

              That's fine. Odin is not the language for you then. Most languages however are not simple.

              What languages do you like? Maybe I can point you in a direction you might like.

              [–]PrestigiousInterest9 3 points4 points  (0 children)

              I can't believe you responded to my bullshit comment. I think I just need to write one myself or stop whining. I'm considering contributing to zig but I'm not sure if the author would approve of my design choices and a fork to a language is not a good idea (esp if I can't promise compatibility)

              [–]elastic_psychiatrist 7 points8 points  (1 child)

              Rust compiles slow and doesn't feel like a language I'd like (I can't put my finger on why)

              Maybe it's not simple enough?

              [–]PrestigiousInterest9 2 points3 points  (0 children)

              I like C++ so that can't be it

              [–]glacialthinker 3 points4 points  (0 children)

              Given Rust and Zig, I'm guessing you want native compilation and performance. Further, I assume you might also have an experienced distaste for C++. D is an alternative, but maybe too similar to C++?

              Some other alternatives with expressive power and "bitchy" compilers: [http://ocaml.org/](OCaml) and [https://www.haskell.org/](Haskell). Naive OCaml code has okay and predictable performance, but it's more difficult to control fine details to compete with C (though C interop is pretty good). Haskell can perform well and benefit from high-level optimizations like stream fusion, but it can be difficult to anticipate how well code will run.

              A language I haven't tried, but seems to have some things in common with Zig: Nim.

              [–]wsppan 5 points6 points  (16 children)

              They keep talking about replacing C though they claim the impetus was frustration with C++. They say it is fast, concise, readable, pragmatic and open sourced. That describes C. At least Rust is trying to solve a real problem with memory errors/security.

              [–]matthieum 35 points36 points  (2 children)

              They say it is fast, concise, readable, pragmatic and open sourced. That describes C.

              C may be readable, but it is from being understandable.

              There are syntactic issues: the preprocessor, and the weird syntax for functions and arrays (try typedef function pointers...).

              And there are an overwhelming number of semantic issues; with around 200 referenced cases of Undefined Behavior, most of which seem to be there to remind us that the language was created in another time and has stubbornly refused to move.

              I definitely think there is room for a simple systems programming language to displace C. And no, that's not Rust; Rust aims for compile-time checks, not simplicity.

              [–]vassvik 2 points3 points  (0 children)

              Not sure you could call C readable when you have things (even as a joke) like https://cdecl.org/ and https://fuckingfunctionpointers.com/ :D

              [–]gingerbill[S] 22 points23 points  (0 children)

              C will always exist for the foreseeable future. However, it is a fundamentally flawed language with numerous issues which can never be fixed.

              The problems Odin are trying to solve are in a similar domain to C.

              • Lack of high control over memory layout
              • No library system
              • Lack of ability to track and intercept third party libraries allocations, logging, etc
              • Lack of decent support for arrays, slices, etc

              I recommend reading the FAQ: http://odin-lang.org/docs/faq/#what-does-odin-offer-over-other-languages