HN user

moth-fuzz

468 karma
Posts0
Comments101
View on HN
No posts found.

This is so true. In webgpu, the functions to request a GPU device / GPU adapter are both async, and I often wonder, what is my engine going to do in the few milliseconds before it's grabbed a handle to the GPU? It can't render anything, it can't load anything... If I really had to guess I would think it's so that when compiled for web, the page doesn't lock up when the browser is showing the "allow this site to access your GPU? yes/no" popup. But it makes far less sense in desktop land.

I dislike the trend among computer users that query strings == tracking data. They're just one of the many ways a browser request can contain data. They are used for all sorts of things in perfectly valid websites, and it's difficult for me as a developer to just just arbitrarily accept that a certain feature HAS to be used for a certain malicious technique, despite it being common.

With more limited copy-paste functionality, tracking parameters could just as easily be put in the request body. Or a cookie/session data. Or, if you're nasty, you could get everything you want to know out of a user via fingerprinting with very little up-front data at all.

We as users have basically already been collectively pwned, the solution being to use VPNs, anti-tracking scripts/extensions, encryption, and just plain ol 'stop using services that track you'. The preceding are all leagues better for one's privacy than superstitiously chopping up a URL.

Honestly, disallowing other websites from from adding their query strings to your URLs I think is awesome, and I think it makes sense that websites should validate their URLs against their internal APIs only. But, given this was only done for query strings, and not other parts of the request, I still feel like this whole thing establishes more of a taboo than an actual security or privacy guideline.

I'm a huge fan of the 'parse, don't validate' idiom, but it feels like a bit of a hurdle to use it in C - in order to really encapsulate and avoid errors, you'd need to use opaque pointers to hidden types, which requires the use of malloc (or an object pool per-type or some other scaffolding, that would get quite repetitive after a while, but I digress).

You basically have to trade performance for correctness, whereas in a language like C++, that's the whole purpose of the constructor, which works for all kinds of memory: auto, static, dynamic, whatever.

In C, to initialize a struct without dynamic memory, you could always do the following:

    struct Name {
        const char *name;
    };

    int parse_name(const char *name, struct Name *ret) {
        if(name) {
            ret->name = name;
            return 1;
        } else {
            return 0;
        }
    }

    //in user code, *hopefully*...
    struct Name myname;
    parse_name("mothfuzz", &myname);
But then anyone could just instantiate an invalid Name without calling the parse_name function and pass it around wherever. This is very close to 'validation' type behaviour. So to get real 'parsing' behaviour, dynamic memory is required, which is off-limits for many of the kinds of projects one would use C for in the first place.

I'm very curious as to how the author resolves this, given that they say they don't use dynamic memory often. Maybe there's something I missed while reading.

I'm not a fan of the recent trend in software development, started by the OOP craze but in the modern day largely driven by Rust advocates, of noun-based programming, where type hierarchies are the primary interface between the programmer and the code, rather than the data or the instructions. It's just so... dogmatic. Inexpressive. It ultimately feels to me like a barrier between intention and reality, another abstraction. The type system is the program, rather than the program being the program. But speaking of dogma, the author's insistence that not abiding by this noun-based programming model is a form of 'lying' is quite the accusatory stretch of language... but I digress at the notion that I might just be a hit dog hollering.

I love Ruby and have tried to use mruby several times, but the one thing that always becomes an issue is that it uses Ruby’s own native-extension build system for compilation, which is configured in Ruby itself. It makes it a total pain to include in other build systems, or when compiling to other targets (i.e. WASM)

Frankly, I love Ruby as a language, but if it were as easy to embed as Lua I would have no reason to use Lua.

Dark Mode Sucks 8 months ago

I agree with the author - I'm sick of hearing the cliches from people who prefer 'dark mode'. But I remember long before there was 'light mode' and 'dark mode' there were themes based on a spectrum of hues and values - actual colors. Why not bring that back? "Light mode" can be way more bearable if it's not pure #ffffff. I dislike the invented dichotomy of light and dark anyway, there's an entire spectrum that designers can use, and I think apps in general would look way better if they took advantage of that.

You'd also be more productive and have less unknowns and potentially less decision paralysis if, say, everyone started using excel hooked up to a database instead of writing their own bespoke CRUD app, but alas, those aren't the reasons one asks programmers to program.

