Hacker Newsnew | past | comments | ask | show | jobs | submit | Dwedit's commentslogin

60 interlaced fields per second, not 30 frames per second. The two fields do not necessarily contribute to the same frame.

If you get those fields out of sync, you will have problems though, so it's okay to consider them in pairs per frame for sanity's sake.

"View -> Page Style -> Basic Page Style" is required to read any of the text.

Indeed, it's a pity that the author placed so much focus on a cool looking font that they forgot to take basic properties like "good readability" into account. Form should follow function, not the other way around.

> Form should follow function, not the other way around.

According to whom? It's their personal website, they're allowed to place value on whatever they want.


> According to whom? It's their personal website, they're allowed to place value on whatever they want.

It's a well-known design principle to not impede the intended function of things by giving them a form that distracts from it. Of course you can deviate from that, especially if you want to make a point of some sort.

However, I presume they publish their writings so they will be read by others. Making this hard will reduce their audience.

If they are making this trade-off willingly, good for them, I suppose. But maybe they're so smitten with the style that they do not realize how hard to read it is.

There's also a point at which the form gets so bad that it starts to disrespect the audience. Again, that can be on purpose, but it might be unintentional.

This being a personal blog, it's not unreasonable to expect that a main purpose of it is communication. I think it's warranted to draw attention to the fact that its design gets in the way of that goal, big time.


According to them. They shared their opinion.

No, they asserted their opinion as a fact.

There is a world of difference between "I prefer x" and criticising something while asserting "everyone should do x (because I prefer x)".


You're allowed to criticize something without engaging in social legalese.

It's not normal to wrap all opinions in "I prefer". The average opinion statement looks superficially like a factual statement, without intent to actually claim it's a fact.

> No, they asserted their opinion as a fact.

Interesting idea, let's see if they confirm they were talking facts. I'll be very surprised.

I'm the worst person to take issue with this. This has been my biggest pet peeve for the longest time as well. Right until my frame of mind flipped randomly, and I recognized that by getting upset over blatantly subjective matters being discussed with zero cushioning like this, I'm doing little more than intentionally misreading the other person, and upsetting myself on purpose.

You're reacting to the smoke, not the fire. For example, this may have very well been a perfectly cromulent alternative reply:

> Sounds subjective, and indeed, I disagree. Not a fan of dogma like this anyhow.


There is no ambiguity that needs further clarification, I am talking about the words as written. Their entire message clearly conveys they believe there is an objective design standard that everyone should strive to adhere to, and they are criticising a website for daring to deviate from their ideal standard as though it were an objective flaw and not a matter of personal preference.

> getting upset over blatantly subjective matters being discussed with zero cushioning like this, then I'm doing little more than intentionally misreading the other person until I upset myself. You're reacting to the smoke, not the fire.

It's not about cushioning. They are explicitly criticising the website ("pity", "forgot to take basic principles into account"), and saying broadly that everyone should do X, where X is their own preference. That is the fire. That will invariably rub people the wrong way. It is inherently not an amicable way to communicate about differences in design opinions.

That's not to say you can't give critical feedback. "I'm not a fan of the font, I prefer fonts that are easier to read" would be perfectly reasonable. It's specifically the assertion that there is a way that things ought to be done, as though there are not trade-offs depending upon what each person values but rather one objectively superior way, that causes friction.


Subjectivity is implied. You’re shadowboxing against a claim that the person you replied to never made. Communication is more than the simple dictionary definitions of the words being written.

And as has been pointed out, you are yourself asserting your opinion about subjective communications as fact (i.e. that you should always make it denotatively clear to readers when you’re going your opinion and when you’re globally asserting something)


I will give you credit, you have an art for writing absolutely infuriating comments. How is it that you manage to so perfectly encapsulate the exact thing you baselessly accuse one of doing?

> You’re shadowboxing against a claim that the person you replied to never made.

You start with this, and then immediately lead into:

> Communication is more than the simple dictionary definitions of the words being written.

> that you should always make it denotatively clear to readers when you’re going your opinion and when you’re globally asserting something)

