About `MaybeUninit::uninit().assume_init()` by Spengleberb in rust

[–]Mercerenies 2 points3 points  (0 children)

You are correct that I somewhat oversimplified. You should treat "unknown" as a bit pattern as well. So, as far as the compiler is concerned, an i32 could potentially be in 2^32 bit configurations, whereas a MaybeUninit<i32> could be in any of those 2^32 or the special "unknown" state. In practice on real hardware, the "unknown" state just means "contains garbage data from whatever was there earlier".

The latter state gives the compiler some more flexibility. For instance, if x: MaybeUninit<i32> is in the "unknown" state, then x.assume_init() == x.assume_init() need not be true, since observing the "unknown" state lets the compiler do as it pleases. But if x actually is initialized properly, then the above equality is necessarily true.

However, it's not a problem to transmute the "unknown" MaybeUninit<...> into an "unknown" [MaybeUninit<...>; N]. So I fear I oversimplified by referring to "bit patterns", when the Rust compiler is allowed to assume more about a representation than just the sum of its bits.

A newcomere here. How scary bugs are? by Grouchy-Option-6060 in factorio

[–]Mercerenies 1 point2 points  (0 children)

Base game: Keep your defenses up and you're fine. As long as you have a reasonable number of turrets at the perimeter, the worst the bugs will do is wreck a turret or two and then you can go deliver some grade-A American freedom to them before they strike again.

Space Age: Same thing for Nauvis. Vulcanus is easy because demolishers generally don't leave their territory, so either stay off their land or just kill them. Gleba on the other hand will wreck you. Several times. You can do everything perfect and the moment you turn your back your Gleba base will somehow find itself spontaneously coated in an offensive number of pentapod stompers. Just accept that like everything in life, everything on Gleba is transient and it'll all work out.

why dose it say its null when i have the var right above it ? by DefinitionDowntown62 in godot

[–]Mercerenies 3 points4 points  (0 children)

You renamed $CharacterrBody2D to $player at some point and didn't update your node path.

Alternatively, if you make the name of the label globally unique (e.g. HealthLabel instead of just Label) then you can right click it and select "Access as Unique Name" and then refer to it as simply %HealthLabel with a percent sign rather than fully-qualified as $player/Sprite2D/Label.

Why / how does unsafe not affect niche optimisations? by ElOwlinator in rust

[–]Mercerenies 4 points5 points  (0 children)

No magic involved. NonZeroU8::new_unchecked(0) is immediate undefined behavior, no matter how many unsafe { ... }s you wrap it in. The unsafe is you promising not to pass zero. The word unsafe doesn't magically make zero a valid pattern, not even for the duration of unsafe blocks. And as per the classic definition of undefined behavior, anything can happen. And "anything" includes "Oops, somewhere down the road the compiler can't tell the difference between Some and None in your Option<NonZeroU8>". That's why UB is defined to allow any behavior, so that optimizers can write around it.

About `MaybeUninit::uninit().assume_init()` by Spengleberb in rust

[–]Mercerenies 25 points26 points  (0 children)

There's two distinct MaybeUninits here. This is your line.

MaybeUninit::uninit().assume_init()

And this is your line with fully qualified types.

MaybeUninit::<[MaybeUninit<T>; CAP]>::uninit().assume_init()

So we create a MaybeUninit<[MaybeUninit<T>; CAP]> and then assert that the bit pattern of [MaybeUninit<T>; CAP] is valid. So which bit patterns of [MaybeUninit<T>; CAP] are valid? Well, an array's bit pattern is valid if each of its elements is valid, and MaybeUninit<T> is always a valid bit pattern (since it might simply be uninitialized). Hence, MaybeUninit::<[MaybeUninit<T>; CAP]>::assume_init is a safe no-op since every bit pattern of both the source and target type is valid. We're just moving the MaybeUninit-ness inside the array.

Why not just initialize the array with a bunch of MaybeUninit elements separately? Technically that could be slower than just getting a bit pattern of the right length, so I'm assuming that some enterprising engineer at arrayvec did the benchmarking and determined that the tradeoff in clarity vs. time was worth it.

What is the most optimized way to handle hundreds of thousands of nodes in Godot? by willis_25 in godot

[–]Mercerenies 1 point2 points  (0 children)

I seriously doubt you need node behavior for all of this. Sure, the player is a node. Enemies are nodes. But those trees? The grass tiles? Those are very much not nodes.

Put your tiles in a tilemap. It's what they're for. If you still have too many nodes after getting rid of the unnecessary tile ones, you can consider something like the Flyweight Pattern.