Crystal 1.16.0 1 year ago

I love Crystal but I’m surprised at how nothing the WASM story is this late in the game. I’d love to run Crystal directly in the browser, especially given how web-focused they seem to be.

Also, windows support has been more or less “done” for a couple of years now, is the “preview” tag still necessary?

Regarding the 'Modular Monoliths' bit, I wholeheartedly agree. I always found it kind of disappointing that while we're told in our OOP classes that using interfaces increases modularity and cohesion and decreases coupling, in reality in most programming languages you're relying on the nominal type of said interface regardless. All libraries have to use a common interface at the source code level, which is obscenely rare. For interfaces to truly live up to what they're describing, they merely ought to be structural (or whatever the equivalent to functions is that structural typing is to data).

Edit, since I remembered Go has this behaviour: I think Go's auto-interfaces I think are easily one of its biggest selling points.

I'm of two minds when I see comments complaining about header files. Practically speaking, I think "have the preprocessor copy & paste source files together" is a bit of a hackjob, but, conceptually speaking, having your interface and implementation separate is ultimately a good thing.

The problem of course lies not with header files, but C++ the language, as all public fields and private fields must be specified in the class declaration so that the compiler knows the memory layout. It's kind of useless in that sense. You can move private methods out to a separate source file, but, you don't gain much in doing so, at least in terms of strict encapsulation. And of course, if you use templates at all, you can no longer even do that. Which is its own can of worms.

Unfortunately, none of these problems are problems that modules solve. Implementations very much disagree on interfaces vs implementations, precompiled vs simply included, etc etc. In my own usage of modules I've just found it to be header files with different syntax. Any API implemented via modules is still very leaky - it's hard to just import a module and know what's truly fair for application usage or not. You still ultimately have to rely on documentation for usage details.

At the end of the day I don't really care how the implementation puts together a particular feature, I care about how it affects the semantics and usability of the language. And modules do not really differ in proper usage from headers, even though the whole backend had to be changed, the frontend ends up being the same. So it's net nothing.

All said and done, when it comes to defining library APIs, I prefer C. No public/private, you just have some data laid out a particular way, and some functions to operate on it. The header file is essentially just a symbol table for the binary code - and said code can be a .c file or a .o file or even a .a or .lib or .dll or whatever - C doesn't care. Raw functionality, raw usability. No hoops.

Enum of Arrays 2 years ago

The idea that arrays of structs are inherently more cache friendly and thus data-oriented-er is a bit reductive of the whole practice of data-oriented code. The point is to optimize data layout for access patterns. Putting fields of a struct into their own arrays is only actually an optimization if you're only accessing that field in-bulk. And if so, why is it even in a struct in the first place? If you use all fields of a struct in your algorithm, then an array of structs is the optimal way.

All the same is true for enums.

I have a problem with how procrastination and perfectionism, this sense of being 'not good enough', is almost universally phrased as not being good enough for others. For caring too much about others' opinions. And that the solution is to just Do Art For Yourself :tm:.

I've tried that. I've tried shunting out everyone else's opinions. But then of course, if you lock me in a room with me, myself, and I, you now have 3 of my biggest critics all in the same room.

I don't really care what others think, never really did, and none of these anti-procrastination or anti-perfectionism pieces help when it's my own standards that I'm not meeting.

I’ve implemented platformer collision dozens of times now and the only way I’ve found it to be genuinely smooth is to do it one pixel at a time, just like the author suggests.

But something always bugs me about that - we know the closest edge of the closest obstacle, we know the vector of the player’s motion, by all accounts we should be able to calculate the point of contact in one go without doing any substeps.

And yet, doing it in one pass always seems to result in a myriad of edge cases (literal!) that break the whole thing, unless you do heavy preprocessing, converting your tiles to a graph of lined surfaces, etc etc.

Honestly my GAS subsided when I realized most of my favorite records were made with affordable or off the shelf gear. So many guitarists on the 80s used JCM800s because that was what Marshall was putting out. Eric Clapton’s Stratocaster wasn’t vintage when he bought it, it was just an off the shelf guitar! Same with most amps, instruments, keyboards, synths, drum machines, even samplers which are hailed as legendary because they have higher bass and a lower bitrate (an effect you can get with a one-knob EQ and a bit crusher, respectively). The artists were just using the tools available to them because… they were available.

