Earlier quoted context omitted.
Can someone help me understand why enums are needed? They only seem like sugar for reducing a few lines while writing. What cannot be achieved without them or what is really a pain point they solve? Maybe it is hard to have a constant with type information?
The original enum are just enumerated integer constants. What people want "the ability to express enums with an associated value", I think we should invent a new term.
Borgo is a statically typed language that compiles to Go
371–380 of 559 posts
Re: Borgo is a statically typed language that compiles to Go
#372Earlier quoted context omitted.
That's hardly the point. The point is that there is a single format for the language itself and you don't have to argue about spaces vs tabs vs when to line break, whether you want trailing commas and where to put your braces. You can format on save or in a pre commit hook. But that the language has a single canonical format makes it kind of new.
Yes, because there is no one in the room able to configure the formating tool for the whole SCM. A simple settings file set in stone by the CTO, such a hard task to do. The fact that is even a novelty unaware of, only confirms the target group for the language.
Re: Borgo is a statically typed language that compiles to Go
#373Earlier quoted context omitted.
Using an Option instead of a pointer buys you the inability to forget to check for nil. Just need to make sure the Option exposes the internal value only through: func (o Option[Value]) Get() (Value, bool) { return o.value, o.exists } Accessing the value is then forced to look like this: if value, ok := option.Get(); ok { // value is valid } // value is invalid Thus, there's no possibility of an accidental nil pointe…
How is that better than if value != nil { // value is valid } // value is invalid ? Of course, this is often left out, but you can just as easily do: value, _ := option.Get() So this is just not true: > Using an Option instead of a pointer buys you the inability to forget to check for nil.
> Of course, this is often left out, but you can just as easily do:
Unfortunately it gets brought up pretty much every time in these discussions.
Deliberate attempts to circumvent safety are not part of the threat model. The goal is prevention of accidental mistakes. Nothing can ultimately stop you from disabling all safeties, pointing the shotgun at your foot and pulling the trigger.
Re: Borgo is a statically typed language that compiles to Go
#374Earlier quoted context omitted.
Unfortunately, this: const ( Hot Temperature = 0 Cold Temperature = 1 ) Isn't really a good workaround when lacking an enumeration type. The compiler can't complain when you use a value that isn't in the list of enumerations. The compiler can't warn you when your switch statement doesn't handle one of the cases. Refactoring is harder - when you add a new value to the enum, you can't easily find all those places that…
> Isn't really a good workaround when lacking an enumeration type. Enumeration isn't a type, it's a numbering construct. Literally, by dictionary definition. Granted, if you use the Rust definition of enum then it is a type, but that's because it refers to what we in this thread call sum types. Rust doesn't support "true" enums at all. > The compiler can't complain when you use a value that isn't in the list of enume…
No, it isn't, unlike C, in which it is. The C compiler can actually differentiate between an enum with one name and an enum with a different name.
There's no real reason the compiler vendor can't add in warnings when you pass in `myenum_one_t` instead of `myenum_two_t`. They may not be detecting it now, but it's possible to do so because nothing in the C standard says that any enum must be swappable for a different enum.
IOW, the compiler can distinguish between `myenum_one_t` and `myenum_two_t` because there is a type name for those.
Go is different: an integer is an integer, no matter what symbol it is assigned to. The compiler, now and in the future, can not distinguish between the value `10` and `MyConstValue`.
> Just like it isn't in C. You will notice this compiles just fine:
Actually, it doesn't compile "just fine". It warns you: https://www.godbolt.org/z/bn5ffbWKs
That's about as far as you can get from "compiling just fine" without getting to "doesn't compile at all".
And the reason it is able to warn you is because the compiler can detect that you're mixing one `0` value with a different `0` value. And it can detect that, while both are `0`, they're not what the programmer intended, because an enum in C carries with it type information. It's not simply an integer.
It warns you when you pass incorrect enums, even if the two enums you are mixing have identical values. See https://www.godbolt.org/z/eT861ThhE ?
Re: Borgo is a statically typed language that compiles to Go
#375Earlier quoted context omitted.
Most of people who tend to brag about Lisp's (Common Lisp) superiority, never actually used it. It is not as impressive as many legends claim.
Can you name a language that provides more freedoms? I used Lisp as an example for that side of the spectrum because I'm familiar with it, having used it for many years in the past. But maybe there are better examples.
Re: Borgo is a statically typed language that compiles to Go
#376Earlier quoted context omitted.
> Isn't really a good workaround when lacking an enumeration type. Enumeration isn't a type, it's a numbering construct. Literally, by dictionary definition. Granted, if you use the Rust definition of enum then it is a type, but that's because it refers to what we in this thread call sum types. Rust doesn't support "true" enums at all. > The compiler can't complain when you use a value that isn't in the list of enume…
> but all the information you need to perform such analysis is there. No, it isn't, unlike C, in which it is. The C compiler can actually differentiate between an enum with one name and an enum with a different name. There's no real reason the compiler vendor can't add in warnings when you pass in `myenum_one_t` instead of `myenum_two_t`. They may not be detecting it now, but it's possible to do so because nothing in…
Go on. Given:
type E int
const (
A E = iota
B
C
)
enum E {
A,
B,
C
}
What is missing in the first case that wouldn't allow you to perform such static analysis? It has a keyword to identify initialization of an enumerated set (iota), it has an associated type (E) to identify what the enum values are applied to, and it has rules for defining the remaining items in the enumerated set (each subsequent constant inherits the next enum element).That's all C gives you. It provides nothing more. They are exactly the same (syntax aside).
> It warns you
Warnings are not fatal. It compiles just fine. The Go compiler doesn't give warnings of any sort, so naturally it won't do such analysis. But, again, you can use static analysis tools to the same effect. You are probably already using other static analysis tools as there are many other things that are even more useful to be warned about, so why not here as well?
> enum in C carries with it type information.
Just as they do in Go. That's not a property of enums in and of themselves, but there is, indeed, an associated type in both cases. Of course there is. There has to be.
Re: Borgo is a statically typed language that compiles to Go
#377This addresses pretty much all of my least favorite things with writing Go code at work, and I hope--at the very least--the overwhelming positivity (by HN standards -- even considering the typical Rust bias!) of the responses inspires Go maintainers to consider/prioritize some of these features, or renews the authors interest in working on the project (as some have commented, it seems to have gone without activity fo…
I have to disagree. I'm on record here lamenting Go. I've never really enjoyed writing it. When I've had to use it, I've used it. Lately though, I've found a lot more pleasure. And much of that comes from the fact that it does NOT have all these features. The code I write, is going to look like the code written by most other on my team. There's an idiomatic way to write Go, and it doesn't involve those concepts from…
From my experience, things I think Go could really benefit from, like I believe it has benefited from generics:
* A way to implement new interfaces for existing types and type constraints for custom types, like `impl Trait for T`. This would obsolete most uses of reflection in the wild, in a way generics alone haven't. This isn't about syntax, it's about an entirely different way to associate methods to types, and with both Go and Rust being "data-oriented" languages, it's weird that Go is so limited in this particular regard. It has many other consequences when combined with generics, such as ...
* Ability to attach receiverless methods to types. Go concrete types may not need associated methods like "constructors", but generic types do, and there's no solution yet. You can provide factory functions everywhere and they infect the whole call graph (though this seems to be "idiomatic"), or make a special method that ignores its receiver and call that on a zero instance of the type, which is more hacky but closer to how free functions can be resolved by type. There's no reason this should be limited to constructors, that's just the easiest example to explain, in Rust associated methods are used for all kinds of things. Speaking of which...
* `cmp.Ordered` for custom types. Come on people. We shouldn't still have this much boilerplate to sort/min/max custom types, especially two full years after generics. The new `slices.SortFunc()` is the closest we've ever come, and it's still not associated with the type. We would basically get this for free if both of the above points were solved, but it's also possible we get something else entirely that solves only ordering and not e.g. construction or serialization.
* Enums, especially if the need for exhaustiveness checking could be balanced with Go's values of making code easy to evolve later. When I need them, I use the `interface Foo { isFoo() }` idiom and accept heap boxing overhead, but even the official `deadcode` analysis tool still to this day does not recognize this idiom or support enough configuration to force it to understand. The Go toolchain could at the very least recognize idioms people are using to work around Go's own limitations.
If we had solutions to these problems, I think most Go folks would find enough value in them that they would still be "Go". In fact, I think people would have an easier time consolidating on a new standard way to do things rather than each come up with their own separate workarounds for it.
This is where I feel "The code I write, is going to look like the code written by most other on my team" the least, because that's only true when a Go idiom has some official status, it's not nearly as true for workarounds that the Go team has not yet chosen to either endorse or obsolete.
Re: Borgo is a statically typed language that compiles to Go
#378Is it correct to say Borgo "compiles to Go", or should it say "transpiles to Go" It appears to be a transpiler (consumes a Borgo and does the work to convert and emit a Go program as text): https://github.com/borgo-lang/borgo/blob/main/compiler/src/c...
The word "transpiler" propagates the misunderstanding that there is something special about a compiler that emits machine code, that requires some special "compiler" techniques for special "compiler" purposes that are not necessary for "transpiler" purposes because "transpiling" requires a completely different set of techniques. There aren't any such techniques. If one were to create an academic discipline to study "…
Re: Borgo is a statically typed language that compiles to Go
#379Earlier quoted context omitted.
The difference is that all code paths are explicitly spelled out and crucially that the programmer had to consider each path at the time of writing the code. The resulting code is much more reliable than what you end up with exceptions.
Do you really do that in practice, or do you just blindly go 'if err != nil return nil, err'? Because fundamentally the function you called can return different errors at any point so if you just propagate the error the code paths are in fact not spelled out at all because the function one above in the hierarchy has to deal with all the possible errors two calls down which are not transparent at all.
There's no requirement for the calling function to handle each possible type of error of the callee. It can, as long as the callee properly wrapped the error, but it's relatively rare for that to be required. Usually the exact error is not important, just that there was one, so it gets handled generically.
Re: Borgo is a statically typed language that compiles to Go
#380Earlier quoted context omitted.
An Enum type has to be on the core Go team's radar by now. It's got to be tied with a try/catch block in terms of requested features at this point (now that we have generics).
How the fuck do you release a language without enums?