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