Neither of which are claims I made. At no point did I engage in the dictionary-definition pedantry that plagues this site. I was specifically highlighting how the sentiments they expressed in their message come together as a whole. An accusation that one "forgot to take basic principles into account" cannot possibly be construed in any way other than insulting. That phrase denies the possibility that the OP considered readability but consciously chose to make a trade-off in alignment with their own values, asserts the author's view as a matter of principle, and denigrates the person who "forgot" to consider it.

> you are yourself asserting your opinion about subjective communications as fact

Insofar as words have any meaning whatsoever, I am observing a fact about how they chose to communicate. If you really want to play the stupid game the people of this forum love where you play at the margins of language endlessly redefining everything into meaninglessness to score points in an argument, you can count me out.


You are asserting your opinion as fact

One should not have to preface every single thing with "In my opinion" or some variant for you to realize that that's what they're talking about.

Please don't complain about tangential annoyances—e.g. article or website formats, name collisions, or back-button breakage. They're too common to be interesting.

https://news.ycombinator.com/newsguidelines.html


Backseat moderating is also against the guidelines. If you believe the comment needs moderator attention, flag it. It's pretty ironic you can't say this rule without breaking it

It's not a rule, but I'd like it to be

No it isn't.

I wish there was a rule against rule lawyering. Those comments are way more annoying than gp. (queue recursive replies)

I'd like to add to my sibling comments that this blog's design is so atrocious for its readability that it deserves to be called out.

In fact, I'd like for such a comment to be at the top here, so that I can decide to avoid following the link until I have read enough comments to determine whether it's worth it.


Or just toggle reader view (Firefox).

I don't have any issues with it but I've been computing since the 8 bit days which basically looked exactly like that :)

I wonder if it renders differently for different people.

On Windows, an optimization is to call CloseHandle from a secondary thread.

VeraCrypt can be set to pass through TRIM. It just makes it really obvious which sectors are unused within your encrypted partition (they read back as 00 bytes)

Oh I did not know of this option, thanks! However, I was wrong about the reason for the performance loss on high speed SSDs and the issue is actually related to how VeraCrypt handles IRPs: https://github.com/veracrypt/VeraCrypt/issues/136#issuecomme...

The MSX was basically the TI-99/4A done properly. Just use a Z80 instead of whatever mess they were using.

But 9900 wasn't a mess. It was a very nice minicomputer-grade CPU. 99/4A problem wasn't the CPU, it was that it was designed as a game console and tried to pass up as a computer.

You violate the license (such as GPL)

It has an operation mode where it can losslessly and reversibly compress a JPEG further, and "not a jpeg" wouldn't cover that.

JPEG XL is the thing that makes your JPEG smaller?

JPEG XL is basically 4 codecs in one...

* A new lossy image Codec

* A lossless image codec (lossless modular mode)

* An alternative lossy image codec with different kinds of compression artifacts than those typically seen in JPEG (lossy modular mode)

* JPEG packer

Because it includes a JPEG packer, you can use it as such.


C++: Where you can accidentally deallocate an object that's still in the call stack. (true story)

Well, you can also write:

   int x = 123;
   delete &x;
and that would compile. But it's not a very good idea and you should be able to, well, not do that.

In modern C++, we avoid allocating and deallocating ourselves, as much as possible. But of course, if you jump to arbitrary code, or overwrite something that's due as input for deallocation with the wrong address, or similar shenanigans, then - it could happen.


The trouble with C++ is that it maintains backwards compatibility with C, so every error-prone thing you could do in C, you can still do in C++, even though C++ may have a better way.

The modern, safest, way to use C++, is to use smart pointers rather than raw pointers, which guarantee that nothing gets deleted until there are no more references to it, and that at that point it will get deleted.

Of course raw pointers and new/delete, even malloc/free, all have their uses, and without these low level facilities you wouldn't be able to create better alternatives like smart pointers, but use these at your own peril, and don't blame the language if you mess up, when you could have just done it the safe way!


> which guarantee that nothing gets deleted until there are no more references to it, and that at that point it will get deleted.

