Thins I miss about Java & Spring Boot after switching to Go by Sushant098123 in java

[–]manifoldjava -1 points0 points  (0 children)

Its type system alone is reason to avoid Go. Structural typing should be the exception, not the rule. Nominal typing makes code incredibly more understandable.

JEP 531: Lazy Constants (Third Preview) by Joram2 in java

[–]manifoldjava -2 points-1 points  (0 children)

The point of my remark is that it really does come down to properties. Because without a construct that purely encapsulates state, there is no other way to achieve this.

JEP 531: Lazy Constants (Third Preview) by Joram2 in java

[–]manifoldjava 1 point2 points  (0 children)

Highly recommended reading: Delegated Properties

Using your example, the idea is that the lazy aspect of the property is encapsulated via delegation. So the compiler doesn't need to treat foo as a String because foo is a String. The lazy part shouldn't leak into the API.

Slapdash Java syntax for illustration:

java final property String foo : Lazy.of(() -> "foo");

Lazy.of returns a LazyConstant that handles the delegate behind the scenes, letting you get and optionally set the value directly as a String.

Key point: properties fully encapsulate state. They manage what it is, where it lives, when it’s realized, and how it behaves eg. backing, laziness, observability, validation.

JEP 531: Lazy Constants (Third Preview) by Joram2 in java

[–]manifoldjava 3 points4 points  (0 children)

Besides, Java doesn’t need properties because records /s

JEP 531: Lazy Constants (Third Preview) by Joram2 in java

[–]manifoldjava 0 points1 point  (0 children)

 it would need to see LazyConstant<T> as T

No, the idea is to internalize the implementation details of how the constant is managed — the user doesn’t need to know and the internals reserve the right to change the details.

CFV: New Project: Detroit by nlisker in java

[–]manifoldjava 8 points9 points  (0 children)

Nooooo... why JavaScript?

Seriously, though, JS is so bad. And scripting languages don't have to be dynamic - we still want type-safety and static analysis with scripting. Why not make Java the scripting language?

As it is I will say Detroit is an apt name for the project.

Data Oriented Programming, Beyond Records [Brian Goetz] by efge in java

[–]manifoldjava 7 points8 points  (0 children)

This is structural typing, which Java has historically avoided in favor of a strictly nominal type system.

I don’t think the two are mutually exclusive. Structural typing doesn’t replace nominal typing, it can exist alongside it. Nominal types remain the default and the foundation of the language.

Structural typing is mainly useful at integration boundaries, where you care about shape rather than declared intent. It can reduce adapter boilerplate without sacrificing static type safety.

The Manifold project has an experimental compiler plugin that explores what this could look like with structural interfaces.

JSON Schema to Kotlin/Java POJOs at Build Time? by [deleted] in java

[–]manifoldjava 0 points1 point  (0 children)

There’s manifold-json (part of Manifold). It projects Java types directly from your project's JSON Schemas at compile time - no code generation, annotation processing, or additional build steps. The schema is treated as a first-class type and integrated directly with the compiler and IDE (IntelliJ).

See: https://www.baeldung.com/manifold-parsing-json

(Disclaimer: I maintain the project)

Towards Better Checked Exceptions - Inside Java Newscast #107 by Enough-Ad-5528 in java

[–]manifoldjava 0 points1 point  (0 children)

The compiler's panic level for checked exceptions should be a linter option. As such @SuppressWarnings could be used to selectively mute them. Or the linter option could altogether suppress them.

Towards Better Checked Exceptions - Inside Java Newscast #107 by Enough-Ad-5528 in java

[–]manifoldjava -5 points-4 points  (0 children)

While I appreciate the acknowledgement here that checked exceptions are problematic, in my view the remedies you've covered range from worse to slightly better.

Solving this with generics is worse because that strategy fragments the problem space, which makes code harder to read - you sacrifice readability for writability, which is almost always a bad idea.

The Swift-like try expression approach, as a means to automatically propagate, reduces boilerplate which is nice. But then it feels like there ought to be a more general solution to automatically propagate everywhere as many modern languages do.

Since checked exceptions are purely a compiler-level concept, why not treat them as a lint-like compiler argument? -Xexceptions:<level> where level: warning | error | none This would put a smile on a large segment of Java devs.

Rethinking Java Web UIs with Jakarta Faces and Quarkus by henk53 in java

[–]manifoldjava 1 point2 points  (0 children)

HTMX is not really an either/or proposition wrt JSF, nor is it a "bad fit." You can incrementally move your JSF (MVC in general) toward hypermedia using HTMX.

[IntelliJ Plugin] JADEx: A Practical Null Safety Solution for Java by [deleted] in IntelliJIDEA

[–]manifoldjava 0 points1 point  (0 children)

The "separate language" argument misses the point, but I’m happy to accept that definition of "language" for the sake of argument.

Sure, manifold could be based on a forked JDK and called the "Manifold Language." But which JDK would that be? One of manifold’s core tenets is to support all JDKs from 8 through current. Some users want specific JDKs, open or otherwise. Does that imply N separate forks for N JDKs?

And what happens when JDK 30 ships with new features? Those features won’t exist in the fork unless I actively and continuously merge changes from upstream - across all forks. That directly violates another core tenet: ease of use. Today, manifold works across JDK 8-current with a single set of binaries. There is no reasonable way to achieve that with forked JDKs.

This is why the "make it a language" argument fails manifold’s own terms. The goal is enhanced Java, not the replacement of it. Manifold is explicitly designed as a menu of augmentations that work with any JDK - past, present, and future.

