mtzet's comments

mtzet | 4 years ago | on: Less Than 10% of Firefox Users on Linux Are Running Wayland

Theoretically, Wayland has proper support for fractional scaling, and this just works. In practice however, this only works for wayland-native applications and all applications running through XWayland will be rendered small and scaled up, which ends up looking terrible. I guess this is implementation dependent, but this is consistent across Wayland on GNOME, Sway and KDE Plasma.

This is unfortunate, since many applications can scale just fine, but only through older hacks. Chrome and Electron applications will scale just fine by providing a proper DPI. Same for very old apps. GTK and QT applications will not, but they scale just fine by setting appropriate environment variables.

In practice, this leads to the experience often being better on X11. I've found KDE X11 to handle this the best, with the limitation being a single global scale, only certain fractions allowed and needing to restart KDE after changing it.

GNOME with Ubuntu patches and Xfce will scale everything x2 and use RandR to provide a higher virtual resolution. This has performance costs and messes with cursor speed (measured in pixels) but otherwise also produces good results.

mtzet | 4 years ago | on: Chesterton’s Fence (2020)

Chesterton's Fence is a valid point, but I dislike how the article celebrates it. Doing the archeology required to figure out why things are the way they are is oftentimes much more expensive than building it was in the first place. This leads to terrible situations where it's cheaper to simply build an expressway over the fence rather than tear it down.

This is the stuff technical debt is made of.

Sometimes it's the right decision to risk second-order regressions in order to make forward progress. This of course depends on the circumstances and the costs of regressions.

mtzet | 4 years ago | on: OpenGOAL: Port of Jak and Daxter, written in GOAL, a custom Lisp by Naughty Dog

I can highly recommend the interview with Jason Gregory of Naughty Dog from Handmadecon 2016. He gives a lot of insight into the reality of working with the scheme-based format in recent-ish times.

https://guide.handmadehero.org/hmcon/2016/05/

My impression isn't that scheme is being passed out just because Sony doesn't like it, but also because the language has issues. On the other hand, it seems they're putting a lot of effort into getting the nice scheme features, like hot reloading, in their C++ environment.

mtzet | 4 years ago | on: Lessons learned from migrating a native iOS app to Flutter

The article expands upon this point in great detail. To wit:

> Flutter's HttpServer that crashed on iOS if the user briefly switched to another app and then back to mine.

The author is seemingly capable of writing a solution to the concrete problem, and even debugging and fixing issues in simple libraries, but fixing this issue in Flutter itself (which is much more complex than a concrete solution) is too complicated, leaving him at the mercy of the Flutter maintainers.

He may be saved from solving an old problem again, but it seems that he now has a new, much harder problem to solve. In this context, I think it makes sense to describe using the Flutter library as a technial debt in your definition above.

You say that libraries are a Good Thing (tm), but how would you handle such an issue?

mtzet | 4 years ago | on: Why is my Rust build so slow?

That's a bit misleading though. The problem with header files is that they tend to get (textually) included in lots of compilation units, and hence rebuilt a lot of times. I did an experiment on a codebase at work where turning on unity builds -- so effectively everything is a single c++ file -- resulted in a 2x speedup in real time, and a 12x reduction in 'user' time.

Of course, such approaches lead to slower hot rebuilds. There's trade-offs worthy of a book. But the point is that C++ is only massively parallel by adding a lot of extra work.

This problem could be overcome by reducing the complexity of header files, but that's generally difficult if template-types are used. In general, the solution is to write code that's closer to C than C++ in the header files. In particular using opaque pointers to hide data.

We're actually seeing a very similiar problem in the linked article. The chief problem is monomorphization (~templates) and the solution is to use boxing (~data hiding via opaque pointers).

mtzet | 4 years ago | on: Working towards a source-based bootstrapping path to a GNU+Linux system

Bootstrapping GNU userland is a major pain point, and it's great to see GNU Guix taking it so seriously. There's even a section of their manual dedicated to it [1].

This is important, even if you don't intend to run GNU Guix itself. I care about building GNU userland for embedded targets, and even with a build system like Yocto, which builds specific versions of the entire host userland, you can get errors due to eg. an older gnu m4 not being buildable with a modern glibc. Thus, you end up essentially requiring developers to build inside a container.

This is paving the way for having everything required to build a piece of software just checked into the git repository. If you want to change it, you just commit it like everything else.

[1] https://guix.gnu.org/manual/en/guix.html#Bootstrapping

mtzet | 4 years ago | on: C++20 Modules with GCC11