To be more precise, C++'s smart pointers will ensure something is live while specific kinds of references the smart pointer knows about are around, but they won't (and can't) catch all references. For example, std::unique_ptr ensures that no other std::unique_ptr will own its object and std::shared_ptr will not delete its object while there are other std::shared_ptrs around that point to the same object, but neither can track things like `std::span`/`std::string_view`/other kinds of references into their object.


> std::unique_ptr ensures that no other std::unique_ptr will own its object

Literally all std::unique_ptr does is wrap the pointer. If we make two unique_ptrs which both think they own object X then not only will they both exist and point at X (so they don't actually ensure they're unique) they'll also both try to destroy X when they disenage e.g. at the end of a scope, leading to a double free or similar.

Uniqueness is a property you are promising, not one they're granting.

I expect you knew this, but it's worth underscoring that there is no magic here. This really is doing only the very simplest thing you could have imagined, it's a pointer but as an object, a "smart pointer" mostly in the same sense that if I add a cheap WiFi chip to this refrigerator and double the price now it's a "smart fridge".


It's really asking for trouble if you view it that way - that you are going to allocate something, then uniquely pass it to a single unique_ptr, or shared_ptr, to manage and release. Better really to use std::make_unique() and std::make_shared().

The smartness, limited though it may be, is just that since it "knows" it's the owner, it knows that it's responsible for releasing it at the appropriate time (reference counted in the case of a shared pointer).

A lot of the value isn't just the automatic release, but that these classes, unique_ptr, and shared_ptr, are built to enforce their semantics, such as literally not being able to copy a unique_ptr, but are able to move it, and copying a shared_ptr being allowed and increasing the reference count of the object.

Yes - they are just simple classes, but using them as intended does avoid a lot of common programmer memory management mistakes, and highly adds to the readability of your program, and ability to reason about ownership, since use of these types rather than raw pointers in effect documents who the owner(s) are, and enforces that this documentation is the reality.


It's an important distinction, just like it's important to know that "const foo *" doesn't mean the foo is constant, just that YOU cannot change it.

Just because you build a unique_ptr from a raw pointer it doesn't mean that it is now magically owned by the object. You also have to ensure that no other place already did that, which unique_ptr simply cannot enforce.


Of course, you're right and my attempt to add precision was itself insufficiently precise. Hoisted by my own petard :(

I was just talking about ownership and smart pointers.

C++'s non-owning "view" classes are a different matter, and the issue there isn't ownership but lifetime of the view vs the underlying data the view is referencing (which in case of string_view could be literally anywhere - a local array of char, a malloc'd block of memory, etc!!).

I'm not a fan of a lot of the (relatively) more recent additions to C++. I think C++14 was about the peak! Given that C++ is meant to be usable as a systems programming language, not just for applications, and given that many new features being added to C++ are really library additions, not language ones, then it's important for the language to include unsafe lower level facilities than can be used for things like that, but actually encouraging application developers to use classes like this that are error-prone by design seems questionable!


> I was just talking about ownership and smart pointers.

Sure, I was just clarifying that "references" in the bit I quoted covers specific things and not everything with reference-like behavior.


Sure, I should have been clearer that smart pointers only guarantee not to release things until there are no more SMART POINTER references to them.

As soon as you start mix 'n' matching smart pointers and raw pointers into what they are pointing to, then all bets are off!


> but neither can track things like `std::span`/`std::string_view`/other kinds of references into their object.

Sure, and if you get into it there are two issues here.

1) Smart pointers are a leaky abstraction that still gives you access to the underlying raw pointer if you want, with which you can shoot yourself in the foot.

2) It's not the smart pointer's fault, but the type you use them to point to might also be a leaky abstraction (e.g. std::string, which again allows access to the underlying raw pointer), or might just be some hot garbage the developer themselves wrote!


The trouble with C++ is that it maintains backward compatibility with C++.

I suppose so, but I think it's relatively rare for languages to just drop support for older features and force developers to rewrite code using newer mechanisms.

Python 2 to 3 is a good example of what can be expected to happen - very slow adoption of the new version since companies may just not have the resources or desire to rewrite existing code that is running without problems.


Late in the C++ 20 timeline P1881 Epochs were proposed. Similar to Rust's editions, which at that time had been tried in anger only once (2018 Edition) this proposed that there should be a way for C++ to evolve, forbidding obsolete syntax in newer projects rather than just growing forever like cancer.

Epochs was given the usual WG21 treatment and that's the end of that. Rust shipped 2021 Edition, and 2024 Edition, and I see no reason to think 2027 Edition won't happen.