I have simplified my recording and production setup to mainly just a computer, 10 channel audio interface, a 90s mackie mixer because it’s big and fun and sums neatly to the 10 channels (8 busses + master 2 buss), and whatever bits of quirky and fun gear I can find.

My GAS left when I realized I don’t need any of it. I could make music on just a laptop if I wanted to, I could just play my guitar and resample it for synth sounds if I wanted to. Plenty of iPhone producers out there who just make weird sounds with their mouth. It’s all relative. People will say you’ve Got to have at LEAST one analog mono, one poly, a digi, a sampler, and an endless supply of grooveboxes, but computers are truly more than capable. “Analog sound” is just an EQ away. Just focus on the creative aspect and the gear aspect diminishes and becomes yet another source of creativity - find quirky pawn shop stuff that makes you smile when you play it. Even if you don’t record it, you don’t feel like it’s GAS because it brings joy.

One is when you are trying to create a system that inverts dependencies by allowing a plugin system or follows some sort of nuanced workflow that others might want to "hook into".

I’m fairly certain that’s the use case of inheritance - at least in the Simula tradition. Classes as a means of lifetime management, moving parts that have well defined steps of operation (methods), and interchangeable parts (subtypes) which you can more or less slot into the larger system (polymorphism).

It’s easier to think about classes not as nouns, but as verbs over time (or rather, bounded by time): at a specific moment in the assembly line, call this particular method, at another moment, call that other method…

Object oriented programming in the Simula tradition I would even go as far as to say is just best practices in structured/procedural programming taken to their logical extremes.

I do not have an internal monologue, unless I intend to. I also frequently don’t even have thoughts unless I intend to, but that I’ll admit comes from several years of meditation. When I tell people I’m not thinking about anything, or that I even have the ability to not think about anything, they act shocked and confused. When I say “hold on, I have to translate my thought into English first,” they’re usually accommodating but I can tell from the looks I get that that’s not something everybody does.

It does however put into perspective a number of arguments I have day to day and online, and the simple fact that most of them are over semantics, definitions, miscommunications, and misunderstandings. I frequently wonder what it would be like to have an argument with someone where you both perfectly understand each other, and are just debating the merits of your ideas and not just how they’re presented.

I feel like a lot of people in the world equivocate language with meaning itself, with no abstraction behind the words and letters. That’s why sometimes if you tell someone they’re using a word wrong they’ll take it personally, as if you told them their very being was wrong. Well, if the externalized word is the only avenue you have for internal understanding, how can it be any other way?

The thing that I miss mainly about CDs and floppies and even SD cards to an extent is that they were actually integrated into the machine itself.

Modern removable storage solutions just use the Universal Serial Bus, and could look like anything, and have no specified shape or size, and stick out of the machine.

CDs, floppies, and SDs slide nicely into a dedicated opening, and go all the way in. They’re nicely stackable and sortable. You can even write on them for quick labeling. Very user friendly.

I by and large loathe how commonplace big do-it-all game engines have become in indie game development, with unity at the forefront of this movement. Even if everybody and their mom used the same awesome product, I'd still be upset because because of the market stranglehold that eventually creates - Unity in this case is worse because it isn't even an awesome product. It's a mediocre product with an actively hostile business strategy.

I admit this is entirely emotional, but when I learned that Hollow Knight[0] was made in Unity, it broke my heart. A 2D game with a consistent art style (read: write the shaders once and forget it), made up entirely of flat surfaces with only a handful of different methods of movement, no physics to speak of, and only a couple hundred different types of enemies, most with large overlaps in AI save for bosses. Gorgeous game, strong art direction, thoughtful lore and story, but any game developer could probably write the engine for such a game in a couple weeks.

But every indie developer I've talked to about game engine development acts like it's a dark art. That it's just impossible for mere mortals to do such a thing, and if you do, then you'll never ever release a game, or you'll spend literal years on the engine. Again, I predict a couple weeks.

Back to the article, I dislike that 'game development post-unity' just means 'picking out a new engine'. Everybody's jumping ship to Godot or Unreal or whatever else because we all need a game engine. But why? Why is this song and dance necessary? I feel like since the author is a game engine programmer himself, this option should have come up higher on the list along with the non-engine libraries and frameworks.

