I don't really "get" the sweet-spot being targeted here. You don't get channels, goroutines, or gc, so aside from syntax and spatial memory safety you're not really inheriting much from Go. There is also no pathway to integrate with existing Go libraries.
Spatial memory safety is nice but it's the temporal safety that worries me most, in nontrivial C codebases.
Go is my most productive language, but it is the worst for some of the usecases I want to use it for due to goroutines and GC pauses and things like that.
I learned C and programming when I was a middle school math nerd and so my understanding of functions was colored by the algebraic definition of a single value function. This led to me writing my code in a more functional paradigm than an object oriented paradigm. I struggled to learn Java. I struggled in programming class when we made the switch from VB6 to vb.net because I didn’t really understand object oriented programming.
I find go’s procedural nature to be the best language for my understanding of programming with functions. The way the object oriented code is possible, but not required allows me to build types and objects that I can compose and use as I understand them, not the way that object oriented, inheritance, and polymorphism requires me to subclass.
I recently have had the idea for a project and I found the perfect ECS library that would allow me to compose my entities and components the way I do in Go, but it does not interface cleanly with Cgo either in runtime overhead or development overhead.
The official bindings for it are rust, c, c#, zig, lua, and clojure.
This would allow me to use it by writing Go code that calls it natively like C.
I’m not concerned about not getting to use Go libraries. I believe in Roll Your Own and always had to roll my own when I was learning C. Go’s stdlib is tight and lends itself to RYO really well.
I was curious how defer is implemented. `defer` in Go is famously function-scoped, not lexically-scoped. This means that the number of actively-deferred statements is unbounded, which implies heap allocation.
The answer is that Solod breaks with Go semantics here: it just makes defer block-scoped (and unavailable in for/if blocks, which I don't quite get).
As long as you exclude defers in a loop, this can be done statically: count the maximum number of defers in a function, and add an array of that size + counter at the function entrance. That would make it a strict subset.
The claim that no goroutines makes this pointless isn't quite right. Migrated 50 services off Docker Compose using Nomad and half of them had zero concurrency needs. A safe Go-syntax C target is actually useful for that layer.
You sure they weren't just using http or something and thus the concurrency was effectively hidden by the library? Almost any services that takes requests of any kind uses goroutines extensively.
> So supports structs, methods, interfaces, slices, multiple returns, and defer.
> To keep things simple, there are no channels, goroutines, closures, or generics.
Sure, slices and multiple return values are nice, but it's not what makes Go good. When people think about Go they usually think about channels and goroutines. YMMV
While I do kind of get what the appeal and target audience is supposed to be, I absolutely don't get why you'd choose a subset and still have it behave differently than the Go counterpart. For me that destroys the whole purpose of the project.
Translating code to C usually results in some nearly unreadable code. I submit the C++ to C translator, cfront, as evidence. I've looked into using C as a target backend now and then, but always "noped" out of it.
I was pleasantly surprised to discover, however, that C code can be readily translated to D.
I'm reminded of the tools in programs like Ghidra or IDA which can take assembly code and convert it into a C-like language. If you could create one of those tools that also takes in the source file so that it names things somewhat reasonably, could you create an anything to C translator? As long as the original file compiles to assembly, that is
As a Go developer I would use this unless...I would have to build the std libraries myself. Now I also wonder how this compares with tinyGo. Why would you pick one over the other...
That is an interesting project, which i have been following for a while. Unfortunately, progress has slowed a lot recently. I hope development picks up…and that the author chooses a different name for the language.
32 comments
[ 1.9 ms ] story [ 57.6 ms ] threadSpatial memory safety is nice but it's the temporal safety that worries me most, in nontrivial C codebases.
Go is my most productive language, but it is the worst for some of the usecases I want to use it for due to goroutines and GC pauses and things like that.
I learned C and programming when I was a middle school math nerd and so my understanding of functions was colored by the algebraic definition of a single value function. This led to me writing my code in a more functional paradigm than an object oriented paradigm. I struggled to learn Java. I struggled in programming class when we made the switch from VB6 to vb.net because I didn’t really understand object oriented programming.
I find go’s procedural nature to be the best language for my understanding of programming with functions. The way the object oriented code is possible, but not required allows me to build types and objects that I can compose and use as I understand them, not the way that object oriented, inheritance, and polymorphism requires me to subclass.
I recently have had the idea for a project and I found the perfect ECS library that would allow me to compose my entities and components the way I do in Go, but it does not interface cleanly with Cgo either in runtime overhead or development overhead.
The official bindings for it are rust, c, c#, zig, lua, and clojure.
This would allow me to use it by writing Go code that calls it natively like C.
I’m not concerned about not getting to use Go libraries. I believe in Roll Your Own and always had to roll my own when I was learning C. Go’s stdlib is tight and lends itself to RYO really well.
I wonder if it could be integrated with https://github.com/tidwall/neco, which has Go-like coroutines, channels, and synchronization methods.
[1]: https://codapi.org/
The answer is that Solod breaks with Go semantics here: it just makes defer block-scoped (and unavailable in for/if blocks, which I don't quite get).
https://github.com/solod-dev/solod/blob/main/doc/spec.md#def...
In C you can allocate dynamically on the stack using alloca or a VLA.
> To keep things simple, there are no channels, goroutines, closures, or generics.
Sure, slices and multiple return values are nice, but it's not what makes Go good. When people think about Go they usually think about channels and goroutines. YMMV
While I do kind of get what the appeal and target audience is supposed to be, I absolutely don't get why you'd choose a subset and still have it behave differently than the Go counterpart. For me that destroys the whole purpose of the project.
So no go error handling?
Not a choice I would have made.Sure when I started Go there were Go routines plastered everywhere. And now I think harder: “do I really need a go routine here?”
I was pleasantly surprised to discover, however, that C code can be readily translated to D.
It’s a mix of go and rust syntax that translates to C