The current iteration of Bjarne's "Profiles" idea is in a similar ballpark though it got there via a very different route. This time because it will aid safety to outlaw things that are now considered a bad idea. If this goes anywhere its nearest ship vehicle is C++ 29.

Now, Python 2 to Python 3 did take a few years, maybe a decade. But just shipping the mechanism to reform C++ looks likely to take at least nine years. Not the reform, just the mechanism to enable it.


Meanwhile editions still don't have an answer for semantics changes exposed on public APIs for crates, each compiled on its own edition.

So what does the compiler chose, the edition of the caller, or the caller?


I don't understand the question, maybe you have an example?

In general, even though semantic changes haven't yet been a thing in editions so far.

Crate A uses edition X.

Crate B uses edition Y + N, which has broken Rust language semantics between those editions, or changed a standard library type that Crate A uses on its public API in a backwards incompatible way.

Now an application on edition Y + M, with M >= N, would like to depend on Crate A and Crate B, and calling that incompatible API would be a requirement for the implementation goal.

So far editions haven't bothered covering such cases, deemed as not worthwhile thinking about.

Those in such scenarios get to hunt for another crate to replace Crate A, or have a local fork.


I think it would be useful to give an example of the kind of semantics that would be desirable to change, and where people might think that it should be possible to change at an edition boundary.

I’m not very sure, but maybe something like unforgettable types? Or linear types? Maybe negative trait bounds, or specialization?


OK, so you don't have any examples, I recommend coming back once you have an example as otherwise there's nothing concrete to engage with here.

That was the example, now if you rather want to play defensive instead of engaging into a meaningful discussion about the Rust approach to language versioning and its constraints, well it is as it is.

> Python 2 to 3 is a good example of what can be expected to happen

People keep bringing this up when discussing backwards compatibility breaks, but I think the conclusion should be a bit more nuanced than just "backwards compatibility break <=> years (decades?) of pain".

IMHO, the problem was the backwards compatibility break coupled with the inability to use Python 2 code from 3 and vice versa. This meant that not only did you need to migrate your own code, but you also needed everything you depend on to also support Python 3. This applied in reverse as well - if you as a library developer naively upgraded to Python 3, that left your Python 2 consumers behind.

Obviously the migration story got better over time with improvements to 2to3, six, etc., that allowed a single codebase to work under both Python 2 and 3, but I think the big takeaway here is that backwards compatibility breaks can be made much more friendly as long as upgrades can be performed independently of each other.


Python3 drops support for older versions of python3 all the time. Every single release comes with a bunch of deprecated and removed features. There is a very strong chance that a python 3.7 codebase is totally broken on 3.14. Almost no language takes backwards compatibility as seriously as c++ does.

It's an interesting policy decision for a language - whether to guarantee (or at least practice) ongoing backwards compatibility or not.

The benefit of NOT maintaining backwards compatibility is that hopefully you end up with a cleaner language without all the baggage of the past, and "impedence mismatches" of new features that don't play well with old ones, etc, etc.

However, as a developer, I think I prefer the backwards compatible approach, knowing that:

1) Upgrading to latest version of the compiler hopefully isn't a big deal, and I can take advantage of any benefits that brings, including new language features, without having to sign up for rewriting existing tested code to remove deprecated features. In a large code base any such forced rewrites could be pretty onerous, and may involve a lot of retesting and potential for introducing bugs into code that was previously working.

2) It's nice to be able to take older projects, that you haven't worked on in a while (whether hobby projects, or legacy corporate code) and have the code still compile with the latest installed tool set, rather than to have developed "bit rot" due to using language features that have since been deprecated. Of course bit rot may also occur due to library changes, so language backwards compatibility is no guarantee of smooth sailing.

Maybe going forwards, with AI coding tools, this will become less of an issue, if they become capable of this sort of codebase updates without introducing errors. In fact, going forwards it may well be that choice of programming languages itself becomes seen as more something the tooling takes care of. Nowadays we write in high level languages and don't really think or care about what the generated machine code looks like. Maybe in the future we can write in high level instructions to the AI, without even having to care what the implementation language is?


The modern safest way to use C++ involves lifetime annotations and ownership annotations run under multiple built-in Clang constraint solvers, but this isn't what most users do.

