HN user

uzerfcwn

39 karma
Posts0
Comments44
View on HN
No posts found.

my understanding is a "clean room" reverse engineering for interoperability was fair use and not a copyright violation

To my understanding, reverse engineering algorithms and interfaces is not a copyright violation since those cannot be copyrighted (i.e. fair use is not relevant). However, a WoW server also distributes e.g. quest texts, which most certainly are copyrightable, since the collective of all quests is comparable to a fantasy novel.

In backend terms (which isn't really relevant in court but helps illustrate the division), every WoW server is said to have a "core" that contains the gameplay logic (netcode, movement, hit rolls, object interactions, etc.) and a "world database" (item names and stats, NPC names and stats, quests, etc.). The core might be considered a collection of clean room reverse engineered algorithms, which aren't copyrightable. However, the world database is full of copyrighted material, and a server distributing that data to clients will violate Blizzard's copyrights. You could avoid this by deleting all of Blizzard's stuff from the world database and writing your own content, but it's not relevant here since Turtle WoW didn't do that.

Nonetheless, vbezhenar's point stands because there are open source server implementations that host both the core and the database on Github, see e.g. https://github.com/cmangos/mangos-tbc and https://github.com/cmangos/tbc-db.

An incoherent Rust 4 months ago

I don't know what quotemstr was specifically talking about, but here's my own take.

The ideal error handling is inferred algebraic effects like in Koka[1]. This allows you to add a call to an error-throwing function 15 layers down the stack and it's automatically propagated into the type signatures of all functions up the stack (and you can see the inferred effects with a language server or other tooling, similar to Rust's inferred types).

Consider the following Rust functions:

    fn f1() -> Result<(), E1> {...}
    fn f2() -> Result<(), E2> {...}
    fn f3() -> Result<(), E3> {...}
    fn f4() -> Result<(), E4> {f1()?; f2()?;}
    fn f5() -> Result<(), E5> {f1()?; f3()?;}
    fn f6() -> Result<(), E6> {f4()?; f5()?;}
Now, how do you define E4, E5 and E6? The "correct" way is to use sum types, i.e., `enum E4 {E1(E1), E2(E2)}`, `enum E5 {E1(E1), E3(E3)}` and `enum E6 {E1(E1), E2(E2), E3(E3)}` with the appropriate From traits. The problem is that this involves a ton of boilerplate even with thiserror handling some stuff like the From traits.

Since this is such a massive pain, Rust programs tend to instead either define a single error enum type that has all possible errors in the crate, or just use opaque errors like the anyhow crate. The downside is that these approaches lose type information: you no longer know that a function can't return some specific error (unless it returns no errors at all, which is rare), which is ultimately not so different from those languages where you have to guard against bizarre runtime errors.

Worse yet, if f1 has to be changed such that it returns 2 new errors, then you need to go through all error types in the call stack and flatten the new errors manually into E4, E5 and E6. If you don't flatten errors, then you end up rebuilding the call stack in error types, which is a whole different can of worms.

Algebraic effects just handle all of this more conveniently. That said, an effect system like Koka's isn't viable in a systems programming language like Rust, because optimizing user-defined effects is difficult. But you could have a special compiler-blessed effect for exceptions; algebraic checked exceptions, so to speak. Rust already does this with async.

[1] https://koka-lang.github.io

Group theory entering quantum physics is a particularly funny example, because some established physicists at the time really hated the purely academic nature of group theory that made it difficult to learn.[1]

If you include practical applications inside computers and not just the physical reality, then Galois theory is the most often cited example. Galois himself was long dead when people figured out that his mathematical framework was useful for cryptography.

[1] https://hsm.stackexchange.com/questions/170/how-did-group-th...

When I run 'notepad dir1/file1.txt', the package should not sneakily be able to access dir2.

What happens if the user presses ^O, expecting a file open dialog that could navigate to other directories? Would the dialog be somehow integrated to the OS and run with higher permissions, and then notepad is given permissions to the other directory that the user selects?

My favourite feature is userChrome. The default chrome sucks in both Chrome and Firefox, but at least Firefox allows me to customize it to my liking without forking the entire browser.

On the flip side, changing keybinds in Firefox requires forking, but the defaults aren't too bad.

Last month, a Finnish court judged that using derogatory words in an email sent privately to the offended person counts as defamation.[1] When this was discussed in the Finnish Reddit [2], some found it unjust that it counts as defamation even though the message wasn't sent to third parties, but it is indeed how the law was written.

