Hacker News .hnnew | past | comments | ask | show | jobs | submit | owlstuffing's commentslogin

Not having to run a mess of Linux commands to install software.

> Maybe this is just a question of taste but I never could get along with Javas (or Kotlin's) tooling

Are you joking? IntelliJ is without a doubt the best dev tooling environment available.


No, I'm not. Through university (and even before) I have access to their full suite. I have tried to use PyCharm, GoLand and Idea.

Idea was useful for Java but felt quite slow and even with vim bindings was a pain to navigate. Learning the shortcuts helped but it never got quite as fast as helix/vim for general editing (especially as my work usually is a polyglot). It might be the best for Java (compared to eclipse or bluej) but that does not mean it fits my workflow/way of work.

PyCharm/GoLand both are "nice" but it did not feel better/more efficient than pylance/pyright)/gopls + vscode/helix. The only I still occasionally use is DataStorm as it is quite a nice SQLite/PostgreSQL client.

edit: fixed typo from gostorm -> goland


GoStorm?


Thanks for noticing the typo, must've mixed up the PHP and Golang IDEs


"industry purposes" likely equates to "enterprise software development." And that assertion is 100% correct.


Go can't compete with Java bc it's not in the same category as Java.

- Java is a high-level, multi-paradigm programming language

- Go is designed as a systems language to supersede C projects at Google

Now Go identifies as a general purpose language that competes with Java? It's a free country, I guess.


How is Go not high level? What makes it "systems" language? That's just marketing.

It is a language with a fat runtime, running a garbage collector. You just burn it into the binary and call it a day.


(just like modern Java can burn its runtime / GC into the binary)


No, not just like. You're downplaying significant differences between the two that do in fact matter. So much so in fact, that you're just wrong. Stop spreading misinformation.


GraalVM indeed does a lot more than Go, it's a full optimizing compiler while Go does very little optimiations.

But burning a JVM next to a jar file is not hard at all, one could make something like cosmopolitan.


Go use cases overlap the most with Java. I think the reputation you mentioned comes from Google using a lot of C++ for high-level things others would likely do in Java, so they see Go as a replacement for C++ in some areas. (assuming you meant C++ not C)


> I think the reputation you mentioned. . .

Actually no. Go was designed from the beginning as a systems language as a C replacement.


In what way does that "design" show up in Go, besides marketing?


It's replete with oddities and limitations that signal "ah, this is because systems language."

Go’s type system, for example, is very much a systems-language artifact. The designers chose structural typing because it was lighter weight, but provided enough type safety to get by. It sucks though for enterprise app development where your team (and your tooling) are desperate for nominal typing clarity and determinism.


The error handling is like a systems language for sure, I'll agree on that.

But where do Go's docs or founders call it a C replacement? gf000 asked where this is mentioned besides marketing, but I don't see it in the marketing either.


Now that Go is styled as a Java competitor its framing is different. But here's an old golang.org archive for fun:

https://web.archive.org/web/20091113154831/http://golang.org...

The main page title *Go: a systems programming language*

It still sports all the low-level stuff too, pointer arithmetic and all.


Thanks. I'm not surprised they called it a C++ competitor back then. All those systems-style features do make it awkward now that it's targeting the Java-like use cases. No pointer arithmetic, but pointers yeah, and it's not very clear what you're supposed to pass by value vs by ref. You can do things like a DBMS in Go that count as systems programming, but for sure it's not a competitor with C.

Go happened to be attractive for web backends too because it had good greenthreading before Java etc did, and better performance than JS, so it makes sense that they changed the marketing.


And a fat runtime with a garbage collector. Like people can write all sorts of programs with a GC, that was never the issue.

But then just stay truthful, otherwise C# is also a system PL.


"Fat" runtime? Go? Nah.

Go's runtime is thin: goroutines, a GC specialized for concurrency, networking, and little else. Java, by contrast, assumes a JVM plus massive stdlibs to handle everything from enterprise apps to big-data, making its platform genuinely "fat" and layered. Other Java-tier languages, C# included, follow the same model.


I agree Go's runtime is as thin as runtimes get. But having a runtime at all disqualifies it from being a C replacement. Rust is trying to replace C, Go is trying to replace Java and some of C++.

Even Rust has a runtime. Compared to that Go's is absolutely fat though.

java has had profiles for an eternity and multiple jvm implementation. it can get really really thin.

also has modules now.


> We now know that we prefer composition over inheritance

When people say "composition over inheritance" in Java discussions, they usually mean the trivial modeling rule: prefer has-a over is-a.

But that’s not what composition is really about.

The deeper idea is interface composition -- building types by composing multiple behavioral contracts behind a single cohesive surface.

Java provides inheritance and interfaces, but it doesn’t provide first-class delegation or traits. So most developers never really practice interface composition. They either subclass, or they wire objects together and expose the wiring.

The slogan survived. The concept mostly didn’t.

The manifold project, for example, experiments with language-level delegation to make interface composition practical with Java.

https://github.com/manifold-systems/manifold/blob/master/man...


> Java provides inheritance and interfaces, but it doesn’t provide first-class delegation or traits.

I'm not sure I am missing first class delegation much (not a lot of UI projects in Java these days).

