Helix: A Modern, High-Performance Language
41 points by 90s_dev 3 days ago | 58 comments- munificent 3 days agoI don't understand how the docs say:
"Non-Nullable Types by Default: In Helix, all types are non-nullable by default, significantly reducing the risk of null-pointer errors. Helix uses a novel approach to nullable types - Questionable Types, which allows for more explicit handling of null or panicking values."
But then when you look at questionable types, it says:
"You can use a questionable type like a regular variable. If you use it in a context where a non-questionable type is required, Helix implicitly checks its validity: If the value is valid, it proceeds. If the value is null or an error, the program stops with a crash."
Is that not exactly the same behavior that Java has?
- evertedsphere 3 days agothe docs were clearly not written by a human, so proceeding from the expectation of global coherence, or that of adherence to principles that would be implied to a human being reading this in a certain context, is likely to end up being a waste of time
- lostdog 3 days ago"Comprehensive Error Handling: Helix's error handling system is novel to helix, it allows for either complete error handling or a more pythonic approach to error handling, this allows for more control over how errors are handled in Helix."
Wow, these really do seem to be LLM written, and I would guess ChatGPT. This long README has a bunch of generic, redundant statements over and over again.
- 90s_dev 3 days agoWait, was this language guided by AI???
- fwip 3 days agoFrom my personal judgment: definitely using AI for the code & commits, probably for the documentation, no idea about the design. For instance, no human would write this commit message, with the preformatted-code-block:
https://github.com/helixlang/helix-lang/commit/4d949efd42b8d...
- ze7111 2 days agoHey I'm on of the devs; No, the code is not by AI: the current compiler and , corelib's code, the thought process and language design is all human, AI would produce slop in that case, however, English isn't our first language, so things like README's, Docs and such, had the following process, we wrote an initial draft, with broken English not cohesive at all - but, the content is factual, then sent it to ChatGPT to improve it, did it use buzzwords and such - yes, but at the time, with our level of English it did seem really good, looking back now it does seem really bad, but Commit messages are done using GitLens Commit Message Generator - simply because I was too lazy to write each and every commit message, Moving forward, We have already started to rewrite the README and the Docs, by hand, we will first commit that, then do a revision with AI, while maintaining the tone and formality, only improving grammar and punctuation. AI is a really good tool when it comes to improving English and communication, however I do stand with the fact code should NOT be written by AI.
- fwip 3 days ago
- lostdog 3 days ago
- grncdr 3 days agoI believe it’s slightly different in that I can declare a value (or parameter) of type T and know that it can’t be null/invalid.
Consider this Java method:
To get the same behavior in Helix, one would have to declare the parameter type as “Bar?”. If the parameter type is plain “Bar”, callers can still pass you a “Bar?”, but presumably you’d get an NPE at the call site and not somewhere further down the stack.void frobnicate(bar Bar) { // is bar null? Who knows? }
I’ve never heard of this language before today and don’t have an opinion on it, but I do find the Questionable Types interesting: sort of collapsing Option and Result into one very concise notation.
- munificent 2 days agoAh, I guess that's a good point.
You get safety for the non-questionable types. But it seems like if you're going to have questionable types, you're better off not letting users silently treat them as if they aren't questionable and then risk crashing at runtime.
- dudeinjapan 2 days agoThis is a let-down, the user expectation here is compile-time checking (not runtime NPEs)
- munificent 2 days ago
- 90s_dev 3 days agoOh hey you're the guy who made the crafting interpreters book, that was really helpful when I went through my wanting to make a langauge phase, thanks for making a great book.
Also yeah seems like they reinvented null pointer crashes but with extra steps.
- serial_dev 3 days agoIt’s a NPE, but it passed through vibe coding.
- ze7111 2 days agoHey, I'm one of the dev's; English isn't any of our first language, The Code is all human written (at least the bootstrap compiler is mostly by me), but the documentation README, and parts like commit messages and such are written by ChatGPT or GitLens's AI Commit Message Generator. But on another note the docs are quite outdated, We only posted on reddit to get an opinion, didn't except it to reach other places as well... But we are now working on rewriting the docs completely. Without AI initially but then with AI to make the English better, If anyone notices any weird things in there, please either do a PR or let us know to change it...
But also yes passing a null value into a non-questionable would lead to NPE however if the type has a questionable operator then that function would be used (like for strings, a questionable null string type is just a blank string, in which case using it with or without questionable doesn't make a difference).
- ze7111 2 days ago
- setopt 3 days agoNot obvious what is novel either. Languages like Haskell have had alternatives like the Maybe monad for a long time.
- evertedsphere 3 days ago
- snovymgodym 3 days agoThis is cool, I think the most novel/unique aspect is the advanced memory tracking: https://github.com/helixlang/helix-lang?tab=readme-ov-file#a...
Still, I don't really see this going anywhere. There are already so many "slightly better C++" languages out there, e.g. D, cppfront/cpp2, Carbon, Zig and they pretty much all don't see wider adoption for the same reason. No matter how simple or ergonomic the interop with C++ is, the switching cost is still high and the benefit tends to be marginal. Almost all of them either include garbage collection or don't fully guarantee memory safety. Choosing a restricted subset of C++ and an opinionated, enforced linter & static analyzer goes a long way and gets you most of the benefits of these new languages, so organizations tend to just do that.
The exception is Rust, because in spite of all its downsides it has the killer feature of guaranteed memory safety without garbage collection, so that's the one seeing constantly increasing institutional support.
- koakuma-chan 3 days agoWhat happened to Carbon? I completely forgot about it.
- andrewl-hn 3 days agoTheir first milestone is due later this year: to show the 2-way C++ interop.
Their second milestone should show memory safety features, and AFAIK it comes up a year or two later.
These milestones will produce technology demonstrators - so there's no expectations people would be using Carbon for anything beyond small demos and maybe check if it can be integrated with their existing C++ codebases.
Then they will try to package up the language and tooling around it with these two flagship features. This is where they expect some people to use the language for real. The language will only support a subset of C++ (they haven't decided what exactly it should include), and they mentioned Rust-like subdivision into "unsafe" and "safe" Carbon. To me this all looks like even after those milestones it may take a while.
Also, while Google folks are hopeful they also donated billions to Rust to improve C++ interoperability there, too. They don't bet on one language only but rather see multiple of them develop and spread.
So, tldr: it's years and years away.
- mlinksva 3 days ago*million rather than billions https://rustfoundation.org/media/google-contributes-1m-to-ru... but sound analysis as far as I can tell.
- mlinksva 3 days ago
- 90s_dev 3 days agoAs I looked up Carbon over the past week, every comment on it was always that nobody uses it because it's going to be eventually https://killedbygoogle.com/
- ioasuncvinvaer 3 days agoIt seems to be in active development though? And Google also made go which very much alive.
- ioasuncvinvaer 3 days ago
- andrewl-hn 3 days ago
- rmorey 3 days agofwiw (and I am not an expert) in my understanding, Swift also has guaranteed memory safety without a GC (using automatic reference counting). not sure how it compares to Rust in that aspect
- ModernMech 3 days agoI'm a big fan of Rust and I also use Swift as part of my job. In terms of memory safety, Rust has a better story in that it will tell you of type problems pretty much upfront. The whole "Rust compile time takes forever" is only half true, because type checking happens pretty quickly. You're never left waiting for long to find out your types are wrong. The long compile happens at codegen phase, after type checking, so once it starts you know it'll finish successfully (unless there's a link error at the very end).
With Swift, that's not true. Sometimes you can wait for a while for the compiler to churn before it bails and tells you it can't fully infer types. As a Rust user, this is entirely unacceptable.
I would have to say, while I don't thoroughly dislike Swift, I do thoroughly dislike Xcode and the Apple ecosystem. The fact that Swift was tied so closely to iOS development for so long means it's not a language that people generally reach for. It feels more like ObjectiveC++ and a facet of the Apple ecosystem as a vehicle into iOS development.
People say that Rust's killer feature is the memory safety, but for me it's always been the ergonomics. Cargo and the painless dependency process is the real killer feature. Swift just doesn't have the same appeal, and that they are slowly getting there is a testament to Rust having already cracked the code; Swift only went fully cross platform (Windows+Linux+Mac) in 2020, so there's a lot of reputation as an Apple language to undo, as well as a lot of ground to catch up on. It's interesting to note that the ground they have to make up is pretty much the path that Rust blazed. So for a lot of the target audience of Swift, the question isn't "why Swift?", it's "why not Rust?". Really, they only good answer for Swift right now is "my target platform Apple."
- frizlab 2 days ago> Why not Rust?
For me the answer is: Ergonomics.
Swift is, IMHO, much more readable and easier to grasp than rust. You don’t have to understand low-level concepts, but can go there if you need performance.
- frizlab 2 days ago
- corank 3 days agoThe point about Rust is to avoid any extra runtime cost by statically enforcing a set of rules (borrow checking) on reference use that are sufficient to guarantee memory safety. It also has ARC but it's reserved only for cases where those rules are too restrictive.
- steveklabnik 2 days agoThe thing is, Swift has automatic reference counting, and Rust has an atomic reference counted type. Their “ARC”s are related but different.
- steveklabnik 2 days ago
- ModernMech 3 days ago
- koakuma-chan 3 days ago
- JadeNB 3 days agoI know that there's no such thing as a unique name, but the fact that https://helix-editor.com/ is a living project, first released in May 2021, might mean that using "Helix" for this project, first released in November 2024, isn't the best choice of name. Or at least it might be worth a disclaimer in the readme!
- dudeinjapan 3 days agoIf one uses Helix editor to code in Helix lang does that make it Double Helix? Asking for a friend.
- serial_dev 3 days agoI thought the team behind the Helix editor came up with a programming language. Even the logo is so similar. A disclaimer would be wise.
- dudeinjapan 3 days ago
- rich_sasha 3 days agoIt's the shopping list of dreams. As fast as it gets. Borrow checker, but friendlier than "other languages' borrow checkers" (I wonder which other ones they mean). Readable. What's not to like. I look forward to v0.1
Is anything known about the key developers? I would imagine such a project needs firepower. Rust had Mozilla's heft from the get-go. Most successful languages have another big sponsor.
- ModernMech 3 days agoI always say this, but my opinion when it comes to bootstrapping a compiler is that it's generally a waste of time unless your language is meant for writing compilers.
While dogfooding your language is a great to stress test it, you want to make sure you're testing the right stresses -- the ones your target users will encounter. A compiler may be that thing, but chances are it is not; most people do not write nor do they aspire to write compilers. So showing off that you've written a compiler in your language doesn't attract users, because they're still left with the question "Okay, well what does it do for me?"
Another reason is that there is an infinite amount of work that goes into writing a compiler. It's really endless, especially for a small team or solo dev. If you try bootstrapping, it means essentially maintaining two compilers until you can fully bootstrap, which may never come. One compiler is really enough work.
The final reason I will say is it takes forever, and puts a total brake on new features, which can really kills project momentum. Writing the first bits of a language can really fly. But when you sit down to bootstrap, it means you're not releasing new features, but redoing everything you've already done. This leads to unfortunate messages like "We’ve now started work on the self-hosted compiler, using the current rudimentary C++-based implementation as a bootstrap.", which followers take to mean "the project is currently in hiatus for the foreseeable future until this background work on the bootstrap compiler is done". This is a critical point in language projects where the bootstrap might never be completed.
When I look at a new language project I always check out the "contributors" section. Whenever I see an initial flurry of activity from one or a few devs, followed by a taper off into nothing, I know the project is in trouble. It seems like maybe this author has hit a wall, and I would be highly suspicious of the bootstrap endeavor causing it.
- ze7111 2 days agoHey, I'm one of the dev's; I do definitely agree with you, while bootstrapping isn't always the best idea and it does take forever, we are doing it for a really simple reason, the project was initially a passion project by me, and then A few friends wanted to jump-in as well and make it a fully fledged thing, so we thought it would be a good idea for me to get the bootstrap compiler completed before moving on to the main compiler, So my bootstrap compiler right now works, its not the best tho riddled with bugs and problems; but its enough to write a compiler with. As to the taper off, We all are working summer internships right now, so the development is definitely slowed down a little, but, we are working on it, albeit slowly for the time-being, but the bootstrap endeavor, isn't causing a stop but rather a slow down also paired with the summer internship, it will pick up back to speed once college starts in Fall...
Our timeline for a early working alpha with the bootstrap is Q1 2026 (or Q2) but no later.
P.S A reason why only I mainly wrote the initial compiler, and also we decided to make a new compiler is since this was a passion project, the code wasn't maintainable AT ALL, I didn't plan on anyone else working on it, the code is really bug prone C++, a lot of lines of code that make 0 sense, and no structure in the codebase. The new compiler however, we are properly structuring it, documenting it, following code guidelines, and working on it as a team as opposed to 1 man writing all the code and the rest of the team only stating ideas.
- ze7111 2 days ago
- hannofcart 3 days ago> Non-Nullable Types by Default
So glad to hear this. I now consider this the single most important requirement when am evaluating a new programming language.
Error handling looks well thought out as well.
Very interested in how the borrow checker logic would shape up.
If this delivers on the promises made, it would pretty much be my dream programming language.
- 90s_dev 3 days agoC has non-nullable types too. Only one type can be null in C, and in that event it signifies an absence of a value of that type.
- freeone3000 3 days agoSure, but practically, that type is used so commonly that such a distinction is useless. Can I get a FILE? I guess I can get a FILE*…
- 90s_dev 3 days agoRight, so check if it's null. In practice, you do it just as often in C as you check for std::nullopt in C++ or std::option::ok in Rust etc.
- 90s_dev 3 days ago
- freeone3000 3 days ago
- 90s_dev 3 days ago
- 90s_dev 3 days agoBest of both worlds of Rust and Zig? C/C++ ABI compatibility? No runtime? Borrow checking with less strictness? Seems too good to be true.
- timeon 3 days ago> Best of both worlds of Rust and Zig
Seems more like something between Swift and unsafe Rust.
- timeon 3 days ago
- sbmthakur 3 days ago> Both Rust and Zig lack comprehensive OOP support, which is essential for certain domains like AI or game development.
Just curious, what benefit OOP offers over other paradigms in AI dev?
- skulk 3 days agoReally cool to see that LSPs are no longer an afterthought, but rather a core part of the compiler. (evidence: https://github.com/helixlang/helix-lang/blob/21ac6a24ba34ca2...)
- johnisgood 3 days ago> Linux is not yet tested, Most development is done on MacOS or Windows, if any issues arise with building on Linux, please open an issue.
That is good to know.
- 44za12 3 days agoBold to announce without finishing the documentation.
- 90s_dev 3 days agoThey didn't announce it, I posted it here out of curiosity to see what other people think about it. I hope they're not very upset about that ':)
- corank 3 days agoI think I saw them sharing it on Reddit earlier
- 90s_dev 3 days agoOh yeah, in fact that's where I saw it and what made me think to post it here. Oops.
- 90s_dev 3 days ago
- ze7111 2 days agoHey I'm on of the devs; We aren't upset at all, this kind of publicity shows us what everyone else really thinks, being critical is a really good thing when it comes to programing, while I do admit, Our Docs is blank and most of the README + current outdated docs are written by AI (after an initial draft by us), and things are not fully polished, we are after all collage students, critical feedback helps us learn more, get better and find ways to improve. Always being complimentary, only boasts the ego and prevents us from really improving...
After reading though everything we've seen posted on here and reddit there's a couple things that keep coming up consistently: AMT - devs want to know more about it Vial - devs want to know more about it Helix the name - everyone thinks it overlaps with the Helix Editor Readme - Looks to generic, Afterall it was put through ChatGPT to make it have good English after a draft... Docs - Outdated and Missing Helix the logo - its too similar to the Helix Editor Our Feature set - devs think its too good to be true. Linux Support - devs think not testing Linux is a dealbreaker.
Addressing the issues: Linux - Issue is we need word and Microsoft apps for college, hence the use of Windows and MacOS, but starting now We will set up WSL to test for Linux as well. AMT - We will add a section in our docs explaining it much more in detail! Vial - Also add a section in the docs explaining it much more in detail! Helix the name - We've kept the name for over a year now, and yes Helix editor has been around longer; We will consider another name, but for the time being we will add a disclaimer. Helix the logo - We will redesign the logo to be truly unique, might take a few weeks but we will change it. Readme - We will rewrite the readme from scratch, would use AI after an initial draft but make the content not seem like trying to market the language instead show the raw technical aspects without buzz words and stuff like that. Docs - Started to rewrite the docs from scratch same thing as the Readme, will post a commit without any AI modifications first. Our Feature set - while it does seem far fetched, we have written down all of our features in MD files (internally) that outline the exact processes that we need to follow, along with the thesis and theory of them, Everything is planed out fully, we just have to implement, while saying this is easier said then done, our goal is to try to make all of the features happen, maybe a year or two down the line it should be complete (or at least a working alpha).
Thank you so much! for all the compliments and criticism, These comments do mean a, lot to us and our team we are all college students, trying really hard to get this working, our coding ability should allow us to make Helix a reality, we are trying to get better at the other aspects, such as marketing, communicating with other devs, listening to feedback, and continuously improving...
- corank 3 days ago
- 90s_dev 3 days ago
- devjab 3 days ago> Lack of OOP Support: Both Rust and Zig lack comprehensive OOP support
To some of us that is a major feature of Rust and Zig, but good luck.
- 3 days ago
- corank 3 days agoI'd love to learn more about how AMT works. How would a doubly linked list work in this language for example?
Does the conversion happen during run-time? Isn't that going to be super expensive?
- ze7111 2 days agoIt depends on the context of the code, its after the optimization pass but before emission of LLVM IR, But in most cases it shouldn't be super expensive, the conversion itself happens at compile time, but the usage is at run-time, it can be turned off entirely, but we need testing to see the actual performance implications. Right now the AMT is written down in an internal MD document, we've figured out the whole theory bit, the implantation comes after we written the error-handler (for compiler side error messages), lexer, pre-processor, parser, symbol table, Optimizer passes, Borrow Checking IR (haven't decided a proper name on it yet for now its just BCIR), and then the AMT, followed by the Emitters. Then the rest of the features follow suite. but we will test each stage individually once their complete and have a proper dataset of numbers to see performance memory usage and other metrics, with proper real world cases (it very well may be slower or not, we don't know yet in theory, there's no immense performance implications at runtime other then a a couple ...ns extra).
- ze7111 2 days ago
- oldpersonintx2 3 days ago[dead]
- auxide 3 days ago[flagged]
- dupdrop 3 days agoSorry for the petty comment, but if you design your language syntax with `x if cond else y` with the condition in the middle like in the Python if-expression syntax, I cannot trust your judgment and we cannot be friends. (from one of the images of code)
I will take an actual look into it later though, seems interesting.
- ze7111 2 days agoHey, I'm one of the dev's; We thought about this ALOT like 4 hour long arguments, we asked a lot of our friends and its was really mixed, some people hated the python style ternary, others loved it, we weren't sure what to choose but the numbers were 38.5% for `<expr> if <cond> else <expr>, 27.25% for `<cond> ? <expr> : <expr>`, and 34.25% for `if <cond> { <expr> } else { <expr }` we did also look at a few other styles like: `if <cond>: <expr> else: <expr>`, but we decided that the python style is the best for a simple reason, its easier for new dev's who want to come into systems programing or writing low level code. If a lot of people do really hate it, we can swap it out before an alpha it would be a really simple AST node parser change...
- dupdrop 1 day agoI don't know if your language is expression based like Rust, but in Rust the nice thing is that it's just the regular if syntax being used as an expression and not some additional special case syntax, which is elegant.
I actually like the Haskell syntax more because it's looks nicer when formatted in multiple lines:
Where in Rust with normal formatting it because 5 whole lines:-- Haskell: -- single line if ... then ... else ... -- multiline if ... then ... else ...
I think the strongest argument for condition-first that's unrelated to "taste" is the fact it is consistent with the order of execution:// Rust: let result = if ... { ... } else { ... }; // or, 4 lines but less common: let result = match ... { true => ..., false => ..., };
I also strongly suggest you look up why Python ended up with the syntax it did. The reasons were not really good and not really applicable to a new language. Maybe my memory is bad because I can't find the source, but I remember one of the justifications was simply that it turned out faster in cpython (the python interpreter) in the test implementation they did.# Python: # you have to read "from the middle out" to read with the order of execution x = a() if b() else c()
I might also consider asking Chris Lattner (Mojo language). They did use that syntax in Mojo, because it is made to be a superset of Python. But I remember hearing him say he really disliked it.
- dupdrop 1 day ago
- goku12 2 days agoI also found the conditional syntax (with the condition in the middle) a bit awkward compared to Rust's or even C's. But there is certainly a common operation. And this is the syntax chosen by the Python language designers.
I'm curious. Why do you think it is bad? What are the possible issues that this style can cause?
- dupdrop 2 days agoI think I only started to really hate it when I had to deal with some Python code where people decided to nest them and made a really hard to read mess where they should have used just a normal if-else chain. A Rust style if-expression would be better IMO, but it was Python code.
On a more basic level, I just don't see any good reason to put the condition in the middle.
Lisp: `(if <cond> <then> <else>)` Haskell: `if <cond> then <then> else <else>` Rust: `if <cond> { <then> } else { <else> }`
All the above read fine and normal. In the python version the order of execution is different then the left-to-right reading order.
It's not like it's a fatal flaw for a language to do it like Python. But it is just silly IMO. My POV is that I actually really like if-expressions, but hate the condition-in-the-middle syntax, so I tend to avoid it unless it's really short. When code changes slightly and becomes longer I'd rather not have to always double take if this now should change to an if-statment or to an expression etc.
- goku12 2 days ago> I think I only started to really hate it when I had to deal with some Python code where people decided to nest them and made a really hard to read mess where they should have used just a normal if-else chain.
Oof! I can see how that can get really messy really fast. Though I wonder how much of it is the language's fault as it is the programmer's. I used to tell my students to avoid trying to be too clever with the source code. Source is meant for humans to read. Leave the cleverness to the interpreter.
> On a more basic level, I just don't see any good reason to put the condition in the middle.
Thinking about it again, I think I understand why the language designers chose that order. They were trying to make it make it more readable by following the structure of the English language. "<Buy a steak> if <the butchers are open>. Otherwise <get some salmon>".
The problem here is that programmers are more accustomed to the natural and somewhat obvious order that every other programming language follows. They also wouldn't have expected some people to abuse it by nesting it.
- goku12 2 days ago
- dupdrop 2 days ago
- ze7111 2 days ago