moefh
They meant (like Wikipedia says) that traditionally a tetrachord spans a perfect fourth (i.e., that's the interval between the first and last notes), not that it's a stack of perfect fourths.
As to the original point, any discussion about dissonance of chords is meaningless without mention of temperament: in the modern tuning system (equal temperament[1]) both major and minor triads are pretty dissonant, look at the thirds at the table in the section named "Comparison with just intonation" in that Wikipedia page.
We have been dealing with the tension between keeping thirds and fifths pleasant for centuries: very roughly, people used meantone temperaments[2] in the Renaissance (which had perfectly tuned thirds), then came the era of well temperament[3], and eventually we settled for the simpler equal temperament we use today with its nasty thirds (it has several other advantages, but "having pleasant major and minor triads" is not one of them).
[1] https://en.wikipedia.org/wiki/Equal_temperament
Worrying about a couple of seconds or even minutes is completely insane for almost everyone.
No, an easy option is to simply shift every timezone by an hour and keep UTC intact. A ton of places already do that twice a year for daylight savings.
I never understood why we mess with UTC so much when we already have another widely used mechanism to keep the sun and clocks aligned.
Some assert that only envious is correctly used to describe someone who feels or shows a very strong desire for something that belongs to someone else, but in truth both envious and jealous commonly carry this meaning. Jealous alone is used to describe someone who tends to suspect unfaithfulness.
[1] https://www.merriam-webster.com/dictionary/enviousIt becomes a pain in the ass when you're generating a VGA signal with a microcontroller with 8 color output pins (3 red, 3 green, 2 blue). The meaning of a color value is very real in this setup: it corresponds to a voltage level you must send to the VGA monitor, 0V-0.7V.
So the blue channel will map (0->0V, 1->0.23V, 2->0.47V, 3->0.7V), and the red/green will map (0->0V, 1->0.1V, ..., 7->0.7V). Notice how none of the blue voltages match any of the red/green ones (other than the extremes)? That means you don't get to see any pure grays -- the closest ones will have bit of blue or yellow tint, depending on the direction of the difference.
Not only that, any gradients at all (other than the ones not mixing blue with the other channels) will be noticeable off: for example, the closest colors in the line between pure red to pure white will all be slightly orange or purple.
Code for VGA output in 8-bit color with double-buffered 320x240 framebuffer for the Raspberry Pi Pico 2 here, if anyone cares: https://github.com/moefh/pico-vga-8bit-demo
Fixing these, it runs mostly as advertised, but it seems to assume that one-letter types are always generic parameters, so it's impossible to (for example) generate this:
struct X;
enum A {
P(X),
Q
}
Trying this: (struct X)
(enum A (P X) Q)
produces this: struct X;
enum A<P, X> { Q }
while using a multi-letter type like `String`: (enum A (P String) Q)
produces the expected: enum A { P(String), Q }
One way to solve this would be to always require the generic annotation, and let it be empty when there are no generics, but when I tried that it did something weird: (struct X)
(enum A () (P X) Q)
produces: struct X;
enum A {
_ /* List([], Some(Span { start: 54, end: 56 })) */,
P(X),
Q
}
I have no idea where the `_` and the comment came from.[1] https://github.com/ThatXliner/rust-but-lisp/blob/70c51a107b2...
[2] https://github.com/ThatXliner/rust-but-lisp/blob/70c51a107b2...
Let me offer a nitpck: in the "Gradual underflow" section it says this about subnormal numbers:
Bonus: we have now acquired extra armour against a division by zero:
if ( x != y ) z = 1.0 / ( x - y );
But that's not that useful: just because you're not dividing by zero doesn't mean the result won't overflow to infinity, which is what you get when you do divide by zero.Think about it this way: the smallest subnormal double is on the order of 10^-324, but the largest double is on the order of 10^308. If `x - y` is smaller than 10^-308, `1.0 / (x - y)` will be larger than 10^308, which can't be represented and must overflow to infinity.
This C program demonstrates this:
#include <stdio.h>
#include <float.h>
#include <math.h>
// return a (subnormal) number that results in zero when divided by 2:
double calc_tiny(void)
{
double x = DBL_MIN; // the normal number closest to 0.0
while (1) {
double next = x / 2.0;
if (next == 0.0) {
return x;
}
x = next;
}
}
int main(void)
{
double y = calc_tiny();
double x = 2.0 * y;
if (x != y) {
double z = 1.0 / (x - y);
printf("division is safe: %g\n", z);
} else {
printf("refusing to divide by zero\n");
}
}
(It will print something like "division is safe: inf", or however else your libc prints infinity)Anyway, here's something more-or-less equivalent in Rust, which will blow the stack if made to loop too many times: https://play.rust-lang.org/?version=stable&mode=debug&editio...
(There may be a way to use a closure instead of a function to avoid hard-coding the type of `$i` in the macro, but I can't find an easy way to write a recursive closure call in Rust).
Maybe the same idea can be used in Rust where some constructs are easier to write in recursive form instead of a loop?
In any case, here's a silly example of a `for-loop` macro in Scheme using a tail call:
(define-syntax for-loop
(syntax-rules ()
((for-loop var start end body ...)
(letrec ((loop (lambda (var)
(unless (>= var end)
body ...
(loop (+ var 1)))))) ; <-- tail call
(loop start)))))
And here's how you'd use it to print the numbers 0 to 9: (for-loop i 0 10
(display i)
(newline))
This macro expands to a function that calls itself to loop. Since Scheme is guaranteed to have proper tail calls, the calls are guaranteed to not blow the stack.(Note that you'll probably never see a `letrec` used like this: people would use a named `let`, which is syntax sugar for that exact usage of `letrec`. I wrote it the `letrec` way to make the function explicit).
On the other hand, I probably wouldn't have recognized the F00F bug mention if you had actually written 0xc8c70ff0.
It wouldn't be surprising if the RP2350 gets officially certified to run at something above the max supported clock at launch (150MHz), though obviously nothing close to 800MHz. That happened to the RP2040[1], which at launch nominally supported 133MHz but now it's up to 200MHz (the SDK still defaults to 125MHz for compatibility, but getting 200MHz is as simple as toggling a config flag[2]).
[1] https://www.tomshardware.com/raspberry-pi/the-raspberry-pi-p...
[2] https://github.com/raspberrypi/pico-sdk/releases/tag/2.1.1
The article says the research was "focusing on 246 deceased drivers who were tested for THC", and that the test usually happens when autopsies are performed. It doesn't say if autopsies are performed for all driver deaths, and it also doesn't say what exactly is "usually".
If (for example) autopsy only happens when the driver is suspected of drug use, then there's a clear selection bias.
Note that this doesn't mean the study is useless: they were able to see that legalization of cannabis didn't have impact on recreational use.
That's not entirely accurate: "fixed-size" array parameters (unlike pointers to arrays or arrays in structs) actually say that the array must be at least that size, not exactly that size, which makes them way more flexible (e.g. you don't need a buffer of an exact size, it can be larger). The examples from the article are neat but fairly specific because cryptographic functions always work with pre-defined array sizes, unlike most algorithms.
Incidentally, that was one of the main complaints about Pascal back in the day (see section 2.1 of [1]): it originally had only fixed-size arrays and strings, with no way for a function to accept a "generic array" or a "generic string" with size unknown at compile time.
[1] https://www.cs.virginia.edu/~evans/cs655/readings/bwk-on-pas...
For example, both compilers do complain if you try to pass a literal NULL to `f1` (because that can't possibly be right), the same way they warn about division by a literal zero but give no warnings about dividing by a number that is not known to be nonzero.
That's is the current state of both gcc and clang: they will both happily, without warnings, pass a NULL pointer to a function with a `[static N]` parameter, and then REMOVE ANY NULL CHECK from the function, because the argument can't possibly be NULL according to the function signature, so the check is obviously redundant.
See the example in [1]: note that in the assembly of `f1` the NULL check is removed, while it's present in the "unsafe" `f2`, making it actually safer.
Also note that gcc will at least tell you that the check in `f1()` is "useless" (yet no warning about `g()` calling it with a pointer that could be NULL), while clang sees nothing wrong at all.
It can't do that because the program might load a dynamic library that depends on the function (it's perfectly OK for a `.so` to depend on a function from the main executable, for example).
That's one of the reasons why a very cheap optimization is to always use `static` for functions when you can. You're telling the compiler that the function doesn't need to be visible outside the current compilation unit, so the compiler is free to even inline it completely and never produce an actual callable function, if appropriate.
Sorry, but this is a pet peeve of mine: special relativity works perfectly well in accelerating frames of reference, as long as the spacetime remains flat (a Minkowski space[1]), for example when any curvature caused by gravity is small enough that you can ignore it.
Better context can be found here[1] (countries by emission per capita). It's still not great because it shows a lot of small countries at the top. For example: Palau is the first, but it has a population of a few thousand people, so their emissions are a rounding error when compared to other countries.
[1] https://en.wikipedia.org/wiki/List_of_countries_by_carbon_di...
> In Rust, sloppy programmers will [...]
You're comparing apples to oranges.
Inexperienced people who don't know better will make safe, bloated code in Rust.
Experienced people who simply ignore C warnings because they're "confident they know better" (as the other poster said) will write unsafe Rust code regardless of all the care in the world put in choosing sensible defaults or adding a borrow checker to the language. They will use `unsafe` and call it a day -- I've seen it happen more than once.
To fix this you have to change the process being used to write software -- you need to make sure people can't simply (for example) ignore C warnings or use Rust's `unsafe` at will.
People who write C code ignoring warnings are the same people who in Rust will resort to writing unsafe with raw pointers as soon as they hit the first borrow check error. If you can't force them to care about C warnings, how are you going to force them to care about Rust safety?
I've seen this happen; it's not seen at large because the vast majority of people writing Rust code in public do it because they want to, not because they're forced.
This is a silly thing to point to, and the very article you linked to argues that the lack of curly braces is not the actual problem in that situation.
In any case, both gcc and clang will give a warning about code like that[1] with just "-Wall" (gcc since 2016 and clang since 2020). Complaining about this in 2025 smells of cargo cult programming, much like people who still use Yoda conditions[2] in C and C++.
C does have problems that make it hard to write safe code with it, but this is not one of them.
No, Weil said he himself misunderstood Sellke's post[1].
Note Weil's wording (10 previously unsolved Erdos problems) vs. Sellke's wording (10 Erdos problems that were listed as open).
"No person shall circumvent a technological measure that effectively controls access to a work protected under this title [...]"
with these definitions[2]: (A) to “circumvent a technological measure” means to descramble a scrambled work, to decrypt an encrypted work, or otherwise to avoid, bypass, remove, deactivate, or impair a technological measure, without the authority of the copyright owner; and
(B) a technological measure “effectively controls access to a work” if the measure, in the ordinary course of its operation, requires the application of information, or a process or a treatment, with the authority of the copyright owner, to gain access to the work.
I think (A) pretty clearly applies: the glyphs being randomized in each request obviously counts as being "scrambled", the method used by the author with the hashes clearly descrambles them by matching the provided SVG images to the letters rendered with the book's font.I'm less sure about (B), not being a lawyer, but I think it's so generic that it does apply: the "ordinary course of [...] operation" of reading the book requires running the apps provided by Amazon. This seems to fit "requires the application of [...] a process [...] with the authority of the copyright owner".
[1] https://www.law.cornell.edu/uscode/text/17/1201
[2] https://www.law.cornell.edu/definitions/uscode.php?width=840...
With that `char msg[static 1]` you're telling the compiler that `msg` can't possibly be NULL, which means it will optimize away any NULL check you put in the function. But it will still happily call it with a pointer that could be NULL, with no warnings whatsoever.
The end result is that with an "unsafe" `char *msg`, you can at least handle the case of `msg` being NULL. With the "safe" `char msg[static 1]` there's nothing you can do -- if you receive NULL, you're screwed, no way of guarding against it.
For a demonstration, see[1]. Both gcc and clang are passed `-Wall -Wextra`. Note that the NULL check is removed in the "safe" version (check the assembly). See also the gcc warning about the "useless" NULL check ("'nonnull' argument 'p' compared to NULL"), and worse, the lack of warnings in clang. And finally, note that neither gcc or clang warn about the call to the "safe" function with a pointer that could be NULL.
I don't know enough about how people use the go assembler, but I imagine it would be very surprising if `add $imm, rsp, rsp` clobbered an unrelated register when `$imm` is large enough. Especially since what's clobbered is the designated "temporary register", which I imagine is used all the time in handwritten go assembly.
When you use `var`, everything is as statically typed as before, you just don't need to spell out the type when the compiler can infer it. So you can't (for example) say `var x = null` because `null` doesn't provide enough type information for the compiler to infer what's the type of `x`.