For me, the rule is to never use .unwrap or panic! as “might as well die” because that produces an ugly and novice-unfriendly error message for the end user.
It’s .unwrap() or todo! for prototyping (there’s a clippy lint to catch .unwrap and not .expect), .expect("rationale") or unreachable! for unreachable, and “Return an error that can be turned into a friendly message” for “might as well die”… especially since I’m always on the lookout for how to make my code reusable so it might become a library later and it’s bad enough that I often feel compelled to wrap third-party dependencies in catch_unwind for want of a maintained Rustig! or findpanics.
Slightly off-topic but I would be interested in knowing more about the UX principles behind error messages (especially as regards end users). It seems to be folk wisdom at this point. I’m just not sure I agree that displaying a back-trace — or an option to generate one — is any less novice-friendly than displaying an error message which may, or may not, describe the error correctly/in enough detail to be useful.
which may, or may not, describe the error correctly/in enough detail to be useful.
For me, “might as well die” inherently means it should present a message like “File X is missing.” or “Couldn’t connect to Y.com. Check your Internet and then see if the server is down.”
My philosophy is that failing to find a way for the message to be actionable for the user is itself a bug… even if “actionable” just means. “The program is broken in way X. Please try reinstalling it and, if that doesn’t fix the problem, send this file to the developers so they can figure out whether the bug is in the program or the portion of the installer concerned with installing/repairing dependencies.
I’m just not sure I agree that displaying a back-trace — or an option to generate one — is any less novice-friendly
There are basically two sides to displaying a backtrace, both of which apply for stuff like the static site generator I wrote for my mother. You could refer to them as positive and negative.
The “positive” side is that that a backtrace will actively crowd out the actionable error message like “Couldn’t find $PWD/src/images/whatever.png” and make it difficult to notice. (She’s in her 70s and even just a couple of lines of git warnings that I forgot to send to /dev/null were enough to trip her up).
The “negative” side is that, in this context, the predefined formatting for .expect(msg) comes at the expense of denying me the ability present a by-design error message clearly enough.
In essence, it’s the same problem you see whenever you have to guide someone on an issue tracker through scrolling back up the make or cmake output until they find the actual error message buried under the stack of “failure while…“s.
“Couldn’t connect to Y.com. Check your Internet and then see if the server is down.”
That is a bad error message. The error should say if there was a DNS error, and if so, was it servfail or nxdomain, or was the stub resolver unable to reach the DNS server? Or was there a connection failure, and if so, was it an ICMP port or host or network unreachable? Or was it a connection timeout?
An error cannot be actionable if it does not explain what went wrong. It should also explain what the program was trying to do when it encountered the problem.
Backtraces can be OK at explaining what the program was trying to do (if you have its source code) but they don’t always say what went wrong. For example, if you unwrap a Rust std::io::Error, the panic won’t tell you the pathname or the operation that caused the error.
Fair enough. I was trying to be intentionally vague to avoid calling out a specific example, but that just made it a bad example, period. If that showed up in an actual example, it would be the higher-level message that is then followed by the more specific text that was bubbled up.
I definitely agree with your point about backtraces and I’m well aware of the pathname problem with std::io::Error. For example, if I do use backtrace-style output in my bubbled-with-context errors (eg. in something purely intended for myself), I use messaging like this at minimum:
Error while trying to render page "/full/path/to/source/file.html":
Failed to embed <img> with src="foo/nonexist":
Couldn't read contents of file "/full/path/to/source/foo/nonexist":
No such file or directory
Note the use of Debug quoting on the src and source path to ensure that things like trailing whitespace will be as easy to notice as possible and the conscious decision to use greppable error messages (instead of source path and line number and the like) and rightward drift to mitigate the “wall of text”-ness that automatic backtraces tend to have.
That particular example is from a case where, last I worked on it, I hadn’t figured out if there was a way to get lol_html to report the line number for the <img> tag currently being rewritten.
A more accurate example of the standard I try to hold myself to is how, for a miniserve-like-but-an-image-gallery tool that I really need to get back to working on, it uses a “What is my IP?” crate to present the user’s external IP address in the “ready to copy-paste to your friend” URL and I have plans to add UPnP support for automatic port forwarding when possible.
It’s worth noting that ‘slop’ has an earlier, if somewhat related, meaning in describing the base, retention-farming content you find on platforms like Tiktok or Youtube Shorts.
‘Somewhat related’ insofar as I think it’s the case the scripts, or ideas, for content farms that put out ‘slop’ were an early use-case for DNN-assisted content production. Alternatively, you could think of these platforms as maximising for retention, which gels with the analogy of DNNs as highly general optimisers.
A common example is using “oddly satisfying” or “minecraft parkour” or “subway surfer” as background content, then select a recent top post from a popular reddit post and have a TTS narrate one of the top comments.
You can make 10 videos for the top 10 comments on the post, if you go for the top 14 posts and go by “top daily”, you can make 20 posts a day for 0 investment. Most of this can be automated.
There is scripts that will use recent news headlines to pick a topic via ChatGPT and have it generate a script that is then narrated by TTS and videofied by adding more filler content (“minecraft parkour”).
There isn’t even the effort of narrating the video by a VA of any sort (even if it’s the creator themselves) or collecting their own video footage.
The videos tend to be not terribly long, 20-30 seconds or so. The way the topic is picked ensures it is likely to be interesting and the background video tends to keep things more busy than they really are. As a result, they get to take 30 seconds of your attention span in exchange for ad revenue.
They’re farming for the 30 seconds of attention it requires to rake in ad money, nothing more.
Exactly. That makes this proposal not very sensible. It’s like if I said “Swiftie is the new name for a fan of the Swift programming language” or “parallelism is the new name for concurrency.”
I wonder why those projects only implement the default color scheme and don’t provide a way to change it. Windows used to be very much themable and came with multiple color schemes for default window decorations, apart from the option to make completely new themes from scratch.
OMG remember the themes in Windows 98 where it would add a bunch of weird sound effects and even aggressively change the mouse pointer to some animated monstrosity! Loved it!
You can read Aaron Hsu’s thesis to understand the codebase better. The author has said their thesis is the Literate Programming version of co-dfns.
Especially section 3, which explains how are trees represented and why. Even if you wont necessary use the same representation in a more mainstream language it shows some important considerations for writing brachless, parallelizable code.
It’s an APL compiler that generates GPU code. The compiler is written in the same APL dialect, so the compiler itself runs on a GPU. I don’t know of any other example of a compiler that runs on a GPU.
The entire compiler is about 750 lines of code, as I recall. Each optimization pass is a line or two of code, and the full optimizer fits on a single page without scrolling. So you can see all of that code at the same time, and this is very valuable for refactoring.
For me, the rule is to never use
.unwrap
orpanic!
as “might as well die” because that produces an ugly and novice-unfriendly error message for the end user.It’s
.unwrap()
ortodo!
for prototyping (there’s a clippy lint to catch.unwrap
and not.expect
),.expect("rationale")
orunreachable!
for unreachable, and “Return an error that can be turned into a friendly message” for “might as well die”… especially since I’m always on the lookout for how to make my code reusable so it might become a library later and it’s bad enough that I often feel compelled to wrap third-party dependencies incatch_unwind
for want of a maintained Rustig! or findpanics.Slightly off-topic but I would be interested in knowing more about the UX principles behind error messages (especially as regards end users). It seems to be folk wisdom at this point. I’m just not sure I agree that displaying a back-trace — or an option to generate one — is any less novice-friendly than displaying an error message which may, or may not, describe the error correctly/in enough detail to be useful.
For me, “might as well die” inherently means it should present a message like “File X is missing.” or “Couldn’t connect to Y.com. Check your Internet and then see if the server is down.”
Ideally, I’d even want to use something like the https://lib.rs/crates/human-panic crate for unreachables.
My philosophy is that failing to find a way for the message to be actionable for the user is itself a bug… even if “actionable” just means. “The program is broken in way X. Please try reinstalling it and, if that doesn’t fix the problem, send this file to the developers so they can figure out whether the bug is in the program or the portion of the installer concerned with installing/repairing dependencies.
(I’m the guy who ported
gtkexcepthook.py
to PyQt5.)There are basically two sides to displaying a backtrace, both of which apply for stuff like the static site generator I wrote for my mother. You could refer to them as positive and negative.
$PWD/src/images/whatever.png
” and make it difficult to notice. (She’s in her 70s and even just a couple of lines ofgit
warnings that I forgot to send to/dev/null
were enough to trip her up)..expect(msg)
comes at the expense of denying me the ability present a by-design error message clearly enough.In essence, it’s the same problem you see whenever you have to guide someone on an issue tracker through scrolling back up the
make
orcmake
output until they find the actual error message buried under the stack of “failure while…“s.That is a bad error message. The error should say if there was a DNS error, and if so, was it servfail or nxdomain, or was the stub resolver unable to reach the DNS server? Or was there a connection failure, and if so, was it an ICMP port or host or network unreachable? Or was it a connection timeout?
An error cannot be actionable if it does not explain what went wrong. It should also explain what the program was trying to do when it encountered the problem.
Backtraces can be OK at explaining what the program was trying to do (if you have its source code) but they don’t always say what went wrong. For example, if you unwrap a Rust std::io::Error, the panic won’t tell you the pathname or the operation that caused the error.
Fair enough. I was trying to be intentionally vague to avoid calling out a specific example, but that just made it a bad example, period. If that showed up in an actual example, it would be the higher-level message that is then followed by the more specific text that was bubbled up.
I definitely agree with your point about backtraces and I’m well aware of the pathname problem with
std::io::Error
. For example, if I do use backtrace-style output in my bubbled-with-context errors (eg. in something purely intended for myself), I use messaging like this at minimum:Note the use of
Debug
quoting on thesrc
and source path to ensure that things like trailing whitespace will be as easy to notice as possible and the conscious decision to use greppable error messages (instead of source path and line number and the like) and rightward drift to mitigate the “wall of text”-ness that automatic backtraces tend to have.That particular example is from a case where, last I worked on it, I hadn’t figured out if there was a way to get
lol_html
to report the line number for the<img>
tag currently being rewritten.A more accurate example of the standard I try to hold myself to is how, for a miniserve-like-but-an-image-gallery tool that I really need to get back to working on, it uses a “What is my IP?” crate to present the user’s external IP address in the “ready to copy-paste to your friend” URL and I have plans to add UPnP support for automatic port forwarding when possible.
It’s worth noting that ‘slop’ has an earlier, if somewhat related, meaning in describing the base, retention-farming content you find on platforms like Tiktok or Youtube Shorts.
‘Somewhat related’ insofar as I think it’s the case the scripts, or ideas, for content farms that put out ‘slop’ were an early use-case for DNN-assisted content production. Alternatively, you could think of these platforms as maximising for retention, which gels with the analogy of DNNs as highly general optimisers.
I heard that called ‘sludge’.
What classifies content as “retention farming”?
For me it’s extremely low effort posting.
A common example is using “oddly satisfying” or “minecraft parkour” or “subway surfer” as background content, then select a recent top post from a popular reddit post and have a TTS narrate one of the top comments.
You can make 10 videos for the top 10 comments on the post, if you go for the top 14 posts and go by “top daily”, you can make 20 posts a day for 0 investment. Most of this can be automated.
There is scripts that will use recent news headlines to pick a topic via ChatGPT and have it generate a script that is then narrated by TTS and videofied by adding more filler content (“minecraft parkour”).
There isn’t even the effort of narrating the video by a VA of any sort (even if it’s the creator themselves) or collecting their own video footage.
Why would posting garbage increase retention? Or am I misunderstanding?
The videos tend to be not terribly long, 20-30 seconds or so. The way the topic is picked ensures it is likely to be interesting and the background video tends to keep things more busy than they really are. As a result, they get to take 30 seconds of your attention span in exchange for ad revenue.
They’re farming for the 30 seconds of attention it requires to rake in ad money, nothing more.
Oh, I thought the “retention” implied that they are somehow optimizing to keep their followers.
I’m pretty sure that is meant to say “attention”, not “retention”.
Exactly. That makes this proposal not very sensible. It’s like if I said “Swiftie is the new name for a fan of the Swift programming language” or “parallelism is the new name for concurrency.”
See also XP.css and 98.css.
I wonder why those projects only implement the default color scheme and don’t provide a way to change it. Windows used to be very much themable and came with multiple color schemes for default window decorations, apart from the option to make completely new themes from scratch.
OMG remember the themes in Windows 98 where it would add a bunch of weird sound effects and even aggressively change the mouse pointer to some animated monstrosity! Loved it!
Guessing the 98.css link was supposed to be https://jdan.github.io/98.css/ ^^
“Readme is a bit sparse, I suppose I’ll look at the tests to understand what this is about.”
The tests:
You can read Aaron Hsu’s thesis to understand the codebase better. The author has said their thesis is the Literate Programming version of co-dfns.
Especially section 3, which explains how are trees represented and why. Even if you wont necessary use the same representation in a more mainstream language it shows some important considerations for writing brachless, parallelizable code.
https://scholarworks.iu.edu/dspace/items/3ab772c9-92c9-4f59-bd95-40aff99e8c7a
It’s an APL compiler that generates GPU code. The compiler is written in the same APL dialect, so the compiler itself runs on a GPU. I don’t know of any other example of a compiler that runs on a GPU.
The entire compiler is about 750 lines of code, as I recall. Each optimization pass is a line or two of code, and the full optimizer fits on a single page without scrolling. So you can see all of that code at the same time, and this is very valuable for refactoring.
It is an impressive feat of engineering.
It gets significantly harder to read than that, although APLers (myself included) have a slightly different notion of readability.
If you’re genuinely looking for more information, the two Dyalog user meeting videos under ‘publications’ flesh things out a bit more.
also, is the rectangle an actual APL symbol or does github break the source code by defaulting to UTF-8?
The rectangle is an actual symbol; it prefixes system names.
⎕ is called Quad, and yes it’s used in APL! When used by itself, it’s something like standard out.
It’s not very interesting as such otherwise, or even a bit messy, it’s where all the system functions and variables go, so called quad names.
⎕EX, for instance, is expunge. It tries to erase a name from the scope, and returns 1 if successful, 0 otherwise.
⎕NL, on the other hand, lists all the names of all the things you specify the name class of.
So yeah, ⎕. Not to be confused with ⎕IO which specifies whether your APL is 0 or 1 indexed :).
EDIT: I should add, some of this information is Dyalog specific.