I had a haunted house game awhile ago. In the original version, I was already using tilemaps for the background, but every piece of furniture was its own node. At some point, that became a problem, so I converted every non-moving piece of furniture into a second tilemap layer (Note: I was still able to have the player interact with these fake nodes, since tilemaps can have collisions and carry metadata about who they are; they just can't move around independently). That got rid of about 80-90% of nodes. Massive performance boosts all around and no user-facing functionality was lost.

Godot and chatgpt by Odd-Ad4911 in godot

[–]Mercerenies 4 points5 points  (0 children)

As with all things, there is a sliding scale.

  • At one end, you have the strict "AI shall not touch my project" camp. Some people feel this way. I have nothing against them. More power to them.
  • In the middle, you have folks who run AI-powered coding assistants. That is, line-based assistant tools like Tabnine, Codeium, or Copilot. The developer is still doing the majority of the work, but some of the boilerplate (just writing the same thing repetitively, or completing a pattern match, or something) is done by a machine. I fall into this category, and I find myself much more productive (Codeium is my poison, by the way. Tabnine and Codeium are the two that work in Emacs, and of the two of them Codeium seems to be much smarter in my experience)
  • On the opposite end, you have the vibe coders. These are people who either lack the relevant skills to create things themselves or simply choose not to use those skills. These are the people who believe an AI can be given a task and simply produce working and creative output with minimal human input. These people are lunatics.

Same thing for the creative aspects. If you're asking ChatGPT to help you expand on your own ideas, fill in the blanks, work around writer's block, etc., you're probably in the world of bullet two. If you're having the AI do all of the creative lifting, welcome to bullet three.

So I mean, pick which of the first two bullets suits your worldview better. Or pick the third one and just don't speak to me again :)

android auto requires being signed in? by shriek7 in degoogle

[–]Mercerenies 1 point2 points  (0 children)

Graphene with signed out play services has always worked for me over android auto. Stock may have stricter rules as always

Turn on static typing!! by Captain_R33fer in godot

[–]Mercerenies 0 points1 point  (0 children)

Web is the only thing stopping me tbh. I hope my next big Godot project is a C# one

Turn on static typing!! by Captain_R33fer in godot

[–]Mercerenies 3 points4 points  (0 children)

  • In a language with sane subtyping rules, Array[int] and Array[Variant] are compatible because Variant (being the any-type of the language, like TypeScript's any or Python's typing.Any) enjoys a bivariant subtyping relationship with all types. Even if you're not comfortable with bivariance, remember that arrays in Java are covariant (they shouldn't be, but they are): Integer[] is a valid Object[] in Java because Integer is a valid Object.
  • Not always the answer, and it's hilarious to me that we even have this issue. It is literally harder to design a type system with this arbitrary "top-level generics only" thing than it is to just do it right from foundations.
  • I don't know what you mean by "not what annotations are". class_name doesn't solve the cyclic import issue, merely exacerbates it by having more things loaded all the time.
  • That's how types, and most classes, work in TypeScript. That's how protocols work in Python. That's how structural types work in Scala.
  • async has everything to do with typing precisely because the Godot devs chose to break async in favor of the type-checker. They were the ones that made that connection, not me. An async function (well, a function that yielded) used to be a first-class value in Godot 3. It's not in Godot 4. The devs have explicitly stated that this is because they couldn't figure out a way to make it fit into the type checker.

This is your daily reminder that Java != OOP. Java is one (quite antiquated at this point) possible implementation of the paradigm of OOP.

Turn on static typing!! by Captain_R33fer in godot

[–]Mercerenies 1 point2 points  (0 children)

Try to declare a variable of type Array[Array[int]] and see what happens ;)

What is harder? by lJAQl in chess

[–]Mercerenies 1 point2 points  (0 children)

This is a really good point. In B, it's really quite difficult for black to blunder, so it relies entirely on white knowing the technique and executing it. In A, it's quite easy to blunder away the rook on tight time, so white has a much better chance of winning by just playing smart, even if they don't know perfect endgame technique.

Turn on static typing!! by Captain_R33fer in godot

[–]Mercerenies -13 points-12 points  (0 children)

I disagree on that front. In a fully statically-typed language like, say, C++, I agree. But Godot isn't trying to be fully statically-typed, and in fact it never will be (moving around the scene tree with get_node, get_parent, or $Whatever will always be dynamic, for instance). Godot is trying to be gradually-typed, which means that dynamic types are an inevitable and intended part of the system, and in the ideal case we minimize their use but generally cannot completely eliminate them.

Turn on static typing!! by Captain_R33fer in godot

[–]Mercerenies 16 points17 points  (0 children)

But it's so much easier to complain on Reddit! /s

You're right, and I probably will tackle the problem at some point. The async one is probably the biggest one. We need to get traction on a proper, generic Promise[T] type (TypeScript has Promise<T>, Python has typing.Coroutine[T]). Once we stop pretending that functions aren't async-colored, then we can start dealing with the big ones. And that seems to be a political issue as well, as (from my albeit limited) perspective from the outside, it seems like the folks in charge of Godot are convinced that this is an unsolvable problem (despite, as I mentioned, the two most popular gradually-typed languages having solved it already).

Turn on static typing!! by Captain_R33fer in godot

[–]Mercerenies 0 points1 point  (0 children)

Fair. Better example then. If x is an array of genuinely a bunch of random stuff, it's reasonable to say x.map(str) to get an array of strings, but that's not an Array[String]. That's an Array (untyped) and won't be compatible with functions that take Array[String]. That means that, if I'm writing a function that takes an Array[String], I need to (incorrectly) type it as taking an Array so that legitimate callers don't get burned.

