HN user

netvl

20 karma
Posts0
Comments23
View on HN
No posts found.

Yes, almost every day.

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.

So this is a direct reimplementation of your example in Java - https://gist.github.com/netvl/32698cc97b88267fecee9b30f00d16...

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.

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.

Typo, yeah :( I don’t agree that it is true)

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.

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.

edit: formatting, explanations

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.

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.

I use one sim card for day-to-day life in the US, and another sim card from my home country to interact with digital services there, when needed.

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”.

Genders.wtf 4 years ago

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.

The key benefit of the Kotlin DSL is that in this precise example, IDEA does suggest valid stuff: https://imgur.com/a/vFYNIU1

Kotlin DSL is miles ahead of Groovy in terms of discoverability and IDEA integration. With Groovy DSL, most of the build script is highlighted with various degrees of errors and warnings; with Kotlin DSL, if something is highlighted, it is a legitimate error, and vice versa - if no errors are detected by IDEA, then it is almost certain to work.

There were rough spots of IDEA integration a couple years ago, but now it is close to perfect, within Gradle's limits of course (due to sheer dynamic nature of it, some things are just not possible to express in a static fashion, unfortunately). The biggest obstacle to Kotlin DSL use might be that some of the plugins use various Groovy-specifc features which are hard to use from Kotlin, but thankfully most of the plugins either fix those, or are rewritten in Java or Kotlin instead.

The whole point of a local date is that it is just a container for three values - year, month and day, and nothing more than that. You cannot go from `Instant` to `LocalDate` without specifying time zone/offset information, and vice versa.

“Local date” is a useful concept on its own, and it is not at all always derived from an absolute instant of time. Some examples:

1. Date in a file/directory name, which often happens with big data processing. There is no way to tie these dates to some absolute frame of reference without external information, but it is often not really necessary, and there is still a need to work with these values as dates, e.g. compare them or compute offsets.

2. Anything which is tied to the user’s local time frame, e.g. alarms. They simply cannot be tied to some absolute time reference, because they always represent some time wherever the user is located right now. Even birthday is something like this, because for the purposes of celebration, people care about the specific calendar day, not the actual moment of time in whatever absolute time scale there is (at least, most of the people I know think like that!)

Fish shell 5 years ago

#159 kind of works with the `string collect` mechanism, although it is indeed not very obvious, compared to bash:

    set file_contents (cat filename | string collect -N)
I understand that this is purely anecdotal, but I'm using fish for quite a long time, I've written a lot of tooling for myself in fish, and I agree that sometimes there are some things which are annoyingly missing from fish (like this multiline variable thing), but I would not say it makes fish significantly less powerful. And these things are sometimes fixed, too.

Android apps are written in Kotlin, and Gradle config is also written in Kotlin. How come it is different from the JS situation? Even though Gradle can be configured in Groovy, and Android apps can be written in Java, it is still the same ecosystem - basically, the situation of TypeScript/PureScript/WhateverScript and JavaScript.

Gradle wrapper is just a name for a script (automatically created by Gradle btw) which allows one not to have any kind of Gradle-related tooling installed on the machine (basically, to run build tasks you execute `./gradlew someTask`, and it takes care about downloading and running the appropriate Gradle version) - which I think is a clear benefit over the fact that you need to have `npm` installed system-wide or via a tool like NVM in order to build JS projects.

Gradle has its own warts, and a lot of them, but at least there is only one major build system in this area, and it is simply impossible for a library published to a Maven repo to be dependent on the build system it is built with.

While Gradle does have a lot of issues, some of the things you mentioned are not correct.

Don't forget you need a basic .properties file in META-INF that just gives out the plugin's name so it can discover it through reflection instead of having a proper API to do so.

Not really clear what do you mean, but declaring plugin names should not be done in properties, Gradle has syntax for declaring plugin ids inside its build config. If the plugin author haven’t used it, well, that’s on their conscience. Plugin users should never ever declare anything plugin-related in meta-inf.

And through some horrible logic, the name of your variable is what is exposed to Gradle.

This is a feature of Kotlin as a language - in it, delegates know the names of the properties they are used for. `lazy` is just the simplest use of the delegates feature, which happens not to care about property names.

Isn't it obvious that it's going to read a .properties file ? Not the values given through the -P flag when building though, because that would actually make sense.

This is simply untrue. Extracting properties this way most certainly will read them from .properties files and from all other sources of properties on a project, including the -P arguments.

Gradle does have a lot of issues, I can talk about them for hours (there are really nasty ones where there are no non-awful workarounds, for example, the built-in `tarTree` does not support symlinks in TAR archives, and there is no way to rebase the archive contents when extracting, i.e. to specify which directory of the archive to extract from, and these issues are very unlikely to be fixed, and these two are just the surface), but too many of your examples are somewhat wrong.

This post, as far as I can see, does not mention scala-meta-based macros (project called scalamacros I think) at all. What happened with this direction of macros development? Was it abandoned? Or is the new approach built on it?

As far as my understanding goes, performing a .so injection at least on Linux systems is much easier: you just need to set up an LD_PRELOAD variable before running the program and that's it. See, for example, here [0].

And it is sometimes useful. One thing I can recall when this was necessary when I had an old webcam which did not work with Skype (a native application, at that moment) under Linux because of incompatibility with V4L2. To make the camera work, I had to do the LD_PRELOAD trick to preload a compatibility library (see here [1], search for "v4lcompat"). Another example, provided in [0], is overriding the default memory allocator.

Another, more coarse-grained way to manipulate the way libraries are loaded is to use the LD_LIBRARY_PATH variable. I believe it is currently used by Steam to specify its own set of libraries.

Granted, this is not really a DLL injection as it is usually understood (adding code to a running process), but it is the same thing as described in the article, as far as I can tell.

[0] https://stackoverflow.com/questions/426230/what-is-the-ld-pr... [1]: https://wiki.ubuntu.com/SkypeWebCams

edit: grammar

Emoji.length == 2 9 years ago

I've never seen people using UTF-8 deal with a code unit stage. They parse directly from bytes to code points.

Well, that's probably because in UTF-8 code unit is byte :)

Quoting https://en.wikipedia.org/wiki/UTF-8:

The encoding is variable-length and uses 8-bit code units.

By definition, code unit is a bit sequence of a fixed size which can form code points. In UTF-8 you form code points using 8-bit bytes, therefore in UTF-8 code unit is byte. In UTF-16 it is a sequence of two bytes. In UTF-32 it is a sequence of four bytes.