In my experience the important libraries I need to interact with are C libraries, not C++ libraries. Of course certain niches have very important C++ libraries, but I don't think the C++ library story in general is that great. Care to expand?

mtzet | 4 years ago | on: SQLite Is Dynamically Typed (2020)

> One nice thing that sqlite being dynamicly typed allows for, is having a key-value table for storing singleton objects, like project config (as opposed to having a well defined table with a single row).

If you need to store singleton objects, wouldn't you just serialize manually to a string representation and store them as TEXT? A fancier solution would be something like the JSON type in Postgres.

I fail to see how sqlite's dynamic types are helping at all in this scenario.

mtzet | 4 years ago | on: Show HN: C3 – A C alternative that looks like C

> I don't think Zig has the same goal.

It seems to me that the only meaningful difference in their goals, is that C3 wants to stay as close to C as possible, including having familiar syntax.

> Also, they usefully compare the languages [...]

The comparison seems disingenuous.

Zig has a module system where each zig file is a module and it has a mechanism to specify public parts of the module.

One of the standout features of zig is the integrated build system, which uses a reliable caching mechanism to allow incremental builds without rebuilding the world. It's somewhat remniscient of bazel actually.

The zig std library features hashmaps and variable length arrays. Strings are not different from slices of u8. It's unclear to me what C3 means by "built-in strings". The only reference I could find was under "crazy ideas", where they vaguely refer to needing to figure out memory management. That seems like a pretty big outstanding issue for a C competitor.

So the unique feature of C3 appears to be the contracts system of pre- and postconditions, which are only used as language hints to the compiler.

mtzet | 4 years ago | on: Thriving in a Crowded and Changing World: C++ 2006–2020 [pdf]

> I find it surprising that anyone could imagine that the creator of C++ is unaware of its issues.

While C++ adds a lot of new features, it does very little to solve the problems inherited from C. The lack of static introspection, a real module system and tagged unions are all inherited from C. I do think it's fair to think that if a problem is not addressed in 30 years, it just might not be considered important.

Adding tagged unions is not a sophisticated language feature. Fat pointers (c++20 std::span) also seems like a no-brainer. Maybe I'm biased by hindsight, but these features were implemented by contemporaries like Pascal?

Actually, the paper also contains a great section about fat pointers:

> The obvious solution is to supply an abstraction that holds a pointer plus a size. For example, in 1990, Dennis Ritchie proposed that to the C standard committee: "'fat pointers' whose representation will include the space to store the adjustable bounds at run-time" [Ritchie 1990]. For various reasons, the C committee didn’t approve. At the time, I heard the priceless comment: "Dennis isn’t a C expert; he never comes to the meetings." It is probably good that I don’t remember who said that.

mtzet | 4 years ago | on: Thriving in a Crowded and Changing World: C++ 2006–2020 [pdf]

At a 168 pages, I only had time to skim it, but this was much better than I thought it would be. He honestly addresses many of my complaints about C++.

In the discussion of variant, optional and any: - He bemoans that "The possibility of direct language, as opposed to standard-library, support appears not to have been seriously considered" - He acknowledges that "variant and friends address an important problem, but inelegantly." - He considers variant, optional and any a "stop-gap measure" - In discussion of a pattern matching library he acknowledges the need for "both closed sets of alternatives (algebraic types) and open sets (class hierarchies)." and explicitly says the aim is to remove the visitor pattern (whereas c++17 just added std library syntax for it)

In the modules discussion (9.3.1), he also identifies the problem that "[the hello world program] yields 419,909 characters for the compiler to digest". I wish he'd also address visiblity specifiers at a module level, rather than just at a class level.

In the static reflection discussion (9.6.2), he discusses the typical problem of iterating over members of a struct. This is indeed a point where C++ has not really progressed much since ANSI C.

The discussion of error handling in chapter 7 felt a bit lacking. My main problem with exceptions isn't performance, but that I can't determine if I've handled all error conditions. The idea of using exceptions for non-local errors and error codes for local errors is too vague. It also doesn't really make error codes much easier to use. For my money, I still think that using error codes and providing syntactic sugar for dealing with the common boilerplate is the best compromise. I can accept exception/panics when they are not supposed to be caught, but just cleanly terminate the application.

Maybe C++ will solve these problems in the future (C++23? C++26?), maybe not. In the meantime, the new languages on the block are attractive because they solve these problems _today_.

mtzet | 4 years ago | on: Gio – write immediate-mode GUI programs in Go