You can also do that intentionally and correctly. After all `delete this;` is a valid statement that can occasionally be useful. That said, I’ve only seen this in old pre-C++11 code that does not adhere to the RAII best practice.

Does it emulate an XBOX 360?

There was WxWidgets.

The main consensus in the native space is that Qt is still miles ahead of any other cross-platform desktop framework (including WxWidgets). Doesn't mean that Qt is anywhere good - it's just the least worst option out of all.

I hoped someday Flutter might be mature enough for desktop development, but so far they've focused most of their efforts on mobile and I don't think this will change in the future.


As 1 datapoint to support this, see Audacity moving from WxWidgets to Qt for 4.0.

Absolutely, they need Qt in order to design and theme a UI that actually doesn't look terrible (They already had good experience in porting Musescore from vanilla C++ Qt5 to QML widgets, so I think they'll use a similar system for Audacity)

> I hoped someday Flutter might be mature enough for desktop development

I really don't think there is any broad future for Flutter. Requiring adoption of a new programming language is making an already an uphill battle even steeper, and the way they insist on rendering websites in a single giant canvas is... ugh


> The main consensus in the native space is that Qt is still miles ahead of any other cross-platform desktop framework (including WxWidgets). Doesn't mean that Qt is anywhere good - it's just the least worst option out of all.

That's not consensus. I very much reject a "desktop framwork". Qt has its own abstractions for everything from sockets to executing processes and loading images, and I don't want that. It forces one to build the entire app in C++, and that's because, although open-source, its design revolves around the needs of the paying customers of Trolltech: companies doing multi-platform paid apps.

I want a graphical toolkit: a simple library that can be started in a thread and allows me to use whatever language runtime I want to implement the rest of the application.

> I hoped someday Flutter might be mature enough for desktop development

Anything that forces a specific language and/or runtime is dead in the water.


> I very much reject a "desktop framwork". Qt has its own abstractions for everything from sockets to executing processes and loading images, and I don't want that.

Yes, that is the consensus of why Qt sucks - it's a massive framework that tries to do everything at the same time with a massive toolset of in-house libraries. This is inherently tied to the revenue model of the Qt Company - sell custom modules that work well with the Qt ecosystem at a high enterprise-level price. I also wish to just use the "good" parts of Qt but I can't, since it already has a massive QtCore as its dependency.

However, there is still no cross-platform framework except for Qt that can actually do the most important things that a desktop framework actually needs: an actual widget editor, styling and theming, internationalization, interop with native graphics APIs (though I have gripes with their RHI system), etc. That's why I'm rooting for PanGUI (https://www.pangui.io/) to succeed - it pretty much completes all the checkboxes you have, but it's still WIP and in closed alpha.

> I hoped someday Flutter might be mature enough for desktop development >> Anything that forces a specific language and/or runtime is dead in the water.

Yeah, but at that time I thought this was at least better than wrangling with Qt / QML. You can write the core application logic ("engine" code) in C++ and bind it with Dart. There are already some companies I've seen gone a similar route with C# / WPF.


As far as I can tell, PanGUI is a drawing library not a graphical toolkit. Its primitives are geometrical, not widgets. Its showcase is an audio app, which is as far away as possible from a boring productivity application that I'd like to do.

In my university days I was very much into GUIs, and I've written apps with wxWidgets, plain Gtk 1 and 2, GNOME 2, Qt, Tk, GNUstep and even some fairly obscure ones like E17 and FTLK. For my tastes, the nicest ones were probably GNOME2, Elementary and wxWidgets. Especially GNOME2, which had a simple builder that let me create the basic shell of an app, with some horizontal and vertical layout boxes that I could later "hydrate" with the application logic.


>That's why I'm rooting for PanGUI (https://www.pangui.io/) to succeed - it pretty much completes all the checkboxes you have, but it's still WIP and in closed alpha

They say it's in beta and it seems anyone can sign up for the beta.


Ah good point. Though I've already signed up for it and didn't get the invite yet... so this seems more like a closed beta.

> Anything that forces a specific language and/or runtime that I don't like is dead in the water.

Ftfy.


No. Any forced runtime is bad because overall it will have few users. The ideal is a C library with the API described in some IDL that allows mechanical generation of bindings for all language runtimes.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: