254 karma · joined April 10, 2009
The docs https://pkg.go.dev/context#Context suggest a way to make it type-safe (use an unexported key type and provide getter/setter). Seems fine to me.
> What if you just use a custom struct with all the fields you may need to be defined inside?
Can't seamlessly cross module boundaries.
If you look at the Hardened Javascript example:
const makeCounter = () => {
let count = 0;
return harden({
incr: () => (count += 1),
decr: () => (count -= 1),
});
};
The "counter object" here is mutable. I think that's what they mean.The report discusses this, and mentions two reasons against doing that:
- What happens if you do it, and then the referendum votes against joining? You're screwed from both ends.
- Due to the previous reason, there will be extreme pressure to vote for joining in the referendum, making it not very democratic.
First, under this system, long-term speculation is not really viable, due to the high tax. So the buyer must have some reason for paying higher than the price you set, which you don't see, i.e. you under-utilize the asset. Google/Facebook ads work this way - every slot is always up for auction. Also similar dynamics in partnership agreement's "shotgun clauses", etc.
Second, you can always factor in your sentimentality into your price, then the buyer will buy your neighbor's house instead. But you have to pay for it in the form of a higher tax. This is like a penalty for obstructing economic efficiency.
Third, this system pretty much does away with the strict idea of private property, into what they call "partial common ownership". It's basically a way to have shared ownership (as in communism) without the central planning, i.e. in a way that might actually work. (In fact, it quite reduces the role of government.)
I'm not advocating for this system, but I think it's fun to think about.
Every citizen and especially corporation would self-assess the value of assets they possess, pay a roughly 7% tax on these values and be required to sell the assets to anyone willing to purchase them at this self-assessed price.
The gist is:
Rule #1: All instance variables must be private
Rule #2: No mutable static state or statically accessible authority
Rule #3: No mutable state accessible across thread boundaries
Here is an interesting proposal on how to possibly get there in JS with import maps: https://guybedford.com/secure-modular-runtimes
Deno uses ambient permissions for the entire process and unfortunately missed the opportunity to do it right.
The method of sandboxing using OS processes + namespaces and what not is too heavy and unusable at such granularity.
The method of per-dependency static permission manifests in some meta-language is also poor.
The method of a single IO monad is too coarse. Also using any sort of `unsafe` should not be allowed (or be its own super-capability).
Obviously there are many tricky considerations. [For example, it is anti-modular - if suddenly UsefulService does need filesystem access, it's a breaking change, since it now must take a FilesystemService. But that sounds good to me - it's the point after all.] But does any language try to do this?
It is believed to be one of the oldest hunting techniques, and so would indicate that humans are in fact meant to run long distances. According to Wikepedia, the runner runs for "about two to five hours over 25 to 35 km (16 to 22 mi)".
> ./do tries a list of compilers in compilers/c, keeping the fastest working implementation of each primitive. Before running ./do you can edit compilers/c to adjust compiler options or to try additional compilers.
Your view of dependencies is very idealistic. And if I'd venture to guess - apologies if I'm wrong - young, at least to programming. I'm saying this because you don't tend to hear such phrases once reality hits.
Everything you said can be flipped:
> If I import this code in my codebase directly instead of using a library, it suddenly becomes my "responsibility" if it breaks.
I have full control & understanding of the code; I can adjust & trim so it fits as much as possible. If it breaks, I can fix it directly.
> And when we're talking about a FOSS side-project, I don't have that kind of time.
Copying/hand rolling some trivial code is often faster than deciding among a dozen libraries which do the same thing, reading their docs, their issue pages and open PRs, adding and integrating to my project.
> Third-party libraries means I get any improvements and bug-fixes for free.
I must keep the dependencies updated. I must read changelogs and hope nothing breaks.
> And if it breaks, I get to talk with the original maintainer to figure it out
I must use inefficient communication with a more-often-than-not absent maintainer in order to resolve my problem instead of fixing it directly.
> I suddenly will be alone trying to figure out what I did wrong
I am able to be self-reliant in fixing the problem, because I wrote the code and I understand it.
I do not have to trust the maintainer of the package or the maintainers of any of its transitive dependencies to be competent or non-evil.
---
For some things this is worth it. IMO for generating 16 random bytes it is not worth it.
crypto = require('crypto');
function uuid4() {
const bytes = crypto.randomBytes(16);
bytes[6] = (bytes[6] & 0x0f) | 0x40;
bytes[8] = (bytes[8] & 0x3f) | 0x80;
return bytes.toString('hex').match(/(.{8})(.{4})(.{4})(.{4})(.{12})/).slice(1).join('-');
}/proc/sys/kernel/pid_max
> PID_MAX_LIMIT, approximately 4 million
/proc/sys/kernel/threads-max
> FUTEX_TID_MASK (0x3fffffff), [approximately 1 billion]
For per-process limit, increase RLIMIT_NPROC.
> I will, in fact, claim that the difference between a bad programmer and a good one is whether he considers his code or his data structures more important. Bad programmers worry about the code. Good programmers worry about data structures and their relationships.
// This is safe since we check the return value.
let sock = unsafe { libc::socket(libc::AF_INET, libc::SOCK_DGRAM, 0) };
if sock < 0 {
return Err(Error::CreateSocket(IoError::last_os_error()));
}
I think in this case it would be better to put the return value check within the unsafe block, this way the unsafety does not "leak out" of the block, so to speak, so it is easier to audit. Of course in such a trivial case it does not matter much.There are a couple of options I'd like to see added to the Python configuration though before I could try it:
- Ability to point it at a virtualenv.
- Ability to set environment variables for the application.