[1] https://www.iltalehti.fi/kotimaa/a/6c9a65fe-f706-449e-b0d9-1...

[2] https://old.reddit.com/r/Suomi/comments/1mv9usq

The core difference between sums and unions is that sum types have cardinality |A+B| = |A| + |B|, whereas union types have cardinality |A∪B| = |A| + |B| - |A∩B|. As you noted, type systems with union types, such as Typescript, also support sum types because you can create disjoint wrapper types (like Ok and Err) and their union type will be semantically equivalent to a sum type, since the intersection is an empty set. In this sense, union types are strictly more powerful than sum types.

The downside is that union types require some notion of subtyping, since otherwise A∩B is always empty for distinct A and B. Unfortunately, subtyping is apparently very difficult to implement in HM-like type systems (like Rust and ML) such that it plays well with type inference.[0] Hence, the downside of having union types in a language is that users have to write out types more often.

Unlike kibwen, I don't think Rust's type system is particularly essential for new languages. It's a design choice where one side has more powerful types but the other side has more powerful type inference.

[0] https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_sy...

Most web apps today use APIs that return JSON and are called by JavaScript. Can you use REST for such services

You kind of could, but it's a bad idea. A core tenet of the REST architecture is that it supports a network of independent servers that provide different services (i.e. webpages) and users can connect to any of them with a generic client (i.e. a web browser). If your mission is to build a specialized API for a specialized client app (a JS web app in your example), then using REST just adds complexity for no reason.

For example, you could define a new content-type application/restaurantmenu+json and build a JS client that renders the content-type like a restaurant's homepage. Then you could use your restaurant browser JS client to view any restaurant's menu in a pretty UI... except your own restaurant's server is the only one that delivers application/restaurantmenu+json, so your client is only usable on your own page and you did a whole lot of additional work for no reason.

does REST require a switch to HTML representation ... How such HTML representation can even use PUT and DELETE verbs

Fielding's REST is really just an abstract idea about how to build networks of services. It doesn't require using HTTP(S) or HTML, but it so happens that the most significant example of REST (the WWW) is built on HTTPS and HTML.

As in the previous example, you could build a REST app that uses HTTP and application/restaurantmenu+json instead of HTML. This representation could direct the client to use PUT and DELETE verbs if you like, even though these aren't a thing in HTML.

Feel free to write a bug report to Chrome developers or ManifestV3 authors. In the meantime, Firefox users can override any delivered content with the webRequest API.

