[HN Gopher] Borgo is a statically typed language that compiles t...
       ___________________________________________________________________
        
       Borgo is a statically typed language that compiles to Go
        
       Author : manx
       Score  : 237 points
       Date   : 2024-04-30 15:13 UTC (7 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | metadat wrote:
       | 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...
        
         | PurpleRamen wrote:
         | Readme says transpile: "Borgo is a new language that transpiles
         | to Go."
         | 
         | And it's written in rust. Kinda unholy.
        
           | metadat wrote:
           | Yeah, the top of the project says "compiles", then the readme
           | says "transpiles". Perhaps the author was just trying to get
           | all the SEO terms in there.
           | 
           |  _> And it 's written in rust. Kinda unholy._
           | 
           | Agreed, it's like, do you really hate writing Go so much that
           | you'll really write all that Rust to get out of it? Haha.
           | Reminds me of the web frameworks which generated the JS so
           | you didn't have to touch it, like GWT of old.
           | 
           | I'm sure it was a fun exercise to create Borgo, though.
           | 
           | My favorite transpiler is Haxe. It targets so many other
           | languages, the surface area is impressive.
           | 
           | https://haxe.org/
        
           | pjmlp wrote:
           | Nothing like adding dependencies to the build toolchain.
        
           | speed_spread wrote:
           | Nothing unholy there. It's easier to transpile to a less
           | constrained language. Transpiling to Rust would require using
           | one of the GC crates or refcount everything. Then you'd have
           | to also satisfy the mutability and send/sync constraints. Go
           | needs none of these things, so all the transpiler needs to
           | care about is it's own added constraints.
        
         | frozenport wrote:
         | Transpiler is a kind of compiler
        
         | michaelsbradley wrote:
         | "transpiler", "compiler", either terminology is valid:
         | 
         | https://en.wikipedia.org/wiki/Source-to-source_compiler
        
           | metadat wrote:
           | Thanks, I'd always thought targeted transformations ->
           | transpiler, but it makes sense it's really a subset of
           | general compiler functionality, sans binary output.
        
             | randomdata wrote:
             | _> but it makes sense it 's really a subset of general
             | compiler functionality, sans binary output._
             | 
             | Tell us more about this compiler subset that does not
             | produce binary output. What do they produce? Ternary?
             | Qubits? Nothing?
        
               | lolinder wrote:
               | They produce text, such as Golang source code.
        
               | randomdata wrote:
               | Thanks for your response, but the Go spec asserts that Go
               | source is represented as UTF-8. UTF-8 is a binary
               | encoding.
               | 
               | We're talking about compilers that produce something
               | other than binary output.
        
               | lolinder wrote:
               | Ah, my mistake, I thought you were making an earnest
               | inquiry and not a joke. Carry on.
        
         | jerf wrote:
         | 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 "transpilers" and one to study
         | "compilers", all you'd end up with is an identical bunch of
         | techniques and analyses with different names on them. (A thing
         | that sometimes happens when diverse disciplines study what
         | turns out to be the same thing; see machine learning versus
         | statistics for a well-known example.)
         | 
         | Even "compiling" to machine code isn't special anymore, because
         | CPUs don't actually execute assembly anymore. They themselves
         | compile assembly into internal micro-ops, which is what they
         | actually execute. So compilers don't even compile "machine
         | language" anymore; it's just another target. This also dodges
         | "is it a 'compiler' or a 'transpiler' if it targets WASM?",
         | which is good, because there is no value in that question on
         | any level.
        
           | markusde wrote:
           | It doesn't matter but I fully disagree with this. A
           | transpiler emits code the user is supposed to understand, a
           | compiler does not. At least that's the general way I've seen
           | the term used, and it seems quite consistent.
        
             | eklavya wrote:
             | I see what you mean but how is it academically useful to
             | identify transpilers something of their own? It's still
             | compiling (lowering) from one notation to another.
        
             | randomdata wrote:
             | All compiler outputs are understandable. I suppose you mean
             | with the intent of it being a one-time translation? As in,
             | like when the Go project converted the original C codebase
             | into Go source with the intent of having developers work in
             | the Go output afterwards and the C code to be never touched
             | again?
             | 
             | What is meaningful about such a distinction?
        
             | Jtsummers wrote:
             | > A transpiler emits code the user is supposed to
             | understand, a compiler does not.
             | 
             | No, a transpiler emits code that another system is meant to
             | understand (often another compiler or interpreter). Whether
             | a human can understand it or not is immaterial to the
             | objective of transpiling.
        
               | rowanG077 wrote:
               | But then compilation is the same thing as transpilation
               | as noted.
        
               | Jtsummers wrote:
               | Yes.
        
               | randomdata wrote:
               | Does that imply that a compiler emits code that nothing
               | can understand? Or are you saying that 'transpile' is
               | just another word for 'compile'?
        
               | Jtsummers wrote:
               | > Does that imply that a compiler emits code that nothing
               | can understand?
               | 
               | Bizarre take. No, compilers in the classical sense target
               | byte code and machine code which is meant to be
               | interpreted by a byte code interpreter or a hardware
               | machine.
               | 
               | > Or are you saying that 'transpile' is no more than
               | another word for 'compile'?
               | 
               | Yes. Compilers translate from one language to another.
               | Transpilers translate from one language to another. Both
               | have the objective of preserving the behavior of the
               | program across translation. Neither has the objective of
               | making something intended for humans as a general rule.
               | 
               | That transpiled code (if we draw a distinction) targets
               | languages meant for humans to read/write means that many
               | transpiled programs can be read by people, but it's not
               | the objective.
        
               | randomdata wrote:
               | _> Bizarre take._
               | 
               | Bizarre in what way? If compilers are somehow different,
               | then they mustn't target systems, as that's what your
               | previous comment says transpilers do. Which leaves even
               | your own classical definition to be contradictory, if
               | they are somehow different. What does that leave?
               | 
               |  _> Yes._
               | 
               | But it seems you do not consider them different, which
               | was the divergent path in the previous comment. But
               | evaluating both the "if" and the "else" statement is
               | rather illogical. The evaluation of both branches is what
               | is truly bizarre here.
        
             | jerf wrote:
             | There is a phenomenon I have observed many times where you
             | can get a bunch of people in a room and make some
             | statement, in this case, "Compilers are different than
             | transpilers", and everyone around the table will nod
             | sagely. Yup. We all agree with this statement.
             | 
             | But if you dig in, it will turn out that _every single one
             | of them_ has a different interpretation, quite often
             | fatally so to whatever the task at hand is.
             | 
             | I mention this because my impression has been that the
             | distinction between "transpiler" and "compiler" is that the
             | latter is into some machine code and the former is not. I
             | think if we could get people to sit down and very clearly
             | define the difference we'd discover it is not as universal
             | a definition as we think.
             | 
             | My personal favorite is when I say a particular term is not
             | well defined on the internet, and I get multiple commenters
             | to jump up and tell me off about how wrong I am and how
             | well-defined the term is and how universal the
             | understanding is, while _each of them gives a completely
             | different definition_. As I write this it hasn 't happened
             | in this thread yet, but stay tuned.
             | 
             | Anyhow, the simple solution is, there isn't a useful
             | distinction between them. There's no sharp line anyhow.
             | Plenty of "transpilers" produce things like Python that
             | looks like                   def f000000001_bch(a0023,
             | a0024, bf___102893):             __a1 =
             | f000000248_BCh1(a0024, const_00012)             if
             | __c_112__0:                 f0000000923(__a1)
             | else:                 f0000000082(__a1)
             | 
             | and it's really quite silly to look at what can be a very
             | large process and make a distinction only in how the very
             | last phase is run, and on a relatively superficial bit of
             | that last phase too.
        
               | floydnoel wrote:
               | I've observed this sort of behavior frequently, is there
               | a name for this phenomenon yet?
               | 
               | Something like "Assuming all concepts are universal to
               | one's own peculiar definition"
               | 
               | Maybe "semantic egocentrism" could fit the bill?
        
               | zer00eyz wrote:
               | And in the other corner you have Chomsky with universal
               | grammar... and in another you have Platonic Forms...
               | 
               | I love the "draw me a tree" idea of a Platonic form, we
               | all have an idealized model of what that is, that is
               | uniquely our own. With that in mind isnt everything
               | subject to some sort of semantics?
        
               | jerf wrote:
               | 2 hours later, I think it's safe to say there are
               | multiple definitions in play that are, if not outright
               | contradictory, certainly not identical.
               | 
               | It seems the term is not terribly useful even on its own
               | terms... it is not as well defined as everyone thinks.
               | 
               | Ultimately, "compiler" isn't a bright shining line
               | either... I can take anything and shade it down to the
               | point where you might not be sure ("is that a 'compiler'
               | or an 'interpreter'?"), but the "transpiler" term is
               | trying to draw a line where there isn't even a seam in
               | the landscape.
        
               | norir wrote:
               | > the "transpiler" term is trying to draw a line where
               | there isn't even a seam in the landscape.
               | 
               | I don't think you have proven that it is a seamless
               | landscape. In fact, I think that people's definitions
               | have been remarkably consistent in spite of their
               | fuzziness. The heart of what I have read is that most
               | people understand a transpiler to be an intermediate text
               | to text translation whose output is input to another
               | tool. The common colloquial definition of a compiler is a
               | text to machine code (for some definition of machine
               | code) translation whose output is an executable program
               | on a host platform. You can make an argument that every
               | compiler is a transpiler or every transpiler is a
               | compiler, but I think it requires a level of willful
               | obtuseness or excessive pedantry to deny that there is
               | something behind the concept of a transpiler. This
               | discussion wouldn't even be happening if transpiler were
               | a completely meaningless term.
        
             | itishappy wrote:
             | Is Babel a transpiler?
        
             | unshavedyak wrote:
             | Yea, not sure i disagree with anything being said here.
             | Though to me, transpiler just typically means it goes from
             | one language i could write, to another i could write. I
             | don't necessarily expect to enjoy reading or perhaps even
             | understanding the JavaScript output from any lang that
             | builds to JS, for example.
        
               | randomdata wrote:
               | _> transpiler just typically means it goes from one
               | language i could write, to another i could write._
               | 
               | What possible compiler target couldn't you write?
               | Compilers are not exactly magic.
        
               | unshavedyak wrote:
               | Fair, by "could write" i meant one intended for humans to
               | write. Ie i would not say LLVM bytecode is intended for
               | humans to write by hand. Can they? Sure.
               | 
               | The difference (to the parent comment) in my eyes is that
               | the target language is the thing intended for humans, not
               | the target output itself. As another commenter points
               | out, transpiled code is often not intended for humans,
               | even if the language is.
        
               | randomdata wrote:
               | Machine code is intended to be written by humans. That
               | was the _only_ way to program computers at one point in
               | time. Given a machine code target, would you say it is
               | product of transpilation or compilation?
        
           | Matheus28 wrote:
           | 1. Transpilers output to another programming language that is
           | typically written by hand by others (so not assembly).
           | 
           | 2. Transpilers don't typically optimize code, leaving those
           | transformations to the compiler of the target language.
           | 
           | 3. Compilers will typically have an internal representation
           | (SSA) which they operate on to optimize. Transpilers
           | typically operate on the AST (because they don't need to do
           | any but the most trivial optimizations).
           | 
           | There are exceptions to the rules but these cover the
           | majority of the reasons on why people make the distinction.
        
             | randomdata wrote:
             | _> the majority of the reasons on why people make the
             | distinction._
             | 
             | You have provided some defining properties that might allow
             | for distinction, but you have not given any reasons for
             | _why_ people make a distinction.
             | 
             | But perhaps we can suss it out. Given the statement "Borgo
             | compiles to Go", what important information is lost that
             | would be saved if "Borgo transpiles to Go" was used
             | instead?
        
               | Matheus28 wrote:
               | In that statement, it doesn't really add anything.
               | 
               | In the statement "XYZ is a compiler/transpiler", it does.
               | It doesn't hurt to have a word that is more specific than
               | others. Otherwise we should just refer to compilers as an
               | "app" :)
        
               | lolinder wrote:
               | I don't think anyone here is saying we shouldn't have the
               | word "transpiler" at all, just that "transpiler" is a
               | subcategory of "compiler" and there's no reason for OP to
               | try to correct the title of this story.
               | 
               | It reminds me of how my 5-year-old son always corrects me
               | when I tell him to get in the car--"you mean the van!". I
               | have tried to explain to him that a minivan is a kind of
               | car, and he's just about getting it, but it's been a
               | challenge for him to grasp.
        
               | Matheus28 wrote:
               | >I don't think anyone here is saying we shouldn't have
               | the word "transpiler" at all
               | 
               | This thread chain is in response to jerf's comment
               | "transpiler shouldn't be a word" (simplifying his comment
               | for brevity's sake)
        
               | lolinder wrote:
               | Eh, that's one possible reading, but their actual take is
               | more nuanced than that:
               | 
               | > 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.
               | 
               | In context of the parent comment I read this to be a
               | reaction to someone insisting that we use "transpiler"
               | instead of "compiler"--more an observation of what is
               | happening here than a call to stop using the word
               | altogether.
        
               | gergo_barany wrote:
               | We shouldn't have the word "transpiler" at all.
        
               | randomdata wrote:
               | _> In the statement  "XYZ is a compiler/transpiler", it
               | does._
               | 
               | Okay. What important information is lost in "XYZ is a
               | compiler" that would be gained in "XYZ is a transpiler"?
               | 
               |  _> It doesn 't hurt to have a word that is more specific
               | than others._
               | 
               | It can if the intent is not properly understood. And so
               | far I'm not sure we do have that understanding.
        
             | lolinder wrote:
             | These differences aren't inherent to transpilers vs
             | compilers, they're mostly the result of the fact that the
             | vast majority of transpilers are less mature than the
             | battle-tested compilers that you're thinking of.
             | 
             | The average hobby compiler--regardless of target--doesn't
             | optimize code and works directly on the AST because that's
             | simple to get started with. Most hobby compilers _also_
             | target some other language rather than LLVM or machine code
             | because that 's simple to get started with, so the result
             | is that most transpilers are hobby projects that don't
             | optimize. But there's no reason why a transpiler _shouldn
             | 't_ include optimization steps that adapt the output to use
             | code paths that are known to be fast, and a production-
             | grade transpiler typically will include these steps.
        
           | Joker_vD wrote:
           | I'm fairly certain that source-to-source transpilers rarely
           | use anything like BURS or any other sufficiently smart
           | "instruction selection" (or insturction scheduling, for that
           | matter) algorithms because why would they, the compilers for
           | the targeted language already incorporate such algorithms,
           | maybe even of the higher quality than the transpiler's author
           | are capable to write themselves.
        
             | jerf wrote:
             | All compilers end up with local considerations. Instruction
             | selection or register allocation is not a consideration
             | special to compilers that "transpilers" do not need to
             | have, they are specific considerations for that particular
             | compiler target. A compiler to Go must consider Go's
             | identifier rules, which does not apply to compilers
             | targeting a CPU. A compiler to SQL must consider valid SQL
             | syntax and have their own optimization concerns that don't
             | apply to Go. And so on.
             | 
             | The middles all look very similar, though, which is where
             | the heart of "compiler" comes from; that process of some
             | sort of parsing and then transforming down to some other
             | representation. This has a distinguishing set of
             | characteristics and problems despite what frontends and
             | backends get slapped on them.
        
       | rowanG077 wrote:
       | Why would you target Go?
        
         | toolz wrote:
         | It's a language known for having a great runtime and tooling
         | but subpar language semantics. Makes sense to me, at least.
         | Most of the benefits of go with fewer drawbacks.
        
           | wesselbindt wrote:
           | I'm not trying to be argumentative, I'm genuinely curious:
           | what is it about the go runtime and tooling that makes them
           | great?
           | 
           | I did not post your parent comment.
        
             | wrs wrote:
             | To name a few things: Excellent and very stable stdlib (if
             | you're making a networked thing), fast GC optimized for
             | latency, async I/O without any fuss, easy CSP-like
             | concurrency, fast compile time, statically linked binaries,
             | large user community.
        
             | zer00eyz wrote:
             | GO:
             | 
             | Easy to learn: you can be productive in go in a day or two.
             | 
             | Strong standard library.
             | 
             | Complies to binary. (you dont need to drag a run time
             | around) And this is fast!
             | 
             | Easy dependency management.
             | 
             | Linting is built in. (No arguing over tabs vs spaces)
             | 
             | First class testing. (and its fast)
             | 
             | "good enough" coding is very fast. You can mostly ignore
             | performance and pick it up when and where you need it.
             | 
             | -----------------------
             | 
             | Go users tend to say "Idiomatic" a lot. Your not getting
             | rails, there is no java like framework, and you really
             | should NOT do the node js thing and stack tools to the sky.
             | Minimalism, brutalism.
             | 
             | As an example: Most languages have tooling for dependency
             | injection. Most go projects have dependency injection but
             | dont use a library or framework or tooling to do it. Its
             | just a bit of code (100 ish lines) that you end up writing
             | as part of your bootstrapping, config or testing (depending
             | on the project)....
        
               | eximius wrote:
               | > As an example: Most languages have tooling for
               | dependency injection. Most go projects have dependency
               | injection but dont use a library or framework or tooling
               | to do it.
               | 
               | I actually see this as a negative and we've been looking
               | at Uber/Fx for more support. DI frameworks don't do
               | anything you can't do without it, but it takes
               | significantly more experience and
               | technological/organizational maturity that I find the
               | average developer doesn't have to do it without framework
               | support.
               | 
               | In the current zeitgeist of being towards the "micro"
               | scale of the spectrum, that "average developer" support
               | is necessary. If you have more modular monoliths or many
               | high quality examples, maybe its better.
        
               | jimbokun wrote:
               | DI in something like Spring, for example, can make it
               | extremely hard to track where a given dependency is
               | coming from. With the use of annotations and defaults and
               | properties on annotations for selecting a dependency, to
               | sometimes autogenerated classes for which there is no
               | source code.
               | 
               | I would much rather have a few lines of straight forward
               | code that set up dependencies explicitly, than deal with
               | opaque semantics and mysterious incantations.
        
               | eximius wrote:
               | I've never really had that trouble. There are typically
               | relatively few places that
               | 
               | 1. a given interface is provided via a DI module 2. said
               | modules are included in a binary
               | 
               | With decent codesearch, finding the implementation of a
               | particular injection for a given deployed binary is
               | usually a fairly short search.
               | 
               | I'm sure there is all sorts of extra voodoo you can get
               | up to, but the straightforward DI case is, well,
               | straightforward.
        
               | jimbokun wrote:
               | The autogenerated class with no source code was not a
               | hypothetical example. This was something I saw cause a
               | problem in production, where the source code in the stack
               | trace didn't exist.
        
               | eximius wrote:
               | _code generation_ is a mostly disjoint topic from DI.
               | Granted, some solutions like
               | https://github.com/google/wire use code generation, but
               | you're exactly right about their pitfalls. If your dev
               | environment doesn't have good support for generated code,
               | it is a nightmare. If you can goto-definition the
               | generated code, then it is suddenly feasible, but perhaps
               | still a bad choice.
        
               | zer00eyz wrote:
               | Wow, that's a pretty good take.
               | 
               | There is a line here though. I think a lot of people have
               | seen what happens when you set a bunch of JR devs loose
               | in a node/ruby code base with all that tooling. It goes
               | about as well as giving a lead footed suburbanite an F1
               | car.
               | 
               | If you work in an agency (new every week) or in a place
               | where you have a high number of jr devs then a framework
               | makes a fair bit of sense. But at that point are your
               | experienced devs being productive or being babysitters?
               | 
               | I think I would rather babysit a bunch of jr devs working
               | in Go where correcting their issues is educational,
               | rather than dealing with babysitting JR devs and high
               | speed stupidity in something like rails...
        
             | zem wrote:
             | seamless cross compilation as a first-class citizen, for
             | one
        
           | aorona wrote:
           | subpar semantics?
        
           | zer00eyz wrote:
           | This is a terrible take.
           | 
           | It's like one of those people who buys a massive over priced
           | knife block with 48 knives in it that they never use.
           | 
           | Most go devs have lived through bloated
           | java/php/python/ruby/js projects that become a pile of
           | dependencies.
           | 
           | Go is to coding what brutalism is to architecture. Simple,
           | functional, efficient. Dont build a massive dependency chain,
           | dont build magic, repeating yourself is OK. Be an adult and
           | deal with your errors (it's a feature)... That minimalist no
           | bullshit language semantics that force you not to be lazy is
           | a feature not a bug.
        
             | 2024throwaway wrote:
             | I'm not sure why you included php in your list of examples
             | of things that become bloated with dependencies. I've never
             | seen that be the case.
        
               | sleepybrett wrote:
               | Obvious troll is obvious.
        
               | 2024throwaway wrote:
               | I just opened the composer.json file for a complex PHP
               | application, it has 20 imports, total.
               | 
               | I just opened the package.json for a react frontend, it
               | has 80 imports.
               | 
               | I just opened the Gemfile for a complex rails
               | application, it has 150+ imports.
               | 
               | But sure, I'm just trolling I guess.
        
               | nasretdinov wrote:
               | Look at your list of built-in modules though :)
        
               | 2024throwaway wrote:
               | So stdlib counts as dependencies now?
        
               | nasretdinov wrote:
               | Well stdlib normally doesn't have stuff like Oracle
               | drivers and such. I think one of the reasons why PHP
               | tends to need so few external dependencies is because it
               | has so many extensions to cover basically anything that
               | you don't need PHP libraries all that much. I don't
               | personally see it as a bad thing but it's something worth
               | considering.
        
             | pjmlp wrote:
             | If Rust was already matured by the time Docker was rewriten
             | from Python, and Kubernetes from Java, I bet that Go
             | wouldn't have been the lucky candidate.
        
               | zer00eyz wrote:
               | I like rust, I write go.
               | 
               | There was a thread here the other day where a rust dev
               | pointed out that "Rust is the language tokio ate"...
               | https://nullderef.com/blog/rust-async-sync/
               | 
               | Rust is a lot of overhead when go is "good enough" for
               | 99% of what needs to get done. That doesn't mean go is
               | good for everything. I would still rather write Rust than
               | C or C++ or bunch of other languages. Look at a project
               | like Pingora, from cloud flair. Perfect Rust project, bad
               | Go project. Rust is in the kernel, rust is what im
               | looking at for a USB driver. I would not shove go in
               | either of these places.
        
               | pjmlp wrote:
               | Go could have been like Modula-3, D or C#, instead they
               | decided to revamp Oberon and Limbo, the version 1.0 of
               | those languages from the 1990's, not what was latter done
               | from their learnings, e.g. Active Oberon.
               | 
               | Now thanks to Docker and Kubernetes adoption success,
               | we're stuck with it.
               | 
               | At least now generics are supported, unless one needs
               | gccgo, maybe in 10 years we get Pascal enumerations.
        
               | zer00eyz wrote:
               | It whooshed right past your head.
               | 
               | Go is stone cold simple to pick up. ITs simple to reason
               | about. I can decompose a project and spoon feed it to a
               | JR engineer and they can get through it.
               | 
               | Rust is none of those things.
               | 
               | Its great for low level stuff, it is in the kernel right
               | next to C and go will NEVER be there. Why, because that
               | is what rust is good at.
               | 
               | > At least now generics are supported, unless one needs
               | gccgo, maybe in 10 years we get Pascal enumerations.
               | 
               | Again I like rust. Crates being colored (as in
               | functions), the shitty compile and tests times... these
               | are things that are holding back rusts adoption in more
               | places... None of this stuff is on the road map to get
               | fixed, it's quite the glass house you have.
               | 
               | Go is going to replace a fair bit of python/ruby in the
               | next few years... Is it going to be rust or zig that eats
               | into c/c++? If the rust community keeps on the way it has
               | been, zig will eat all the core apps we depend on.
        
             | wrs wrote:
             | I don't think any of that is contradicted by what this
             | seems to be trying to do. In fact, Go _doesn't_ make you
             | deal with your errors (you're free to ignore the returns)
             | whereas this would (via exhaustive pattern match).
        
               | zer00eyz wrote:
               | > In fact, Go doesn't make you deal with your errors
               | 
               | Your right, it does not. I will _ =: an error in a throw
               | away script all the time.
               | 
               | I see that in a code review, in production code... Big
               | red flag. This is a departure from an exception, that
               | might be thrown in one place and handled far far away
               | from the code you're looking at.
        
               | strongly-typed wrote:
               | I'm not an expert in Go, and my experience is somewhat
               | limited, however, a few years back I fixed a really
               | subtle bug in a project that was related to the fact that
               | errors _weren't_ being handled correctly. As a relative
               | newbie to Go, the code in the diff[0] didn't appear to be
               | doing anything wrong, until I added some print statements
               | and realized that the numbers were not adding up
               | correctly. IMO, if the returned value had been more like
               | a Rust optional or result type, I think this issue would
               | have either not been a bug in the first place, or it
               | would have been easier to spot the bug.
               | 
               | [0]: https://github.com/semilin/genkey/commit/fafed674455
               | 5c5a81fd...
               | 
               | EDIT: The fact that this was a bug at all makes me fear
               | for the rest of the code base. If this one slipped
               | through the cracks, how can I know that the rest of the
               | code base is correct?
        
               | randomdata wrote:
               | _> The fact that this was a bug at all makes me fear for
               | the rest of the code base._
               | 
               | The fact that the commit was accepted into a release
               | without any changes to accompanying tests is what is most
               | concerning. You should be afraid.
        
               | nasretdinov wrote:
               | Is the wrong code in the new part of the diff or in the
               | old one?
               | 
               | Generally getting zero value from a map is a feature, but
               | the code that the diff replaces did look overly complex
               | and fragile to me already tbh
        
               | Thaxll wrote:
               | Rust does not enforce error checking either.
               | 
               | You can ignore errors in Rust.
        
               | ben-schaaf wrote:
               | Ignoring errors is a thing you can do whether you're
               | checking them or not. Rust does enforce error checking,
               | every Result<T, E> is required to be checked before the
               | value can be accessed. The only exception for this is if
               | you don't need to access the Result's value, for which
               | there's at least a built-in warning. And of course
               | `unsafe`.
        
               | randomdata wrote:
               | _> Result <T, E> is required to be checked before the
               | value can be accessed._
               | 
               | Which is a flaw in Borgo, at least when interfacing with
               | Go code, as in Go both T and E should independently valid
               | states.
        
               | djbusby wrote:
               | Basic has                   on error goto next
        
         | theamk wrote:
         | it's literally the 2nd sentence of README: "It's fully
         | compatible with existing Go packages."
         | 
         | It's a nice way to bootstrap ecosystem IMHO. No one wants to
         | use a brand-new language without library support for common
         | tasks.
        
           | rowanG077 wrote:
           | It doesn't make sense that that is the reason. Surely C++ has
           | way more packages. So Go would be a bad choice if package
           | availability was a very important concern.
        
             | eximius wrote:
             | There is more code written in C++, but there are fewer "C++
             | packages" in the sense of just doing `go get` and you're
             | ready to use it.
        
               | rowanG077 wrote:
               | I doubt that's true. In all the years I have never not
               | found a library that can the things I want in C or C++.
               | It doesn't have a package manager but that doesn't mean
               | it doesn't have packages.
        
             | eklavya wrote:
             | It doesn't make sense when you use this reasoning on
             | established languages like C++ and Go. Makes all the
             | difference when you are less than a year old language.
        
             | furyofantares wrote:
             | > I want a language for writing applications that is more
             | expressive than Go but less complex than Rust.
             | 
             | > Go is simple and straightforward, but I often wish it
             | offered more type safety. Rust is very nice to work with
             | (at least for single threaded code) but it's too broad and
             | complex, sometimes painfully so.
             | 
             | It seems clear that the author really likes aspects of both
             | Go and Rust and desires something between the two. Check
             | out the complexity vs type-safety illustration at the top
             | of the page, with Borgo placed between the Gopher and the
             | Crustacean just before the complexity curve gets steep.
             | 
             | They're basically building their personal ideal version of
             | Go with inspiration from Rust.
        
               | rowanG077 wrote:
               | Sure. I'm not knocking the design goal. The same thing
               | could be achieved by having C++ as a target. So why
               | choose go.
        
               | furyofantares wrote:
               | Because they like go, are making essentially a go
               | extension, and so a lot of their features map directly to
               | go features. No need to re-implement goroutines and
               | channels etc.
               | 
               | The type system lets them reject the programs they want
               | to reject, but if a program is valid in the type system
               | it can, in large part, emit essentially the same go code
               | sans the types. I mean, I'm making some assumptions here,
               | but that's typically the reason.
        
         | akira2501 wrote:
         | Because a plethora of languages, some of which you don't
         | personally like using, being part of a large and healthy
         | ecosystem, benefits all languages and programmers.
         | 
         | There is no "one true" answer, and time spent bullying people
         | over it, is entirely wasted.
        
       | dexwiz wrote:
       | Can you use Go modules?
        
       | HippoBaro wrote:
       | Go has an amazing runtime and tool ecosystem, but I've always
       | missed a little bit more type safety (especially rust enums).
       | Neat!
        
       | templaedhel wrote:
       | They made a coffeescript for go
        
         | christophilus wrote:
         | They made a Typescript for go. Coffeescript was dynamic.
        
           | recursive wrote:
           | Coffeescript added semantics and behavior. Typescript for
           | better or worse is _almost_ only types on top of existing
           | behavior. (with the primary exception being the `enum`
           | concept)
        
       | Qerub wrote:
       | Reminds me of this previous effort to build upon Go but add a
       | more flexible type system: https://github.com/oden-lang/oden
        
       | philosopher1234 wrote:
       | The only language I can think of that has pulled off "compiles to
       | another totaling language" and gained mainstream adoption is
       | typescript, and I'm sure it wouldn't have done so if it were
       | possible to run in the browser otherwise.
       | 
       | Can anyone think of another example?
        
         | elliotlarson wrote:
         | Elixir compiles to Erlang, I think.
        
           | giancarlostoro wrote:
           | Correct Elixir runs on the BEAN.
        
           | toolz wrote:
           | Not exactly correct, it does have "core erlang" as a
           | compilation step, but they both have that as a compilation
           | step ultimately compiling to beam bytecode.
        
         | tylerhou wrote:
         | C++ used to compile to C.
        
         | ARandomerDude wrote:
         | CoffeeScript was pretty popular about 10 years ago and did
         | this.
        
         | furyofantares wrote:
         | C++ is for sure gonna be the biggest example. I think
         | Objective-C too.
         | 
         | There's other successful but not "mainstream" languages that
         | might count or semi-count, like Clojure targeting the JVM
         | (though not Java) and being able to use Java packages, or
         | ClojureScript targeting JavaScript.
        
         | michaelsbradley wrote:
         | Nim compiles to C by default, and it seems most Nim devs stick
         | with that default. Nim hasn't gained mainstream adoption,
         | though.
        
         | hiccuphippo wrote:
         | Not exactly the same but a few languages compile to llir which
         | then is compiled by llvm to machine code.
        
         | dhosek wrote:
         | There's web2c which transpiles Pascal-Web to C code. And in the
         | 90s, Eberhard Mattes, to enable his port of TeX and friends to
         | OS/2 and DOS wrote a Pascal to C compiler (I remember when it
         | was first released, there was speculation that it might have
         | been a pirated commercial implementation because how could one
         | guy manage this, but that was short-lived as people realized it
         | was faster than any of the commercial versions.)
        
         | zem wrote:
         | haxe is not quite "mainstream adoption" level but it has a
         | decent amount of stuff done in it
         | 
         | clojurescript is fairly popular too.
        
         | doctor_eval wrote:
         | I like your take but - not that this was important to
         | TypeScript - JavaScript was literally the assembly language of
         | the web (asm.js) until WASM came along. There was no other
         | target that TypeScript could compile to. I guess that's why
         | TypeScript simply added types to JS, rather than being a wholly
         | new language, which in turn made it compatible and familiar to
         | potential adopters. It also solved a big problem caused by the
         | growing size of client code bases.
         | 
         | All of that said - this train of thought lead me to discover
         | AssemblyScript! https://www.assemblyscript.org/
        
       | eximius wrote:
       | Be still my heart. I would use this so fast at work where we
       | currently use Go.
       | 
       | But introducing a new language is a scary thing.
        
       | eklavya wrote:
       | Congratulations and best wishes for your project. I have hoped
       | for a Go+Rust lang for a long time now.
        
       | lordofgibbons wrote:
       | Wow, this is everything I want from a new Go!
       | 
       | Having worked on multiple very large Go codebases with many
       | engineers, the lack of actual enums and a built-in optional type
       | instead of nil drive me crazy.
       | 
       | I think I'm in love.
       | 
       | Edit: Looks like last commit was 7 months ago. Was this
       | abandoned, or considered feature complete? I hope it's not
       | abandoned!
        
         | H1Supreme wrote:
         | 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).
        
           | TwentyPosts wrote:
           | The issue is that it's more or less impossible to graft onto
           | the language now. You could add enums, but the main reason
           | why people want them is to fix the error handling. You can't
           | do this without fracturing the ecosystem.
        
             | drdaeman wrote:
             | > but the main reason why people want them is to fix the
             | error handling
             | 
             | Why do you think so? Maybe I'm an odd case, but my main use
             | case for enums is for APIs and database designs, where I
             | want to lock down some field to a set of acceptable values
             | and make sure anything else is a mistake. Or for state
             | machines. Error handling is manageable without enums (but I
             | love Option/Result types more than Go's error approach,
             | especially with the ? operator).
        
               | randomdata wrote:
               | _> my main use case for enums is for APIs and database
               | designs, where I want to lock down some field to a set of
               | acceptable values and make sure anything else is a
               | mistake_
               | 
               | Then what you are really looking for is sum types (what
               | Rust calls enums, but unusually so), not enums. Go does
               | not have sum types, but you can use interfaces to archive
               | a rough facsimile and most certainly to satisfy your
               | specific expectation:                   type Hot struct{}
               | func (Hot) temp() {}              type Cold struct{}
               | func (Cold) temp() {}              type Temperature
               | interface {             temp()         }
               | func SetThermostat(temperature Temperature) {
               | switch temperature.(type) {             case Hot:
               | fmt.Println("Hot")             case Cold:
               | fmt.Println("Cold")             }         }
        
               | blueberry87 wrote:
               | annoyingly go _can 't_ have proper sum types, as the
               | requirement for a default value for everything doesn't
               | make any sense for sum types
        
           | jurschreuder wrote:
           | I've never needed either.
           | 
           | Try/catch is super confusing because the catch is often far
           | away from the try. And in Python I just put try/catch around
           | big chunks of code just in case for production.
           | 
           | I think Go is more stable and readable because they force you
           | not to use the lazy unreadable way of error handling.
           | 
           | Enums I honestly never used in Go also not the not-type-safe
           | ones.
           | 
           | But I'm also someone who used interfaces in Go maybe I think
           | 4 times only in years and years of development.
           | 
           | I just never really need all those fancy things.
        
             | kbenson wrote:
             | I think what this comment is missing is any sort of
             | analysis of how your experience maps to the general go
             | user, and an opinion on while you've never _needed_ either
             | whether you think it could have provided any benefit when
             | used appropriately.
             | 
             | For example, and option type with enums combined can ensure
             | return values are checked by providing a compile time error
             | if a case is missing (as expressed in the first few
             | examples of the readme).
        
             | pdimitar wrote:
             | Your comment could have been a nice opinion that proves to
             | a drive-by reader that needs can differ drastically between
             | programmers.
             | 
             | But you ruined it with "fancy things" which shows offhand
             | disregard and disrespect.
             | 
             | A question like "what do you need these features for?"
             | would have been a better contribution to the forum.
        
         | samatman wrote:
         | While I have no particular beef with Rust deciding to call its
         | sum types "enum", to refer to this as the _actual_ enum is a
         | bit much.
         | 
         | Enumerated types are simply named integers in most languages,
         | exactly the sort you get with const / iota in Go:
         | https://en.wikipedia.org/wiki/Enumerated_type
         | 
         | Rather than the tagged union which the word represents in Rust,
         | and only Rust. Java's enums are close, since they're classes
         | and one can add arbitrary behaviors and extra data associated
         | with the enum.
        
           | gr4vityWall wrote:
           | Haxe also has Enums which are Generalized Algebraic Data
           | Types, and they are called "enums" there as well:
           | https://haxe.org/manual/types-enum-using.html
        
             | samatman wrote:
             | Very well then: Rust is not the only one to call a variant
             | type / tagged union an enum. It's a nice language feature
             | to have, whatever they decide to call it.
             | 
             | It remains a strange choice to refer to this as the _true_
             | enum, _actual_ enum, _real_ enum, as has started occurring
             | since Rust became prominent. If that 's a meaningful
             | concept, it means a set of numeric values which may be
             | referred to by name. This is the original definition and
             | remains the most popular.
        
       | ketralnis wrote:
       | Rust is not as complicated as the opening graphic indicates. I
       | usually see this meme from less experienced people but I'm
       | frankly surprised to see it from somebody that's capable of
       | writing a compiler _in rust_.
        
         | logdahl wrote:
         | I think they are calling Rust _complex_ , not complicated. Rust
         | is way more complicated than Go, when we are talking about
         | language features.
        
         | itishappy wrote:
         | Compared to GCed languages like Go and Borgo? Ownership is non-
         | trivial...
        
         | akira2501 wrote:
         | It's also not as type safe as the graphic implies.
        
       | ralegh wrote:
       | Great! Something I've always wanted.
       | 
       | I'd love to be able to use a bit more type-y Go such as Borgo,
       | and have a Pythonesque dynamic scripting language that latches
       | onto it effortlessly.
       | 
       | Dynamic typing is great for exploratory work, whether that's ML
       | research or developing new features for a web app. But it would
       | be great to be able to morph it over time into a more specified
       | strongly typed language without having to refactor loads of
       | stuff.
       | 
       | Like building out of clay and firing the parts you are happy
       | with.
       | 
       | Could even have a three step - Python-esque -> Go/Java-esque ->
       | Rust/C++esque.
        
         | mattlondon wrote:
         | Sounds like JavaScript and typescript would be a good fit for
         | you. Highly expressive, dynamic and strongly typed, and highly
         | performant both on server side and within the browser.
        
           | ralegh wrote:
           | I do like JavaScript but it strikes a weird balance for me
           | where it's a bit too easy to write and a bit too verbose so I
           | tend to end up with hard to maintain code. Feels good at the
           | start of a project but rarely a few weeks in. Also not a fan
           | of the node ecosystem, I try to use deno where I can (maybe
           | that would be bun these days).
        
           | zem wrote:
           | perhaps rescript [https://rescript-lang.org/] even more than
           | typescript
        
         | anonzzzies wrote:
         | > Like building out of clay and firing the parts you are happy
         | with. > Could even have a three step - Python-esque -> Go/Java-
         | esque -> Rust/C++esque.
         | 
         | We do exactly that with Common Lisp. It compiles to different
         | languages/frameworks depending on what we require (usually sbcl
         | is more than enough, but for instance for embedded or ML we
         | need another step. All dev (with smaller data etc) is in sbcl
         | so with all the advantages.
        
           | ralegh wrote:
           | Is there somewhere I could read more about this? I've always
           | wanted to learn Lisp but lacked a specific need for it.
        
         | VBprogrammer wrote:
         | I like the idea but in all honesty I have difficulty imagining
         | it working in practice. Once your python code is stable (i.e.
         | You've worked out 99% of the bugs you might have caught earlier
         | with strict type checking) would there be any incentive to go
         | back and make the types more rigid or rigorous? Would there be
         | a non-negligible chance of introducing bugs in that process?
        
           | ralegh wrote:
           | I agree it's a bit of a pipe dream. I'm more thinking of
           | performance here, e.g. web services using Django. You could
           | start off in dynamic/interpreted land and have a seamless
           | transition to performant compiled land. Also lets you avoid
           | premature optimisation since you can only optimise the hot
           | paths.
           | 
           | Also types are self documenting to an extent. Could be
           | helpful for a shared codebase. Again Python just now getting
           | round to adding type definitions.
           | 
           | At the end of the day good tooling/ecosystem and sheer
           | developer hours is more important than what I'm suggesting
           | but it would be nice anyway. I dream about cool programming
           | languages but I stick to boring for work.
        
           | zem wrote:
           | by the time you have your code in its final state (i.e.
           | you're done experimenting) and shaken out the bugs, your
           | types _are_ mostly static; they 're just implicitly so.
           | adding annotations and a typechecker helps you maintain that
           | state and catch the few places where type errors might still
           | have slipped through despite all your tests (e.g. lesser-used
           | code paths that need some rare combination of conditions to
           | hit them all but will pass an unexpected type through the
           | call chain when you do). it is very unlikely that you will
           | introduce bugs at this point.
        
         | claudionaoto wrote:
         | Dart? Version 1 was a lot like Javascript/Typescript in one
         | spec (a dynamic language with optional unsound typing). Version
         | 2 uses sound typing, but you can still let variables unannoted
         | (and the compiler will infer type "dynamic") for scripts.
        
       | sevkih wrote:
       | So swift?
        
       | preommr wrote:
       | This and pub/private modifiers for structs instead of letter
       | casing is all I've ever wanted.
        
         | odc wrote:
         | I love Go's letter casing. It's such a neat way to remove
         | cruft.
        
           | metaltyphoon wrote:
           | Dislike it very much specially with codebases which have lots
           | of acronyms, aka aviation. Having to change an acronym from
           | upper to lowercase just suck.
        
             | Groxx wrote:
             | In that case, maybe try: `_ACRNYM`
        
               | metaltyphoon wrote:
               | Function names with _ ? That's not for me :)
        
           | phplovesong wrote:
           | It also adds cruft. Public struct members JSON usually needs
           | to be converted to lowercase. Hence the stuct tags.
        
             | eadmund wrote:
             | JSON is just one tiny part of most programs, sitting on the
             | edge where the program interacts with other programs; it
             | doesn't permeate the entire codebase.
             | 
             | Structure privacy, OTOH, does. Count me in as someone who
             | really enjoys the case-based approach. It's not the only
             | one which could work, but it does work.
        
               | gpderetta wrote:
               | The single most productive habit I picked up int the last
               | few years is to always use exactly the same name for the
               | same entity across source files, configs files, database
               | entries, protocol fields, etc.
        
               | doctor_eval wrote:
               | That's funny, I did it your way for years and ended up
               | considering it a big mistake.
               | 
               | Today I use idiomatic names - MyName in Go, myName in
               | JS/JSON, my_name in SQL. There are many reasons but
               | generally speaking, for me, it's less effort and code is
               | more readable.
               | 
               | Curious what your rationale is?
        
             | zer00eyz wrote:
             | And database col name, and validation and...
             | 
             | The moment you integrate with a third party your US centre
             | zip_code field is suddenly coming over the wire as
             | postCode. The conversions are going to go on, at least in
             | go I can define all of that conversion with ease in one
             | place.
        
           | jjallen wrote:
           | I spent quite a few hours tracking down bugs due to miscased
           | struct fields unfortunately. Strongly prefer explicitness
           | over implicitness
        
             | latchkey wrote:
             | Which IDE do you use? Mine would flag this as an error
             | pretty quickly.
        
             | randomdata wrote:
             | The casing rules are quite explicit and enforced by the
             | compiler. A build would have immediately failed on whatever
             | mismatch you had. A few hours and you didn't even think to
             | try compiling it?
             | 
             | I'm guessing you are talking about something else entirely,
             | like, perhaps, decoding JSON into a struct using reflection
             | and encountering a situation where the field names didn't
             | match? Indeed, implicitness can bite you there. That's true
             | in every language. But, then again, as you prefer
             | explicitness why would you be using that approach in the
             | first place?
        
           | akira2501 wrote:
           | > It's such a neat way to remove cruft.
           | 
           | I don't disagree, the problem I have with it is, I have to
           | pay for that up front and have to factor it into my design
           | immediately. This also combines with the fact that the
           | namespace is very flat with no heirarchy, so, choosing good
           | public names is something I feel like I spend way too much
           | time on.
           | 
           | Go is the only language that causes me to pull out a
           | thesaurus when trying to name methods and struct members.
           | It's kinda maddening. Although, after going through this
           | exercise, I end up with code that reads like English. I just
           | wish I could refactor my way into that state, rather than
           | having to try to nail it up front.
        
             | aatd86 wrote:
             | >I just wish I could refactor my way into that state,
             | rather than having to try to nail it up front.
             | 
             | Procrastination looms. :o
        
           | hgs3 wrote:
           | Go's semantic use of case is objectively bad because most of
           | the worlds scripts do not have the concept of it. For example
           | ideographs, as used in eastern countries, do not have
           | capitalization. This means programmers in many parts of the
           | world cannot express identifiers in their native tongue.
        
             | randomdata wrote:
             | It looks like something was lost in the middle of your
             | comment. You open with something about it be objectively
             | bad, but then it jumps to something about how it is
             | subjectively bad. What was omitted?
        
               | from-nibly wrote:
               | How is "i cant name variables in my native language"
               | subjective?
        
               | bigstrat2003 wrote:
               | I don't really think the sarcastic tone was called for,
               | but the previous poster is right. "I can't name variables
               | in my native language" is objective, but whether or not
               | that's bad is subjective.
        
           | doctor_eval wrote:
           | I like the terseness of it but having to refactor just
           | because I change visibility is a bit stupid.
           | 
           | I never wrote ObjC but didn't they use + and - (and nothing)
           | as visibility modifiers?
        
       | ThouYS wrote:
       | wow. this is it!
        
       | a3w wrote:
       | Go is less complex than rust? Really? I thought that was
       | disputed.
        
         | unshavedyak wrote:
         | Go is less complex than Rust, imo. As someone who has used Go
         | and Rust for about the same time (5-6 years), it's not _as less
         | complex than it seems_ , though. Namely i found a odd type of
         | complexity emerge in Go where by every individual unit was
         | simple, but the whole was so spread out and poorly abstracted
         | that it it spread out the complexity. So if you squinted,
         | everything was simple. If you zoomed out, it felt convoluted.
         | 
         | Rust on the other hand drastically simplifies a lot of the
         | complexity i dealt with in Go. However depending on the type of
         | work, it's of course got plenty of complexity to dig into
         | should you need it.
         | 
         | The challenge with Rust imo is to know where to use that
         | complexity. Lots of rope to hang yourself with. On average i
         | find myself with code that to me is simpler in Rust, because
         | it's easier to reason about larger blocks of logic. However i
         | still wouldn't ignore the extra rope of the whole language and
         | call it "simpler" than Go.
        
         | akira2501 wrote:
         | You can read and grok the entire gospec in a week.
        
           | preommr wrote:
           | The golang language spec is very sparse on implementation
           | details in comparison to something like the java spec. I
           | don't think the length of the lang spec is a great metric for
           | language simplicity.
        
             | akira2501 wrote:
             | The Java specification is bigger because it has to define
             | the entire Virtual Machine where a compiler can target
             | already defined architectures. I'm also not seeing much in
             | the way of "implementation details" in their specification.
             | Can you point out what you mean?
        
       | littlestymaar wrote:
       | _Many people on HN_ "Rust syntax is so ugly"
       | 
       |  _rustaceans_ "I love the Rust syntax so much I want it in Go
       | too"
        
         | Scramblejams wrote:
         | The author notes[0] that it keeps the Rust syntax to avoid
         | having to write a parser.
         | 
         | I have no issue with the syntax but I think the chance of
         | uptake would be considerably improved if the syntax were as
         | close to Go's as reasonably possible. That's because I estimate
         | Go programmers to be a better target for this than Rust
         | programmers, but maybe I'm wrong.
         | 
         | [0] https://news.ycombinator.com/item?id=36847594
        
           | speed_spread wrote:
           | Having a soft-Rust alternative is a recurring topic in the
           | Rust community and is acknowledged as being of interest by
           | core members:
           | 
           | https://www.reddit.com/r/rust/comments/j2l9v9/revisiting_a_s.
           | ..
        
       | rthnbgrredf wrote:
       | Would it be possible to make a Python (without C extensions) that
       | compiles to Go?
        
         | funny_falcon wrote:
         | There was one: https://github.com/grumpyhome/grumpy
         | 
         | Looks like abandoned though.
        
         | cardanome wrote:
         | I am not sure you can easily directly transpile to Golang from
         | Python. Python is very, very dynamic and can have extremely
         | complex types that are not representable with the Golang type
         | system. Not impossible but I guess you might end up with an
         | extra runtime layer and some more dynamic operations will not
         | be very fast. Or you restrict it to a subset of Python like
         | this project does: https://github.com/zanellia/prometeo
         | 
         | You could of course write a bytecode VM in Golang but I guess
         | that defeats the purpose.
        
       | rdevsrex wrote:
       | It looks pretty interesting! Definitely something to play around
       | with, but honestly, I'd rather just use Rust (or Gleam if GC is
       | ok).
        
       | giovannibonetti wrote:
       | This seems to achieve a similar type safety<->complexity tradeoff
       | as Gleam [1] does. However, Gleam compiles to Erlang or
       | JavaScript, which require a runtime and are not as performant as
       | Go.
       | 
       | I wonder if Borgo's compiler messages are as nice as
       | Rust's/Gleam's, though.
       | 
       | [1] https://gleam.run/
        
         | ffsm8 wrote:
         | > are not as performant as Go.
         | 
         | Ymmv, you might be surprised if you actually bothered to
         | benchmark. Depending on the workload, either JS or erlang can
         | ultimately turn out on top.
         | 
         | They're all optimized to a degree that each has a niche it
         | excells at and leaves the others in the dust.
         | 
         | even with heavily scewed benchmark like techempower fortunes (h
         | ttps://www.techempower.com/benchmarks/#hw=ph&test=fortune&s...)
         | you end up with JS getting ahead of Go with raw requests. And
         | not just slightly, but by 1.5 times the throughput.
         | 
         | In other benchmarks, Golang does indeed win out with similar or
         | even bigger advantages... so the only thing you can ultimately
         | say is ... that it depends. Its a different story if you chose
         | other languages though. But JS, Golang and Erlang are all
         | _extremely_ optimized for their ideal usecase.
        
           | lolinder wrote:
           | I'd add Java to that list as well. JIT compilers have come a
           | long way, and OpenJDK was on par with Rust for performance on
           | the last project I tried porting.
        
           | hombre_fatal wrote:
           | Well hold on a second. The JS impl that you're talking about
           | uses a minimal custom runtime (https://github.com/just-
           | js/just) that you would never use--it barely implements JS.
           | It's basically only used for this benchmark. It doesn't make
           | sense to compare that to Go when we're talking about
           | Javascript vs. Go performance.
           | 
           | Scroll down to the "nodejs" entry for a more realistic
           | comparison.
        
       | DerSaidin wrote:
       | I like the graph at the top of the readme as a summary.
       | 
       | The rest of the readme focuses on the delta between Go and Borgo.
       | It doesn't say much about the delta between Borgo and Rust.
       | 
       | I think the delta there is mainly no lifetimes/ownership?
        
         | eximius wrote:
         | No traits, const generics, probably no turbofish equivalent for
         | when inference struggles.
        
           | sushisource wrote:
           | Most importantly: Null pointers still exist (yes I know they
           | technically exist in unsafe Rust, to head off any pedants)
           | 
           | Also: No `?` operator
        
             | jdknezek wrote:
             | There is a `?` operator: https://github.com/borgo-
             | lang/borgo?tab=readme-ov-file#error...
        
       | shepherdjerred wrote:
       | I would kill for these languages features in Go
        
         | neonsunset wrote:
         | That's what C# offers (except _true_ * Rust-style enums).
         | 
         | The latter will be there in one of the future versions and is
         | in an active design phase, which luckily focuses on tagged-
         | union implementation strategy.
         | 
         | With that said, you can already easily use one of the
         | Option/Result libraries or write your own structure - switching
         | on either is trivial (though you have to sometimes choose
         | between zero-cost-ness and convenience).
         | 
         | It already has struct generics, iterator expressions (LINQ),
         | switch pattern matching, good C interop and easy concurrency
         | primitives (no WaitGroup nonsense, also has Channel<T>). Oh,
         | and also portable SIMD, C pointers and very strong performance
         | in general.
         | 
         | * True as in proper tagged unions with either a tag or another
         | type of discriminant and aliased layout, instead of tag +
         | flattening all constituent parts into a one jumbo struct. Or
         | making it an opaque pointer to a box (like Java does, or C# if
         | you go inheritance/interface route). These don't count. I'm
         | curious about Borgo's lowering strategy for enums, but given Go
         | doesn't have those, I'm not holding my breath and expecting
         | something like F# struct unions at best.
        
           | mdaniel wrote:
           | As someone who is "C# curious," but haven't been able to keep
           | up with all the _horrific_ number of rebrands of the  "new,
           | open, .net, core, framework", what is the C# equivalent of
           | $(for GOOS in linux darwin; do for GOARCH in amd64 arm64; do
           | dotnet build -o thing_${GOOS}-${GOARCH}; done; done)?
        
             | nrr wrote:
             | That's spelled `dotnet publish -r ${GOOS}-${GOARCH}` with
             | the new ahead-of-time (branded Native AOT) compilation
             | features installed and enabled.
             | 
             | It isn't without a whole list of caveats if you're used to
             | Go's way of doing things though. See
             | <https://learn.microsoft.com/en-
             | us/dotnet/core/deploying/nati...> for details.
        
               | mdaniel wrote:
               | You're very kind, thank you
               | 
               | For others wanting to play along at home:
               | $ docker run --name net8 --rm -it
               | mcr.microsoft.com/dotnet/sdk:8.0-jammy-arm64v8 bash -c '
               | cd /root       dotnet new -d -o console0 console       cd
               | console0       dotnet publish --nologo --self-contained
               | -v d -r osx-arm64 -o console0-darwin-arm64       sleep
               | 600       '
               | 
               | although it didn't shake out                 $ docker cp
               | net8:/root/console0/console0-darwin-arm64/console0
               | ./console0       $ ./console0       Killed: 9
               | 
               | I tried with and without --self-contained and the biggest
               | difference was that self-contained emitted a bazillion
               | .dll files and without just emitted the binary. I case
               | the context isn't obvious, $(dotnet new console) is a
               | skeleton for the infamous WriteLine("Hello, World")
               | without doing crazy whacko stuff
        
               | neonsunset wrote:
               | For simple JIT-based but fully self-contained binaries,
               | without adding any properties to .csproj, the command is
               | a bit mouthful and is as follows                   dotnet
               | publish -p:PublishSingleFile=true -p:PublishTrimmed=true
               | -o {folder}
               | 
               | (you can put -p: arguments in .csproj too as XML attrs in
               | <PropertyGroup>...)
               | 
               | This will give you JIT-based "trimmed" binary (other
               | languages call it tree shaking). You don't need to
               | specify RID explicitly unless it's different from the one
               | you are currently using.
               | 
               | For simple applications, publishing as AOT (without
               | opting in the csproj for that) is
               | dotnet publish -p:PublishAot=true -o {folder}
               | 
               | Add -p:OptimizationPreference=Speed and
               | -p:IlcInstructionSet=native to taste.
               | 
               | Official docs: https://learn.microsoft.com/en-
               | us/dotnet/core/tools/dotnet-p...
        
               | mdaniel wrote:
               | You're also very kind, and I realized that it's possible
               | there were a bazillion "watch out"s on the docs and was
               | just trying the <PublishAot>true trick when I saw your
               | comment
               | 
               | However, it seems this brings my docker experiment to an
               | abrupt halt, and is going to be some Holy Fucking Shit to
               | re-implement that $(for GOOS) loop in any hypothetical CI
               | system given the resulting explosion
               | /usr/bin/sh: 2: /tmp/MSBuildTemproot/tmp194e0a13157b47889
               | b36abb0ce96cd2d.exec.cmd: xcodebuild: not found
        
               | neonsunset wrote:
               | You need an OS for which you are building to be able to
               | compile an AOT binary - it depends on OS-provided tooling
               | (MSVC on Windows, Clang on macOS and Linux, and a system-
               | provided linker from each respective system). In fact,
               | once ILC is done compiling IL to .a or .lib, the native
               | linker will just link together the csharp static lib, a
               | GC, then runtime/PAL/misc and a couple of system
               | dependencies into a final executable (you can also make a
               | native library with this).
               | 
               | Cross-architecture compilation is, however, supported
               | (but requires the same extra dependencies as e.g. Rust).
               | 
               | If you just want to publish for every target from a
               | single docker container (you can't easily do that with
               | e.g. Rust as noted), then you can go with JIT+single-file
               | using the other command.
               | 
               | Keep in mind that Go makes concessions in order for
               | cross-compile to work, and invested extra engineering
               | effort in that, while .NET makes emitting "canonical"
               | native binaries using specific system environment a
               | priority and also cares a lot about JIT instead (there
               | aren't _that_ many people working on .NET compiler
               | infrastructure, so it effectively punches above its
               | weight bypassing Go and Java and matching C++ if
               | optimized).
        
             | neonsunset wrote:
             | The sibling comment pretty much sums it up. But if you want
             | more detail, read on:
             | 
             | Generally, there are three publishing options that each
             | make sense depending on scenario:
             | 
             | JIT + host runtime: by definition portable, includes slim
             | launcher executable for convenience, the platform for which
             | can be specified with e.g. -r osx-arm64[0].
             | 
             | JIT + self-contained runtime: this includes IL assemblies
             | and runtime together, either within a single file or
             | otherwise (so it looks like AOT, just one bin/exe). This
             | requires specifying RID, like in the previous option, for
             | cross-compilation.
             | 
             | AOT: statically linked native binary, cross- _OS_
             | compilation is not supported officially[1] because macOS is
             | painful in general, and Windows <->Linux/FreeBSD is a
             | configuration nightmare - IL AOT Compiler depends on Clang
             | or MSVC and a native linker so it is subject to
             | restrictions of those as a start. But it can be done and
             | there are alternate, more focused toolchains, that offer
             | it, like Bflat[1].
             | 
             | If you just want a hello world AOT application, then the
             | shortest path to that is `dotnet new console --aot &&
             | dotnet publish -o {folder}`. Otherwise, the options above
             | are selected based on the needs either via build properties
             | or CLI arguments. I don't know which use case you have -
             | let me know if you have something specific in mind ("Just
             | like in Go" may or may not be optimal choice depending on
             | scenario).
             | 
             | [0] https://learn.microsoft.com/en-us/dotnet/core/rid-
             | catalog
             | 
             | [1] https://github.com/bflattened/bflat (can also build
             | UEFI binaries, lol)
        
           | orthoxerox wrote:
           | It's not the best solution, but an analyzer like [0] covers
           | most of the cases for reference types. For enums and struct
           | DUs in general we'll have to wait for language (or even
           | runtime) support.
           | 
           | [0] https://github.com/shuebner/ClosedTypeHierarchyDiagnostic
           | Sup...
        
           | shepherdjerred wrote:
           | To clarify, my team uses Go and prefers to stick with
           | "idiomatic" Go. So, while we could implement our own types,
           | there would be pushback. As an example I liked lo [0] but my
           | team was resistant because it's not considered idomatic.
           | 
           | If were up to me we'd be using a language with a better type
           | system :)
           | 
           | [0]: https://github.com/samber/lo
        
       | jjnoakes wrote:
       | What's the license?
        
       | fl0ki wrote:
       | It's a little suspicious the example uses math/rand.Seed() which
       | has been deprecated for over a year. That's when I noticed the
       | repo itself hasn't had a single commit in 7 months.
       | 
       | Why is this suddenly news, when by all appearances it's
       | abandonware?
        
         | OJFord wrote:
         | > Why is this suddenly news, when by all appearances it's
         | abandonware?
         | 
         | Because the submitter suddenly found it, and it was new to many
         | others too? It's not a 'Show HN'.
        
       | OJFord wrote:
       | Why compile to Go rather than less-than-ideal (or even slightly-
       | unsafe) Rust?
       | 
       | I find it conceptually compelling, I'm just surprised the target
       | would then be in the GC'd, larger-binary'd direction. Like 'Java
       | expressiveness with C simplicity, transpiles to Java'.
       | 
       | Perhaps 'just' because it's a lot simpler to just expand the
       | target language slightly and then you only have to deal with
       | mapping the new bits into implementation, it's less like writing
       | a compiler for a whole new language?
        
       | outside1234 wrote:
       | Nice - it uses Rust Try syntax to solve error conditions and Rust
       | style enums!
       | 
       | Which of course begs another question but I won't be that Rust
       | fanboy
        
       ___________________________________________________________________
       (page generated 2024-04-30 23:01 UTC)