0. https://www.hollowknight.com/

I agree that interface is key to not just software design, but design in general. Designing parts in isolation, you can do pretty much whatever you want. But people being able to gracefully handle where and when two parts collide is what makes the software world go round. One of my favorite bits on interfaces is this Rust Koan[0], which has a funny twist of pragmatism at the end.

It's a shame too many developers think this huge idea is just the interface keyword, or OOP, or even just the `object.method()` syntax. I hear dot-autocomplete come up in conversation almost every day now. When I was in college people asked me "How can you even use C? It doesn't even have classes...?", the implication being you couldn't encapsulate your code at all, and I get the same shrinking feeling when people talk about dot-autocomplete as if it's synonymous with interface discoverability. But it's really just one particular implementation (heh) of a much broader and more abstract (heh) idea. It's like calling all tissues Kleenex or all sodas Coke.

0. https://users.rust-lang.org/t/rust-koans/2408/3

One thing that's bothered me for a few years about Object-Oriented code, is the question of why the dichotomy of 'implementation' vs 'interface' is drawn on the exact same line as 'variables' and 'functions'.

Everyone who's ever worked in a functional programming languages knows that functions can easily be considered 'state', and everybody who's spent time in real-life plugging in various electronic devices knows that data itself can be considered an 'interface'.

So why does OOP dogma conflate these ideas together? Why couldn't a single variable or property be virtual and polymorphic? Why couldn't a member method be reassignable like a member variable? The philosophy and the actual implementations just self-reference each other. Interfaces are great because they keep interfaces separate from state. I agree. But strictly in terms of language features, why are functions considered interface while variables are considered state? Well, because that's just how they're defined, I guess.

But if you're doing OOP in C, and you have a VTABLE full of pointers, well, it doesn't really matter what those pointers point do, do they? They could be function pointers, they could be variables/memory locations, they could even be references to other structs. It's not quite as delineated when you do it from the bottom up.

You can't evaluate a future in normal rust as there's no default executor, you need to pull in some library to even make blocking calls to async functions.

IMO, this is even worse than function coloring.

Exactly. I just didn’t want to sound too pessimistic in the original post… honestly I’m just excited we get bare minimum a modern architecture on the web. That doesn’t mean I wouldn’t still rather just write for desktop in the end anyway if I want to use techniques from this generation.

It’s all dated. All of it. WebGL 1 is an outdated version of OpenGL (which is already an outdated API), WebGL 2 which was only just recently widely supported, brings a sort-of-less-outdated version of OpenGL (which, again, is itself outdated).

So we’re mostly waiting on WebGPU support so we can use a more modern-feeling API. But by the time WebGPU becomes both itself standardized and then widely supported, well, who knows if it will still be relevant…

The web just unfortunately lags behind while still emulating desktop. It would be fine if it did it’s own thing entirely so we wouldn’t have anything to compare to but writing 3D for web just feels like writing 3D for desktop 10 years ago. Plus performance and security… it’s way easier to just drop a .exe on itch.io or whatever.

AI won’t make artists redundant because you don’t pay an artist for a picture in the first place, you pay them for their creativity, their ideas, which may eventually result in a picture. You know, their artistry. Too many artists devalue themselves and their livelihood by defining their work as entirely mechanical, entirely defined by their material product. Art is more than just produce. You’d think artists would be the first to say that.

I read the whole article. The midsection on mindfulness reached the non-conclusion of "but the world and people in it are still imperfect, despite the existence of Buddhism", and like, yeah? It's supposed to be? That's the whole point.

