EuAndreh
Joined 12 years ago
Joined 12 years ago
I have not deleted any of my daily borg backups for many years, covering my laptop and some servers. Borg has an equivalent `borg serve` feature as detailed in the article.
I use borg mount every other week. After the initial config, you can just type:
$ borg mount :: borg/
...and browse the full archive lazily. Most of the time I'm looking at the last entry, but I've done some historical searching once or twice.Even though I count the rsync.net backup only once in the 3-2-1 backup rule, its geo-distributed under the hood, so there's also that.
I forgot to update the payment credit card once and got a few months of grace with periodic notices, but no service cut and excellent customer support.
I'm also fond of their stance on pretend standards, like PCI compliance: https://www.rsync.net/resources/regulatory/pci.html
IIRC I created the account for use as a git-annex remote, but I've used it for archival and sshfs, which is very convenient.
https://pubs.opengroup.org/onlinepubs/9799919799/utilities/e...
They "can arguably be construed as the violence" from a discriminatory argument. An honest argument wouldn't provide us this false equivalence.
- marketing;
- big companies using it;
- familiarity;
- history of the creators;
- history of the influencing languages;
- timing;
- luck;
- regional usage;
- etc.
Despite some programmers seeing themselves as fully rational making cold decisions, we're like everyone else.Not true.
On the one hand, just see how many non-compiled languages are used outside of primitive school projects.
On the other hand, this simpler approach is actually faster for writing actually fqst compilers. Many modern compiled languages have compilers that work on the order of ~100ms on a simple file with 1k LoC, when it could (and arguably should) work on the order of ~1ms, IOW, imperceptible given the syscalls overhead.
A 100x faster compiler that generates meh code is more useful 99% of the time: when one is recompiling all the time during development.
As is, C already is single-pass compilable, modulo some unnecessary syntax ambiguities.
As the compiler reads the text, it marks some character strings as tokens, these tokens are grouped as a fragment of code, and some fragments of code are turned into machine code. A simple function of a 100 lines doesn't need to be parsed until the end for the compiler to start emitting machine code.
Like the parser, this requires memory to keep tabs of information and doesn't work for all types of constructs, like a jump instruction to a label defined later in a function. The code emitter soaks input untill it is possible, and does so, like when the label is already known and can be jumped to.
Stand-aloneness and single-passness are orthogonal.
> I found no advantage to a single pass compiler. It isn't any faster.
A gigantic advantage: a single-pass-compilable language is simpler. By definition.
Implementations may or may not be simpler or faster.
> C++ doesn't allow forward declarations either.
Well, that's not what I meant.
C++ is "C with just this thing" done way too many times.
> The trouble with such sayings is like following a google map that says cross this bridge, but wasn't updated with news that the bridge is out.
TBH, I didn't really get this. Is this about sticking to C as is, but it is outdated as is?
C would be outdated if it didn't have, say, long long for 64-bit numbers. Having "true" be a keyword instead of a macro doesn't change how outdated it is or isn't, just like compile-time evaluation also doesn't.
> They are once you use another language that doesn't have those restrictions.
I have used many, and I still don't find them obvious.
> C adds new things all the time to the Standard, like normalized Unicode identifiers, which are a complete waste of time.
I agree that many/most are a waste of time, and shouldn't be added to C. The fact of C adding things to the standard all the time shouldn't justify adding even more things, but make one question if those are needed at all, and how to accomplish the goal without it.
> Every C compiler also adds a boatload of extensions, some good, some wacky, many ineptly documented, all incompatible with every other C compiler extensions.
I know about that, and my position is the same: just don't.
I don't use them also.
I have a much better list for things to add to C: Nothing. C isn't perfect, or nearly as good as it could be, but simply adding things onto C gets you C++.
Adjusting what sircmpwn says: in C you don't solve problems by adding features, but by writing more code in C.
I liked an answer on stack overflow on a question on "how to write a generic function wrapper in Go", or something similar. Many suggestions included reflection, but the author wanted something simpler with varargs without reflection. A comment simply said: "wrong language".
I'd rather adopt this position for some languages, instead of add more and more to C3X. I do away with things in C23, and don't want even more things added in to C.
Making a strech of OP's arguments: "look at all this cool things that C could do, and that D does!". Well, go on and use D, nothing wrong with that.
(BTW, I do write test targets for every file in my C projects, but I'm not so much into jogging).
Those things aren't that obvious, and I'd rather not have them added to C.
Wrong language.
LISP doesn't really read well the bigger the codebase
[citation needed]- tech $X is from the 60s, therefore it is bad and/or outdated: one doesn't need to "disrupt" or innovate in everything to become modern. There are plenty of things from the 60s that still don't have a better replacement, and its OK to keep using it.
- "YACC-style parsers" clumps together parsers that are generated at compile-time, from declarative grammars, using LALR(1). But that's not inherit to the technique or algorithm: a parser can be LALR(1) from a declarative grammar and still extensible at run-time, or provide LL(1) alongside, or be built from statements instead of a grammar. There's nothing wrong with using PEGs over "YACC-style" parsers, but not for these distorted reasons.
A closure with no behaviour is just a pointer to the enclosed variable. A closure with 2 pointers is a pair, which you can get the car and cdr.
The runtime needs to make the pointee available outside its definition, so escape analysis, garbage collection, etc. But no dictionary is needed.