But interfaces with default (and static) method implementations are actually quite usable as traits / mixins. Since Java 8 IIRC.

You can also pass around functions / lambdas (coincidentally also since Java 8) to compose functionality together. A bit harder to follow and/or understand, but another perfectly legitimate and very powerful tool nevertheless.


Well, what mainstream language has better tools for composition?


Rust with traits and Swift with protocols


So just type classes?

How does a type class help with composition? They do help with the expression problem (adding support for an "interface" after definition), and via parametric polymorphism they might give you a bit with regards to composing two traits.. but you do also have generics in Java, even if not as good as type classes.

So anyways, I don't see as big of a change here. But there was a Brian Goetz mail/presentation somewhere where he talked about adding "basically type classes" to Java? But unfortunately I couldn't find it for you now.



kotlin


Kotlin's "delegation" feature isn't true delegation, it's just call forwarding, which is better than nothing, but it falls down pretty quickly as an alternative to implementation inheritance.

The manifold project provides true delegation[1] for Java.

1. https://github.com/manifold-systems/manifold/blob/master/man...


Yes, the empty infix operator is often called the "juxt" operator, which is an apt term here.

However, I use the term "binding expressions" intentionally because there’s more going on than ordinary juxtaposition. In a normal juxt expression such as:

    a b c
the evaluation order is static and independent of the type system:

    (a b) c
With binding expressions the precedence is type-directed, so the type system determines which grouping is valid:

    (a b) c
    a (b c)
Additionally, the operation itself can be provided by either operand. For a given expression a b, the compiler may resolve it as:

    a.prefixBind(b)
    b.postfixBind(a)
For example:

    10kg
Here kg is a MassUnit, and MassUnit defines postfixBind(Number) returning Mass, so given there is no left-to-right binding, the expression resolves right-to-left as:

    kg.postfixBind(10)
So while juxtaposition is the syntactic surface, the semantics are type-directed binding.


> California's new speed camera pilot (AB 645) explicitly solves for this... like parking tickets

That makes the Florida judge's framing of red light cameras as a revenue generating scheme even more applicable. More than that, it ambiguates the crime.


> The drawback is that building an AST now requires a symbol table

Well, yes and no. During AST building a binding expression resolves as an untyped polyadic expression. Only later during the compiler's type attribution phase does a binding expression's structure resolve based on the operand types.

https://github.com/manifold-systems/manifold/tree/master/man...

> in typical code you don’t have the case of constant values so often.

Agreed. It's not really useful with inlined expressions:

   Schedule contacts.select(contactId) inputForm.getDateTime()
but if you write it like:

   var plumber = contacts.select(contactId)
   var date = inputForm.getDateTime()
   var building = findLocation(warehouse)
   Schedule plumber on date at building
But, honestly, I can't say I personally use it that way ;)

Initially, I wrote it as a science extension to Java: https://github.com/manifold-systems/manifold/tree/master/man...


Author here.

Yes, technically this is a form of backtracking, similar to what a parser does. The key difference is that the search is drastically constrained by the type system: reductions are only attempted where the types actually support a binding operator. Unlike a parser exploring all grammar possibilities, this mechanism prunes most candidates automatically, so the compiler efficiently "solves" the expression rather than blindly exploring every syntactic alternative.

Here is the high-level explanation of the mechanism:

https://github.com/manifold-systems/manifold/tree/master/man...

But the short answer is that it’s not parser-style backtracking over a grammar.

The Java parser still produces a normal AST for the sequence of tokens. What happens afterward is a type-directed binding phase where adjacent expressions may bind if their types agree on a binding operator. The compiler effectively reduces the expression by forming larger typed expressions until it reaches a stable form.

The algorithm favors left associativity, but since a type can implement the binding operator as either the left or right operand, the overall structure of the expression can emerge in different ways depending on the participating types.

So rather than exploring grammar productions, the compiler is solving a set of type-compatible reductions across the expression.

For example:

    2026 March 10
reduces roughly like this:

    (2026 (March 10))
    → March.postfixBind(2026)  // → LocalYearMonth
    → [retreat]                // → no binding with 10
    → March.prefixBind(10)     // → LocalMonthDay
    → .postfixBind(2026)       // → LocalDate
And if `Month` binds with `Range<Integer>`:

    2026 March 10 to 13
can reduce as:

    (2026 (March ((10 to) 13)))
The meaning is therefore determined entirely by which types participate in binding e.g., `LocalDate`, `Month`, `Integer`, `Range`, etc. and which reductions they define.

If a competing interpretation exists but the types don’t support the necessary bindings, it simply never forms.

In that sense it behaves less like a traditional parser and more like a typed reduction system layered on top of the Java AST.


100% agree.

The frequency of primarily AI-guided PRs is getting out of hand, particularly the whole codebase oriented type: “this PR improves performance, fixes bugs, and refactors random chunks of code.” The cherry on top is the author never attempting to verify the claims of the PR.

A PR should be a focused, cohesive body of code that targets a predetermined, well articulated goal.

Personally, I do not review widely scoped PRs esp. the AI-driven ones. Wasted far too much time chasing down false positive claims and reviewing junk code.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: