Hare clearly isn't like that: it's _actually_ aimed at (FOSS) C programmers, almost stubbornly so, and isn't going to appeal to many others. But for those people I can see C-with-tagged-unions being an improvement, and there's value in finding the minimal diff that makes a language better.
[1] Remember when Go called itself a "systems programming language"? Neither community seems to use this phrase any more, though.
What I like about go is that I can go full unsafe.Pointer if i want to, and do whatever I want.
The other thing I really like, is that they did such a good job discouraging it that i frequently hear people complain about go having pointers but not even letting you have fun with them.
The problem isn't that go doesn't give you enough control, the problem is that it's garbage collected. And you'd need to work around the GC. It's doable and people have done it though. Good idea? Maybe not.
Still waiting for someone to make "go but with ownership and borrow checker"
I'm no a systems programmer unless you count hobby microcontroller projects, but my understanding is that, when a systems programmer is talking about control, they tend to be talking first and foremost about keeping tight limits on memory usage. Pointers and suchlike just happen to be key tools that help you do that.
https://www.withsecure.com/en/solutions/innovative-security-...
That would have interested me more a few years ago, but I'm deeply invested in Rust these days.
Is that all you'd change about Go? One of the reasons I moved was the error handling and lack of generics. Go has fixed the latter, but I can't stand not having Result<> and Option<> these days. The '?' is awesome too.
No, go has plenty of warts, like every language (ever formatted a date in go?). I just don't like kitchen sink languages.
Leaving aside the GC, until Go has a real FFI it's hard to to imagine it being a really great fit for systems programming when the systems are all not written in Go.
I’m not bashing Go though. I appreciate the focus on readability among other things. It’s a fine language for the use cases it was actually designed for, like pushing petabytes of ad data to serving clusters all around the world with acceptable latency and reliability.
I guess the Genera, Xerox PARC, ETHZ, Microsoft folks are borderline dishonest.
Writing compilers is not systems programming in the sense that it requires a systems programming language, no. One could easily write a C compiler in Ruby, but we don't consider Ruby to be a systems programming language.
Thus, obviously, Go, despite not being a systems programming language, could be used to write the compiler for a systems programming language. I guess that is what Tamago is? I'm not going to read through the source to find out and the web page you linked is boring marketing copy.
TamaGo is a bare metal runtime for unikernels, whose main use is a commercial product for secure USB keys, sold by F-Secure.
Back on my youth, writing compilers was considered systems programming, in parity with kernel drivers, how things change.
I guess writing userspace drivers in hybrid kernels is also not considered systems programming.
Possibly related, building against foreign objects and manually setting up the FFI call: https://words.filippo.io/rustgo/.
What was good for C while it was gaining adoption, surely is good enough for Go.
Wouldn’t this be just a lesser version of rust then? If someone makes a new language and wants it to catch on, it needs new ideas. Not just nice simple syntax mixed with something someone else is already doing.
That depends if you consider C++ an upgrade over C :)
Many flamewars have been had on this topic and i think it's just a matter of personal taste.
I'm firmly in the less is more camp.
Are you saying the reason Rust is now being integrated into the Kernel instead of Golang is because of the success of evangelists, not because of the merit of the language itself?
I'm not involved in Kernel development myself, but if I was, I'd see your statement as a big hit in the face that we don't know what we're doing, if they (Kernel developers) are being sold to use Rust because of marketing, not because of the value of the language.
For example, the arguments against namespaces and function overloading, high context dependency, easy of understanding and in favour of C's simplicity in general.
My guess (it's just a guess) is that his position has shifted over time to consider a higher-abstraction, higher-complexity language, as development methods and the complexity and professionalising of the kernel have changed since then.
The person you’re replying to is either deeply misinformed or trolling
You see how parties completely unrelated to the fight got Linus ousted? That was not based on technical merit, it was due to the changing tide regarding outcomes when people are offended/mistreated. Rust has significant overlap with the community that gave way to this, don't think it is 100% open arms and welcomes, because that is not the case.
Every day we stray further from God.
Compare and contrast Rust, where the code I write will usually just work. I don't need to be extra careful with it because the compiler is strict. You can say that this is indicative of some flaw in my character or whatever, but, uh, I don't care.
Rust for Linux relies on the fact that Rust is deliberately structured in layers so that the bottom layer doesn't need that infrastructure, this was needed to make embedded Rust practical, but it's also important for Linux. Actually, Linux needs even more than Rust had initially, but that's driven further improvements to Rust itself.
You could add a layer to do all this lifting (that's what e.g. a Java OS does) but that's not going to fly in Linux, which is one reason why Go for Linux isn't a thing whereas Rust for Linux is.
What does that mean? Isn't GC a fundamental part of Go?
OTOH, if the differences are minimal, then the benefits are likely to be correspondingly minimal. And either way, the compiler/interpreter for a relatively new language will by definition be much less battle-tested.
Practically speaking, I think if a new language is going to compete with C, it needs to offer more than a few incremental improvements.
A lot of so called "modern" languages make a choice for you. Here is a hash map, over there is a class, have a tuple, set, etc. And they all have a specific way to be used.
In implementing all that, many languages lose on flexibility while gaining general utility. Hare seems to go in the opposite direction, one that makes programmers think hard about the solutions to their problems.
And that is, IMHO, a good thing.
Maybe I would come up with something like this if I only ever worked on Linux software using C, but outside those niches these choices seem weird.
You can declare your language feature complete sooner
There's a reason we call it "dependency hell" and not "happy fun fussing with dependency version conflicts among projects that are completely unrelated except that you happen to be using the same computer to work on them time."
What I keep daydreaming of is a package manager that resolves and download packages, but doesn't automatically grab transitive dependencies. I don't even want it saying, "Hey, we need to grab these 15 other ones, too, is that OK?" I don't want to hide the pain of huge dependency graphs like that; I want to feel it acutely. Give me an error message saying, "Oops I couldn't add FancyPackage because it depends on X, Y and Z transitive dependencies," and send me on a fetch quest. And I want the whole community around the language I'm working in to feel it acutely like that. That way we're all in the same boat, and collectively incentivized not to create the problem in the first place.
Now, keeping your language design stable and backward-compatible is a no brainer. Given that, it's possible to handle "dependency hells" simply by building from source.
Hare is designed to be ultra conservative, so you don't have to worry about dependency hells. Features are in code, not builtin into the language.
It is a win-win situation.
If I'm writing for a proprietary OS, that's probably Windows or OS X. Both of which give me a more stable target to aim at when it comes to what dependencies I can expect.
If I'm writing for an open source OS, that's probably some flavor of Linux. But which flavor? And which package manager does it use? And do they support all the dependencies I need, in the versions I need? Without pulling non-standard package repositories into the mix?
When open source software has difficulty working on proprietary OSes, I think it's usually not because of the package manager. More often it's because of something like a glibc dependency. At which point the domain of support isn't really "open source OSes", it's usually something more like "glibc-based linux distributions."
Hare is a systems programming language. What kind of a systems programmer doesn't know how to build from source?
Hare does the smart thing - it decouples the library distribution model from the language.
After all, it's the programmers job to make sure that distribution and packaging of his/her library is as simple as possible.
I think that Hare's workflow and usecase encourages having very few or no dependencies.
That means, in most cases, you should just be able to download a project's source, build and use it right away.
Many Hare programs will not need to have dependencies at all. We encourage a more conservative approach to dependencies than is common in many modern languages such as Cargo, PyPI, npm, Go, etc. Even dependency-heavy Hare projects will not have hundreds of dependencies, but maybe dozens at most. Think more C, not Node.
I can definitely see the problems with the Node "explosion of modules" approach, but if we're looking at fixing issues with C then IMO "everyone implementing their own data structures and not always with the care and attention they deserve" is right up there with things like lack of proper arrays/strings and poor null handling.
It seems like it ought to be possible to find a middle ground where dependencies are easy to find, install, update and integrate with a standardised build system, but where there is a cultural norm of being conscious of dependency size and not using micro-dependencies
A really common optimization is to replace a linear scan on a list with a hash table. In most languages, that is a trivial step to do, which means that it gets done.
There isn't any overhead.
With hare, you just blew your complexity budget on this thing.
And for the record, Hare does have built-in growable slices, so linked lists are pretty rare in Hare. They exist in a few niche situations -- I only ever wrote a Hare program with linked lists once.
It seems you can grow them by appending, so they aren't like Rust's slice which is non-owning or a typical array which can't grow.
I suspect a Linked List is actually almost never the right shape for a data structure in Hare, because you should just use these vectors to do that.
The two actual rationales for Linked List in the 21st century (other than "I was writing C and I don't know what I'm doing") are: 1. Concurrency, Lock Free and sometimes even Wait Free algorithms are practical for Linked List and the other costs pale into comparison on highly contended data structures and 2. I'm doing some serious acrobatics with huge lists, I constantly perform split/ merge operations and so those being cheap is crucial. Hare doesn't have concurrency, and nobody should attempt such acrobatics in a language this dangerous.
Also, did you use a nullable pointers to represent the next node element in the linked list? Or a tagged union of ( ptr | void)? Or something else?
https://git.sr.ht/~yerinalexey/carrot/tree/master/item/conso...
Went with nullable pointer types, which is also a rarely used feature in Hare.
maps/sets are also fundamentally building blocks for a lot of algorthms and structures, not having them makes it WAY harder to implement them. actually potential impossible as performance can easily degrade to a point where it's unusable when you use O(n) (or worse) lookups instead of O(1) ones.
this is not a case of premature optimizations but of missing fundamental building blocks
and if you don't want genetics, ok, do it like go did initially make the map special language thingy.
But that's not "modern" applications, which often deal with a ton of data structures. C applications that do so usually have a few "template headers" lying around (indeed, certain operating systems ship with them), though one of the most frequently used data structures in C is of course the intrusive linked list. Which is not a good data structure to use in most cases. Why is it used so much in C? Because it is easiest to implement. Why does that matter? Because C makes implementing generic data structures tedious. Is it a good idea to replicate that model?
qed.