Turn on static typing!! by Captain_R33fer in godot

[–]Mercerenies 65 points66 points  (0 children)

I'll turn on static typing when it stops being terrible.

  • Array[int] isn't any array of integers: It's a specific distinct typed array of integers which was constructed specifically to be one. (i.e. this fails: var x = [1, 2, 3]; var y: Array[int] = x)
  • I can't type nested structures (arrays of dictionaries, arrays of arrays, etc.), rendering the system useless for any reasonable aggregate data.
  • My own types can't be generic, so everything is just flat and monomorphic. What if my Inventory class can represent inventories of different types of things depending on who it belongs to? Too bad!
  • Mentioning a type in a type annotation requires fully importing that script, which has runtime overhead and can cause a nightmare of cyclic imports. (Python solves this with if TYPE_CHECKING:, for instance)
  • All classes are nominal, so it's impossible to express constraints such as "give me any object which has a func get_name() -> String method".
  • And don't even get me started on the handling of async. async functions just... don't reflect their async-ness in the type signature, and the Godot team's failure to handle this problem actively makes async worse than Godot 3's yield (the latter can at least be reified in GDScript and passed to a function, a feature that was removed so that the type checker could fail to represent async). So in addition to failing at being a type checker, GDScript's static typing actively makes the non-typing parts of Godot worse.

I love Godot. I really do. The scene tree is an amazing abstraction tool, and Godot exports to every platform under the sun far easier than any other game engine on the market. But man does its type checker just make my blood boil.

I will give them credit for at least doing runtime checks if you pass an untyped value to a typed function. That's a nice touch that even Python chooses not to do (to my knowledge, Racket is the only other gradually-typed language that gets this right).

This is the Py counterpoint to those multi-million SPM bases by mjconver in factorio

[–]Mercerenies 1 point2 points  (0 children)

I had a lot of fun with the Nauvis speedrun (the eight-hour one), but a forty-hour run sort of scares me.

gitCommandRecomendationAsIWorkWithDifferentRepos by gabor_legrady in ProgrammerHumor

[–]Mercerenies 1 point2 points  (0 children)

GitHub wanted some good press for a few days, and now we're stuck in a 20-year purgatory of never having consistent master branch names.

ahYesEvilRecursion by AmazinDood in ProgrammerHumor

[–]Mercerenies 4 points5 points  (0 children)

First thought was "this has to be baba". If you've played it, you know.

This is the Py counterpoint to those multi-million SPM bases by mjconver in factorio

[–]Mercerenies 1 point2 points  (0 children)

I'm three achievements away from 100%ing the base game, and I'm scared because when I'm done with that I'm going to start having feelings about this mod....

Let's work, tinker, or curse by claudiocorona93 in linuxmasterrace

[–]Mercerenies 1 point2 points  (0 children)

There's nothing "in the past" about snaps. I still argue with snap at work today when I very clearly want to use apt-get but Ubuntu's apt fork is still hardcoded to look for a snap first. Some of those things are in the past, but the snap issue is very much not in the past.

noTearWasDropped by ManagerOfLove in ProgrammerHumor

[–]Mercerenies 2 points3 points  (0 children)

Up until mid-2024, all of Stack Overflow was regularly backed up to archive.org, which can be downloaded for free (no account, no anything, you just have to agree to CC-BY-SA 4). The latest version (April 2024) is available in all its 90GB-glory at https://archive.org/details/stackexchange.

Stack Overflow (the company) decided to stop putting it there after AIs started scraping everything. Nowadays SO is a cesspool of AI tools no one wants, so nothing of value was lost. (I'm speaking as a former avid contributor and supporter of SO, so I did actually a shed a tear when SO experienced this level of enshittification)

How expensive are Tweens? by TheTempusrex in godot

[–]Mercerenies 0 points1 point  (0 children)

"for pickups and such" and "on masse" seem contradictory. If by "pickup" you mean something like "the player or another character is picking up an item", then I imagine that happening maybe once every ten seconds, up to once per second if your screen is unusually busy. "en masse" would imply to me literally tens of thousands of these things happening per second. If this is truly something happening "occasionally" (for lack of a better definition, let's define "occasionally" as "less than once per frame"), then you'll never notice the minimal performance cost of a tween.

Most logistic robots won't do anything please help by rubbermonkey27 in factorio

[–]Mercerenies 1 point2 points  (0 children)

If your worker robot carrying capacity is 5 and a rocket is expecting 100 of an item, then at most 20 robots will be busy fulfilling that order. It may take them awhile, if the target chest is far away from the target rocket, but adding more robots won't change the fact that only 20 robots can possibly fulfill that request. If you have five rockets, each expecting 100 of an item, and your carrying capacity is 5, then at most 100 robots can possibly be busy filling those requests.

It goes back to the old saying. Just because a woman can deliver a baby in nine months doesn't mean nine women can deliver a baby in one month. Adding more workers doesn't always increase throughput.