114 karma · joined February 16, 2021
Edit: For API comments it's "what" of course, detailing the workings and contracts of the exported method, function or type, so one doesn't have to read the code to figure out how to use it.
For example:
local
val backupIntervalHours = 24
val approxBackupDurationHours = 2
val wiggleRoomHours = 2
in
val ageAlertThresholdHours = backupIntervalHours + approxBackupDurationHours + wiggleRoomHours
end
Then it's easier to document what components a constant is composed of using code without introducing unnecessary bindings in the scope of the relevant variable. Sure constants are just data, but the first questions that pops into my head when seeing something in unfamiliar code is "What is the purpose of this?", and the smaller the scope, the faster it can be discarded.For me, base CMake is pretty easy by now, but I'd rather troubleshoot a makefile than some obscure 3pp CMake module that doesn't do what I want. Plain old makefiles are very hackable for better or worse [1]. It's easy to solve problems with make (in bespoke ways), and at the same time this is the big issue, causing lots of custom solutions of varying correctness.
[1]: Make is easy the same way C is easy.
But I concur that realloc is mostly pointless. For code that want to grow or shrink, I think it's much better for it to know the data block size. I think there's very little opportunity to happen to have free memory next to your allocation that can be "grown into". At least for slab like allocators, so the growing room is minimal.
It's a bit difficult to unify all APIs because data will be needlessly passed around, when in most cases you don't care. Aligned allocation may also need a slightly different implementation anyway.
realloc and calloc are warts in my book...
- Taking environment variables into account as a dependency (they may affect Makefile logic and also code generation by tools that interpret them).
[^1]: https://www.gnu.org/software/automake/manual/html_node/Multi...
"var x []int; fmt.Printf(`%p %d`, x, len(x))" outputs "0x0 0"
Indexing "x[0]" results in: "panic: runtime error: index out of range [0] with length 0"
They can also be appended to and then produce a valid slice.
You need to care if using mmap directly to map files or other resources into the virtual memory address space. The default page size can be queried using for example sysconf() on Linux. I guess something like garbage collectors in language run-times would also use mmap directly as it's most likely to side step malloc/new.
An application would normally not use madvise, unless also using mmap for some special purpose.
It depends on the CPU architecture how flexible it is with different page sizes. For example, from what I recall, MIPS was extremely flexible and allowed any even power of two size for any TLB entry.
x86_64 only support three different page sizes, 4 kB, 2 MB and 1 GB and there are limitations wrt the number of TLB entries that can be used for the larger page sizes.
So, yea, there are bound to be regressions if just trying to switch to 2 MB as a default but I think it should be doable. Not all archs use 4 kB to begin with.
I know there has been such designs in the past but I don't know how it works in the Ryzen CPUs.
The original JPEG standard is an ISO standard (ISO/IEC 10918) with payed access.
MP3 is also an ISO standard (ISO/IEC 13818-3). Perhaps not as relevant today but was once used by basically everyone.
Access to the standard is only relevant to the implementer. It's of no consequence to users of a piece of software.
portable = able to port
That's my armchair take on it.
/*
gcc -g -Wall -o x x.c
gdb ./x
(gdb) r
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x0000555555554617 in foo () at x.c:6
#2 0x0000555555554628 in main () at x.c:10
(gdb) f 1
#1 0x0000555555554617 in foo () at x.c:6
6 bar();
(gdb) p bar
$1 = (void (*)(void)) 0x0
*/
#include <stddef.h>
void (*bar)(void) = NULL;
void foo() {
bar();
}
int main() {
foo();
}But was the built-in append function generic pre generics? I think it is?
E.g. map[int]*MyType
Using interface{} is quite common in the absence of sum types (or inheritance with base class). I guess interface{} is like Object in Java.
It's not worse than Python or other dynamic languages that many people are fine with. The run-time panics when asserting that a type is something it's not.
E.g. https://go.dev/play/p/c4hx8HSiB8I
That said, no, it's not optimal and could be better (IMHO).
It seems there are a bunch of languages in the fast but not quite as fast as C/C++ category: Java, C#, Go, OCaml, SBCL (Lisp), Haskell
I'm pretty skinny but like to eat junk food and candy. My target weight is 80-82 kg. When I hit 90 kg I don't feel good about myself. Pants too tight etc.
First time I hit 90 kg was 2013. I tried intermittent fasting 8/16. This worked really well for me at that time. I lost weight really quickly. I could even continue my bad eating habits within the 8 hour window where eating is allowed and still loose weight.
I've stuck with a 8/16 diet with cheating up till now. Beginning of this year I hit 90 kg again. My old intermittent fasting diet did not seem to have the same effect any more (granted I cheated quite a bit at the end). I tried mixing it with Keto, counting every kcal, grams of carbs and fat in a log book. In one month I lost 8 kg so I think it was successful. I'm off Keto for now but I may be a trick you want to try. My main takeaways from Keto is that it really does take away your cravings. I could also do longer periods of fasting (did 36 hours two times) which I think would have been very hard for me when on a carb rich diet.
It could be less verbose without loosing readability. My two top picks would be to add a ternary expression and a real while loop so that you could write better iterators.
while next := some.Next(); next != nil { // ... }
Such a while loop would be consistent with the if statement support for an assignment and following check.