Live data from Hacker News

Borgo is a statically typed language that compiles to Go

github.com

371–380 of 559 posts

Re: Borgo is a statically typed language that compiles to Go

#371

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.

The term you're looking for is ADT - Algebraic Data Types

https://en.wikipedia.org/wiki/Algebraic_data_type

Re: Borgo is a statically typed language that compiles to Go

#372
post #335

Earlier 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.

IMHO it's not about the standards in your company, it's more about being able to parse any random library on GitHub etc with your eyeballs.

Re: Borgo is a statically typed language that compiles to Go

#373
post #270

Earlier 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.

It's better because you do not need to remember to check for nil, the compiler will remind you every time by erroring out until you handle the second return value of `option.Get()`.

> 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

#374

Earlier 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…

> 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 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

#375

Earlier 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.

What kind of "freedom", precisely, are you talking about? Freedom to write purely functional programs? Well, then you need Haskell or Clojure at least. Freedom to write small, self sufficient binaries? Well you need C or C++ then. CL is a regular multiparadigm language with a rich macro system, relatively good performance but nonexistent dependency management, too unorthodox OOP, with no obvious benefits compared to more modern counterparts, and a single usable implementation (SBCL). If I want s-expressions based language I can always choose Scheme or Clojure, if I need modern flexible multiparadigm language I'd use Scala

Re: Borgo is a statically typed language that compiles to Go

#376

Earlier 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…

> No, it isn't, unlike C, in which it is.

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

#377

This 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…

A lot of people said the same about generics, and some even still do. I could barely stand Go before generics, and still don't think they go far enough.

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

#378
post #17
post #2

Is 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 "…

This was very nicely put. Thanks. I don’t think we need different terms just because the target languages are different (higher level or whatever).

Re: Borgo is a statically typed language that compiles to Go

#379
post #258

Earlier 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.

I don't see how it's possible to do it blindly unless the code gets autogenerated. If you're typing the `if err != nil` then you've clearly understood that an error path is there.

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

#380

Earlier 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?

You can enumerate constants. There is syntax to implicitly assign the integer values, just use iota as a value.
Post reply on HN