This gets brought up pretty much every time immediate mode GUIs are discussed on HN. I think your comment is reasonable, and I don't disagree, but I also think it's important to not throw the baby out with the bathwater and dismiss immediate mode GUIs for accessibility reasons.

It's not at all clear to me that the right approach is to have both the accessibility interface and the GUI be generated from the same components. It seems to me that it's just approaching the lowest common denominator of a passable GUI and a passable accessibility interface.

The traditional widget-style GUI paradigm asks you to essentially copy all your application data into their format and to keep this format in sync with your own data. This is tedious, and I believe hinders the creation of better GUIs. On the flip-side, owning your data structure means it can indeed hook into the accessibility API for you.

Immediate mode GUIs provide an alternative approach, where they only handle rendering stuff on screen. Since all the data structures are now properly controlled by the programmer, it is much easier to create dynamic GUIs. Taking a step back like this provides an opportunity to further the state of the art.

The solution I see to providing accessibility in immediate mode GUIs is that the programmer has to hook into the accessibility API themselves -- if it makes sense. It's not clear to me that certain advanced GUI programs can ever be very accessible. Yes, this is more work, but there's also an opportunity to create richer experiences for people with disabilities.

mtzet | 4 years ago | on: The Return of Fancy Tools

On the other hand, I find the integration between Atlassian tools to be pretty barebones. It feels very clear to me that Atlassian tools are really developed separately, with a separate jira task to integrate specific parts. There's no "coherency" to them.

You are right that it's difficult to replace the entire Atlassian suite. The thing about Atlassian is that when there's if there's a box to check on a feature list, they've made sure to check it. If you go around the office asking everyone what features they want, Atlassian is going to check all those boxes. That's pretty hard to compete with.

mtzet | 4 years ago | on: Perlis' Epigrams (1982)

> 20. Wherever there is modularity there is the potential for misunderstanding: Hiding information implies a need to check communication.

This is a really great point. Along the same vein: modularity has a cost too. A cost in terms of communication. The benefits of modularity should be weighed against this cost.

We're really good at talking about new patterns to increase modularity, in particular in the OOP tradition (always hide data, every data structure is its own little module with a public interface). We're very bad at talking about the costs associated with these.

mtzet | 5 years ago | on: Joe Is Wrong (2009)

These discussions tend to boil down to OOP vs FP. That's a false dichotomy. The alternative to OOP is not FP, it's pre-OOP imperative programming with various techniques a la carte.

Should data and functions be together? That's a choice you can make on a case-by-case basis. It makes total sense that a HashMap has an insert() method. On the other hand, maybe your Player object is just some data which is interpreted by a PhysicsSystem and MovementSystem etc. Maybe it's clearer that all the physics calculations are in a common PhysicsSystem rather than being spread out into several implementing classes.

Should you use a switch-statement or a polymorphic interface? If you're traversing a graph with a fixed set of nodes, or you need to change all systems when new nodes arrives, the (exhaustive) switch may be preferable. I'd certainly prefer it to the visitor pattern.

If you can extract a calculation into a pure function, then that's great. If you're doing something inherently stateful, FP techniques are probably not too great. Maybe you can afford a high-level functional interface, but keep the implementation stateful.

The problem with OOP, FP, etc. is not that the techniqures are BAD, it's that all techniques are trade-offs. We're very good at talking about the advantages of some technique, but seem always forget the costs associated with it.

mtzet | 5 years ago | on: How Safe Is Zig?

You're also forgetting: simpler language/explicit code => faster build times. Zero-cost abstractions are only zero-cost in optimized builds and and complex optimization isn't free.

Whether static checking vs faster iteration time is more important depends entirely on the context, but rust isn't going to help you when you accidentally did front-face culling instead of back-face culling.

mtzet | 5 years ago | on: How Safe Is Zig?

I think this is a roughly fair assesment, but I also think it's important to contextualize memory safety. Ultimately, the goal here is to produce /correct/ software. Memory safety is a subset of this, but there are other aspects to correctness as well.

I really like zig's approach of explicitness and fast iteration cycles. Fast compile times and the very flexible build system makes me hopeful for a really slick workflow for embedded development,where zig code can be used to deploy and test as well. For my own use I think it's a clear win.

On the hand, the amount of damage poorly architected zig code can cause is about as large as for poor c code. For typical enterprise code the rust compiler will make sure that many bad decisions will not even compile. There's still a risk of towering abstractions, but at least I could avoid spending as much time debugging hideous race conditions.

page 2