Following that, I don't think the OP's list of individual contradictions which vary by culture and belief system constitutes a meaningful critique of the whole idea (insofar as there even is a 'whole idea', which, maybe there isn't). "Someone somewhere else thinks differently than you, so what you think sucks", like, what? That obviously doesn't follow. I'm not and have not been talking about Pure Land Buddhism, so any critique of Pure Land Buddhism, is not a critique I'm responding to.

The final part of the article criticizes the form of 'western meditation' I was talking about, where you simply try and make yourself not feel things, rather than accepting those emotions as a part of life and let them flow in and out of you while acknowledging them for what they are. I agree with the author that 'self-scolding' is a terrible approach to meditation, but this is something I see more commonly in Buddhist-appropriation rather than actual Buddhist teachings. So, to my original point, I think OP and I are simply reading different texts.

I don't think OP is wrong in any capacity, I just think they've misidentified the target and are scoping a bit too broad - OP has gripes with certain schools of Buddhism and the way certain people practice it. But the whole article doesn't really contain a criticism of like, the whole thing.

a major element of the original Buddhist scriptures is life-denying, anti-emotional asceticism

Maybe OP and I have been reading different Buddhist texts, but for me the whole point of anattā is that you affirm your life and emotions as part of a greater interconnected whole. You lose the transcendent conception of yourself, get rid of the whole 'soul' thing, you relax fully into the immanent, you realize that you're dirt - but you're dirt that breathes and thinks and feels.

You don't ignore your anger and sadness and hurt, as much of Western meditation teaches for some reason, you let it pass through you, appreciated and unharmed, as you realize that our species and many others ultimately developed those emotions because they were beneficial in some way. You don't ignore suffering, as that behaviour is itself an attachment - an attachment to happiness! You have to 'challenge the question' per se. Get rid of the root problem by realizing that life is suffering.

We along with many species developed the ability to realize and to feel suffering because we evolved to deal with life, not to cast ourselves away from it, physically or spiritually. This process of development ties you into the larger part of nature, and the earth in general, as a system of indefinite change in which you are a small part, like a drop in a coursing river. You're a living example of nature in action, and every time you're angry or sad or hungry or hurting or even happy or excited, that's nature working. That's not life-denying, that's affirming what it truly means to be alive.

To provide a more pragmatic and less flowery note, my friends and colleagues often sow an incredible amount of dismay and frustration into their lives trying to avoid anger or avoid pain, when they could just allow themselves to feel the feelings that are already in their bodies in the first place. Oftentimes sadness is less sadness-in-itself and more like a frustration at an unmet desire to not feel sad. This desire, this attachment, is ultimately misguided. It's like seeing your check engine light flashing and thinking "I really need to stop that light" instead of "I need to check my engine". Do away with all that attachment and then feeling one's feelings simply becomes being mindful of those emotional 'indicators' and realizing that they're impermanent. The feelings are still there, there's just no attachment.

I’ve begun to learn Vulkan recently, and honestly, the API is not the best. But I feel like it’s the best long-term option - it’s really more about the mental model: buffers, pipelines, commands and queues, all exist in one way or another in Vulkan, Metal, and DX12. OpenGL is the odd one out as it’s a global state machine. That said, you can build a vulkan-like abstraction atop of OpenGL (I’ve tried).

The problem however, is compatibility. We’re in a very weird transitional era for graphics. Things aren’t unified anymore. Modern OpenGL features that aren’t difficult to implement are held back by drivers since most of that work is done by drivers in the first place. It’s not like the GPU can or can’t do these things, it’s that the vendors don’t expose that functionality. Vulkan is not available on my ivy bridge thinkpad (unless I run Linux and an open source driver). OpenGL greater than 4.1 is not available on MacOS because apple writes the drivers and they chose to stop writing them. Vulkan is not available natively on MacOS, except, with MoltenVK you can enable it, since at the end of the chain a GPU is just a GPU and it doesn’t care what API you use. Microsoft, in their commitment to legacy compatibility, allows DX12 to run on any windows machine made in the last decade, the catch is it’s windows only. So all the options have their ups and downs and pitfalls whereas it felt like 10 years ago OpenGL was ‘the’ answer.

Honestly, the state of graphics programming is a mess. To be compatible, you have to stick to some narrow versions of OpenGL that are uncomfortable and outdated, because computers or drivers are either too old or too new or both, or you have to write individual abstractions for every platform you target.

I hate the state of it but I get why indie devs are all just using Unity now. When I was growing up it was SDL2+OpenGL, and then it was XNA, but it seems coding at all is too much now. And I don’t really blame them, the problem domain has expanded significantly and the knowledge required has expanded along with it. Libraries can’t just be libraries to solve one task, they have to be frameworks or engines or entire graphical editors because all this is just too much for one person to figure out anymore. I just wanna write some code that draws some shapes, man.