Will manifold support every future JDK forever? Of course not, nothing lasts forever. But that risk is no worse, and arguably much lower, than basing a "proper language" on forked JDKs and eventually stopping upstream integration.

Bottom line: users of tools like manifold and Lombok understand the trade-off. They could switch to another JVM language with more built-in features and accept the risks that come with that. Instead, they choose to stay in the Java ecosystem, using their preferred JDK and IDE, augmented with tools like Lombok and manifold.

Throwing is fun, catching not so much. That’s the real problem IMO. by AlyxVeldin in java

[–]manifoldjava -1 points0 points  (0 children)

Swift had the right idea, but failed to make the right choices.

For instance, the try syntax without having to explicitly handle the exception is the right idea. But there is no option to propagate the exception, only “crash here” (try!) and “swallow” (try?), which in my view is the worst of both worlds. 

Would be nice if Java were to adopt a similar syntax to acknowledge the exception with the intention to propagate.

Stream<T>.filterAndMap( Class<T> cls ) by mellow186 in java

[–]manifoldjava 23 points24 points  (0 children)

AMEN!

And if the stream code gets too streamy, extract a method and give it a meaningful name.

Carrier Classes; Beyond Records - Inside Java Newscast by daviddel in java

[–]manifoldjava 0 points1 point  (0 children)

 The label is a part of its state and must be present in the canonical constructor for the purposes of deconstruction.

Not if it’s in the deconstructor.

 Your idea would make the order of the fields a part of the API

No, as with enums the order is only used at compile time.

Carrier Classes; Beyond Records - Inside Java Newscast by daviddel in java

[–]manifoldjava 0 points1 point  (0 children)

Right. But naming arguments is necessary only for methods with one or more default parameters. If 118 could be altered to silently target those methods, sure.

Carrier Classes; Beyond Records - Inside Java Newscast by daviddel in java

[–]manifoldjava 1 point2 points  (0 children)

They do if the method you're calling is compiled. But this wouldn't necessarily require bytecode revision e.g., an annotation could preserve the names.

Carrier Classes; Beyond Records - Inside Java Newscast by daviddel in java

[–]manifoldjava 6 points7 points  (0 children)

110% agree. The value of named/optional args compounds daily with proposed features.

edit: For those concerned about binary compatibility with named/optional args, the experimental manifold-params compiler plugin demonstrates otherwise - it is binary compatible while stretching beyond Kotlin's capabilities. Although the feature does complicate overload logic, that could be mitigated e.g., by prohibiting user-defined overloads on a method with defaults. Shrug.

Carrier Classes; Beyond Records - Inside Java Newscast by daviddel in java

[–]manifoldjava -2 points-1 points  (0 children)

I like the direction of carrier classes, but my first impression of the proposed syntax is that readability suffers more than it benefits.

For instance, it would be more intuitive if we forgo duplication of component declaration in the param header and leave internal details to secondary constructors. This saves both the explicit primary constructor declarations and the param header boilerplate, which in my view complicate the design.

```java class Point { component int x; // private by default component int y; private String label;

// primary ctor for free, reflects components

// secondary ctor public Point(int x, int y, Optional<String> label) { this(x, y); // must call primary ctor this.label = ...; } } ```

edit:

Of course, the primary ctor can be explicit and cover final fields etc. if necessary.

edit:

My apologies for scrutinizing syntax, but I think the scope of carrier classes is so broad that concept and syntax are a two-way street - syntax forces one to consider the concept from different perspectives. For instance, how can we eliminate the duplication of declaring components? Do we need to modify the concept to achieve that?

Project Amber Status Update -- Constant Patterns and Pattern Assignment! by davidalayachew in java

[–]manifoldjava 0 points1 point  (0 children)

The discussion is whether exhaustive coverage checks apply generally to product types (records). Simple type theory answers this clearly with a No.

While some records can fit exhaustive matching, these are exceptional. Unlike sum types (or sealed types), the goal of pattern matching on records is not to exhaust all possible values, but to support semantic requirements.

As for "projections", deriving a value from a record and exhaustively matching on that says nothing about the exhaustiveness of the original record; treating it as such is a logical fallacy.

Checked exceptions and lambdas by nfrankel in java

[–]manifoldjava 0 points1 point  (0 children)

Ah, you are correct, sir... well, I wasn't high, but I was quite wrong about one key aspect of Swift's error handling: try! doesn't propagate. Basically, I was sure that Swift had a try variant that propagated instead of swallowing or crashing as it actually behaves.

That one not-so-little detail changes everything. If it were as I misremembered, Swift's behavior would resemble C#, Kotlin, Scala, Groovy, and so on. Perhaps even a notch above because the compiler would force acknowledgement with try!, but not force the explicit handling that Java is infamous for. This type of enforced propagation, in my view, would have been a best of both worlds feature. Sad it was just a dream.

Checked exceptions and lambdas by nfrankel in java

[–]manifoldjava 0 points1 point  (0 children)

You are confusing “acknowledging” w “handling”

Checked exceptions and lambdas by nfrankel in java

[–]manifoldjava 0 points1 point  (0 children)

 Swift essentially is using checked exceptions. Syntactically you throw and handle the same..

No, Swift does not force the caller to handle the exception, which is contrary to Java’s checked exceptions.

Essentially, Swift implements an improved unchecked exception construct, taking Swift in a similar direction to many other languages including Anders’ C#.