I spend approximately 60-70% of my time working with the headset on, connected to my MacBook. It’s actually better for me than my physical display because of the Zeiss inserts - I usually don’t wear glasses, so due to inserts, the desktop is subjectively crisper than the monitor :) I really can’t wait for visionOS 2 improvements in the virtual display feature.
Most of the media content I consume alone, and Vision Pro is perfect for that, especially watching something before sleep - the headset does not light up the entire room (unlike a phone/tablet screen) and thus does not mess up my wife’s sleep.
One thing I surprisingly don’t use it for are “immersive” videos and other experiences like VR or MR games. I’m not quite sure why - I always plan to try something out, but never do it actually.
Yup - my correction is not very strong, I usually don’t wear glasses at all, and I was able to use Vision Pro without inserts just fine, but with inserts subjective sharpness is much better.
1 is really trivial and took me like 5 seconds to write:
public class Test {
public static void main(String[] args) {
System.in.transferTo(System.out);
}
}
2 is anything but trivial in any language, unless it is some kind of a language specifically designed to build gRPC programs.
Never versions of Java are quite pleasant to work with. There are a lots of quality-of-life improvements (switch expression, multi-line string literals, string templates (currently in preview), lots of useful stdlib APIs), as well as quite fundamental additions like Loom.
Ok, that's really convenient :) I suppose it would be much harder to do it without the transferTo function, but that would be beyond the point. I'll instead focus on the example 2.
> 2 is anything but trivial in any language, unless it is some kind of a language specifically designed to build gRPC programs.
> I suppose it would be much harder to do it without the transferTo function,
No, it would not:
public class Test {
public static void main(String[] args) throws Exception {
byte[] buf = new byte[4096];
int read;
while ((read = System.in.read(buf)) > 0) {
System.out.write(buf, 0, read);
}
}
}
I imagine it will look pretty much the same in the majority of languages which have similar I/O abstractions.
It is under 120 lines, uses Java SE API only, and the complexity is approximately the same. Go does have advantage of built-in selects and channels, which make parts of the logic nicer, but not by much IMO.
On the other hand, in Java almost no one uses standard library to write network apps like this. If I had to use external libraries, which would be the case in the majority of real-world projects, the implementation would look even better and clearer.
That's impressive. However, even the direct reimplementation has introduced a subtle bug - a connection that sends something other than "server" or "client" is left hanging and never closed (use nc with -N flag, and press Ctrl+D to send EOF to see what I mean - it should disconnect and yet it doesn't). While not a functional bug, it could still cause a DoS attack if someone wanted to hog all the available sockets.
In Go, this is avoided by `defer conn.Close()` which guarantees that the connection will be closed at the end of the function execution, no matter what. It's a sort-of nicer syntax of "try {} finally {}" that let's you write the cleanup code immediately after the setup code, instead of at the end.
> On the other hand, in Java almost no one uses standard library to write network apps like this
I'm curious about the way the average Java programmer would write such an application. Would you please write an example of such a program, using an external library that would make implementation both correct and easy to read?
I can try doing it later today, but I’m 100% sure that TCP example will look pretty much the same in Java, in terms of complexity.
> The gRPC protocol here is only an example. Feel free to use any protocol you like.
FWIW, this is a pretty huge change. gRPC is quite complex, as it includes protobuf, http/2 and its own RPC mechanism. A simple TCP protocol is peanuts compared to that.
Interesting concepts, but dependency on Bazel is meh :(
Also, there are some passionate statements about other languages:
> As it's currently defined, there's nothing requiring the two arguments to actually have the same type. In this trivial example, that may be fine, but if I were to actually want to ensure that two arguments both implement an interface and they both actually have the same type, then I'm out of luck - there's no way to statically encode this constraint in Java!
This is simply not true:
static <T extends Stringify> void prettyPrintPair(T x, T y)
I personally really dislike when people talk about any kind of language feature with strong negativity, while providing their solution as the superior one. There is a high chance that they are wrong, since different features in the same area have different benefits, and usually no one thing is “better” than another, whatever this means.
It does not - my M3 continues to keep the speed if I override autopilot with the steering wheel. If I press the brakes, then both systems are shut down.
After Java’s JSR-310 almost any other API in almost any other language looks broken or insufficient. Threeten’s modeling of different time types seems so powerful and natural - specifically, it has Instant (which is literally a nanosecond-precision UNIX epoch timestamp), then it has ZonedDateTime/OffsetDateTime, which are full timestamps with time zone or offset information, and LocalDateTime/LocalDate/LocalTime, which are basically these “naive” timestamps from Python. These are all different types, with well-defined conversion methods between them, so you can’t easily use an inappropriate type.
My personally most hated piece of date-related API is Go’s formatting API, with its asinine number-based patterns instead of something reasonable and conventional like strftime-like or Java-like symbols. What’s especially maddening in it is that it is so US-centric, with month coming before day in these number patterns, which does not follow unit size increase or decrease sequence.
> What’s especially maddening in it is that it is so US-centric, with month coming before day in these number patterns,
Whether this particular bit of design is good or not, you'll certainly be hard pressed to find someone who has a reasonable argument in favor of the absurdity that is the Go date-time format string.
> 2006-01-02 (aka 'yyyy-MM-dd')
> January 02, 2006 (aka 'MMMM dd, yyyy')
> Jan-06 (aka 'MMM-yy')
> Monday (aka 'EEEE')
It's insanity start to finish and it boggles the mind how it was ever accepted in the language spec.
This is not true for Maven and overall the general Java ecosystem. Your own build may have arbitrary logic, true (this holds for Maven, Gradle, SBT - virtually any build tool for JVM), but the artifacts which are distributed to consumers of libraries never have anything which gets automatically executed by the build process of the consumer. build.rs and equivalents, however, are a part of the package itself and are executed when the package is “depended on”.
> but the artifacts which are distributed to consumers of libraries never have anything which gets automatically executed by the build process of the consumer
What if I build everything from source, including all libraries? (That is, do not consume any .jar files but build them myself). I would surely need to run the build step of every library right?
You’re right in that knowing pronouns is sufficient to determine grammatical gender of words to be used with relation to a character in Russian. Combining a particular gender of pronoun with an unmatching form of verbs/nouns/etc is definitely not a part of the language, even outside some formal norms.
One possibly unobvious thing is, though - there are only three grammatical genders in Russian, so all words which do have gendered forms can have at max 3 of them (male/female/neuter). This means that if you do allow more than 3 kinds of pronouns, you’ll probably have to define the pronouns->grammatical gender mapping somehow. Well, I guess plural variant also counts, so maybe 4.
The problem with SparkJava is that it is not maintained anymore :( according to GitHub, meaningful work on it last happened in 2020. It was indeed a great tool, but now I’d choose Javalin since it is maintained, or even better, Ktor if I’m using Kotlin.