To me, the cool (and uncommon in other languages' standard libraries) part about C++ ranges is that they reify pipelines so that you can cut and paste them into variables, like so:

    auto get_ids(std::span<const Widget> data)
    {
        auto pipeline = filter(&Widget::alive) | transform(&Widget::id);
        auto sink = to<std::vector>();
        return data | pipeline | sink;
    }

That looks more like ad hoc union types than sum types. What happens if you do:

    data FooResult = Number | Number
If you can't distinguish the two cases, then it means they're not an actual sum type, since e.g. the set size is |FooResult| = |Number| whereas a sum type should have 2*|Number|.

The reason ad hoc union types are avoided in Hindley-Milner (HM) languages is that their usability depends on subtyping, which is incompatible with HM. You could get around this by saying that ad hoc sum types require the types to be distinct, but this would greatly impede usability. For example:

    ErrorA = FileNotFoundError | ParsingError
    ErrorB = FileNotFoundError | PermissionError
    ErrorC = ErrorA | ErrorB // Oops, trying to ad hoc sum FileNotFoundError twice
The tried and true solution in HM is to use generic types like Result<A,B>, where you separate the cases with labels Ok and Err.

On the other hand, languages with subtyping aren't that averse to ad hoc union types. TS and Python already have them and C# is adding them soonish [1].

[1] https://github.com/dotnet/csharplang/blob/main/proposals/Typ...

Once, I wanted to write a C# function roughly like this:

  (T1, ..., Tn) Apply<T1, ..., Tn>((Func<P, T1>, ..., Func<P, Tn>) args)
This is not possible in C# because the language doesn't have variadic generics. Instead, I used runtime reflection and wrote something like this:
  object[] Apply(Func<P, object>[] args)
Although it worked, the downside is that the types T1, ..., Tn are no longer statically known, which means that the function's contract has to be written in comments and the caller has to check them manually. In contrast, C++ has variadic templates, which would allow the compiler to check the types automatically.

Exceptions are difficult to discuss because different languages implement exceptions differently, each with their own downsides. That said, I don't think anyone has an issue with bubbling. Even sum type proponents love Rust's ? shorthand, because it makes it easier to propagate Results up the stack.

The big issue with exceptions in C#, Python and JS is that they're not included in function signatures, which means you have to look up the list of possible exceptions from documentation or source code. This could be amended with checked exceptions like Java, but it allegedly doesn't mesh well with the type system (I haven't personally written Java to confirm this). And then there's the C++ crowd that slaps noexcept on everything for possible performance gains.

Personally, I like the way Koka does exceptions with algebraic effects and type inference. It makes exceptions explicit in function signatures but I don't have to rewrite all the return types (like in Rust) because type inference takes care of all that. It also meshes beautifully with the type system, and the same effect system also generalizes to async, generators, forking and other stuff. Alas, Koka is but a research language, so I still write C# for a living.

JSON Patch 2 years ago

You can add to the end of an array by using the path /.../myarray/-, i.e., the index is replaced by a dash.

JSON patch is indeed not idempotent.

The dataset Github page https://github.com/simonalexanderson/MotoricaDanceDataset does mention some missing finger data:

Session 2: Casual dancing ... No finger motion.

Session 3: Vintage jazz dancing ... Fingers captured with Manus gloves, which unfortunately suffered in quality due to sensor drift during rapid motion.

Session 4: Street dancing ... Simplified finger motion (markers on thumb, index finger, and pinky according to the OptiTrack layout).

The first video in the article does have a bit of finger motion, so I'm guessing it's from session 4. Toes also look a bit iffy and clip into the ground instead of curling at times.

It seems like the author had some very specific read and write pattern in mind when they designed for performance, but it's never explicitly stated. The problem setting only stated that "reads are more common than writes", but that's not really saying much when discussing performance. For example, a HTML server commonly has a small set of items that are most frequently read, and successive reads are not very strongly dependent. On the other hand, a PIM system may often get iterative reads correlated on some fuzzy search filter, which will be slow and thrash cache pretty badly if the system is optimized for different access patterns.

When designing software, you first need to nail down the requirements, which I didn't really find in TFA.

Then there are other webapps which seem to implement their own login flow: they figure your session is expired, but don't allow you to switch accounts. The only way to use a different account from this flow is to sign out of the current one, which, of course, signs you out from everywhere.

Container tabs[1] are great for these. My work browser has a separate container for each of my frequently used Azure logins. When I need to use one of those pesky apps, I just open it in the respective container.

[1] https://addons.mozilla.org/en-US/firefox/addon/multi-account...

I find it interesting how the author's first approach was to use a black box neural network instead of the evidently simpler beam search. As far as I'm aware, beam search was widely considered to be the simple method for game optimization just a decade ago.

Sure, new methods will always replace old methods, just like CNNs replaced SIFT for image processing. However, I feel that beam search is one of those elementary methods that you'd always want to check first, similar to A* and quicksort. Even though there are fancy neural networks for game optimization, pathfinding and sorting, it's easier to get started with elementary methods because they're simple and tractable.

As an end user, I love when web applications pass events through the DOM tree, because it allows me to easily create plugins by hooking on the same events. Youtube is a prime example of how to do things right.

Unfortunately, modern frameworks really want to use their own event channels, which makes hooking a pain.

I agree. Cloud vs. Data Center is a big issue that doesn't get brought up enough when bashing Jira.

DC (and formerly Server edition) are pretty good products that do their thing fine and are fast enough for typical use. Unfortunately, Server edition was discontinued and DC is too expensive, so formerly happy developers are forced to switch to Cloud edition, which is horrendously slow. Jira Cloud also lacks some loved features, such as the plaintext comment editor [0].

[0] https://jira.atlassian.com/browse/JRACLOUD-72631

One can only imagine what would happen if the Finnish government tried to ban sympathy strikes in the same way the US government has here.

Although it's not quite on the level of US bans, the new Finnish government is currently trying to restrict sympathy strikes and political strikes, so we'll see how that goes. Trade unions are already throwing jabs with 1-day strikes and uppercuts are probably coming next year.

[0] https://yle.fi/a/74-20051635

I use spreadsheets for all kinds of bookkeeping, and very often there's some data you need to fetch once when a new entry is created, be it stock prices from a webpage or calendar entries from Outlook. LibreOffice's python scripts are great for those cases, because the tooling is just plain better than VB. Alas, VB is still necessary for formulae.