4 ms·
You don't need to reach for Haskell or Rust, you can wrap any unsafe string in an UnsafeString type that can't be mistaken for a plain string. I was hoping the
by karmakaze 4y ago
You don't need to reach for Haskell or Rust, you can wrap any unsafe string in an UnsafeString type that can't be mistaken for a plain string. I was hoping the post would get to saying 'make wrong code into errors'.
- MauranKilom 4y agoYou can't always encode every semantic mismatch in the type system (or be checked by the compiler in general). Although with a sufficiently powerful type system, at least the ones that are reflected in variable naming should be catchable. For example, the convention of naming your 4x4 matrix transforms AfromB leads to the following kind of composition: vecInD = DfromC * CfromB * BfromA * vecInA Here, you can very clearly spot any mismatch (e.g. if someone put BfromC in the middle instead). With the right language, you could also have each matrix source and destination reference frames encoded in the type system if you so desired. Where it gets harder to produce errors is higher-level patterns that transcend adjacent names: if (atomicVariable.read()) { /* something that assumes atomicVariable is true */ } This should invite suspicion - it is clearly concurrent code, so what prevents atomicVariable from changing right after entering the if?
- spockz 4y agoReading ad-hoc is fine if you just want to observe the value at some point in time. That is why there is room for both a “peek” function, maybe should be called “unsafeRead”, and a “withValue” method that takes a function with the actual value as argument and locks the atomic variable while executing the closure. This prevents the user from ever forgetting to write the lock.
- MauranKilom 4y ago> Reading ad-hoc is fine if you just want to observe the value at some point in time. There are such cases, indeed. Double-checked locking comes to mind. But if the code inside the if does assume the atomic to have a given value, it is almost surely wrong (absent of other synchronization mechanisms, such as in double-checked locking).
- tialaramex 4y agoI agree with the thrust of your argument but for your harder example this is exactly the sort of thing Rust does encode in the type system? If I read that I'd assume the block cares not that atomicVariable is true but only that it was, at least briefly, true.
- MauranKilom 4y agoWell, you kind of underline my point: Rust does not encode the difference between "is true" and "was, at least briefly, true" in the type system. You can reach for other types/abstractions (and whatever data you touch inside the if might also have the borrow checker up in arms), but that above code as written is suspect.
- josephcsible 4y ago> Rust does not encode the difference between "is true" and "was, at least briefly, true" in the type system. Couldn't it encode that by taking advantage of the fact that nobody else can change a variable while you have it mutably borrowed?
- marcosdumay 4y agoIsn't that exactly what people do. This thread seems surreal to me. Rust type system does encode exactly what the later comments are complaining that isn't encoded. And you sate what code cares about the variable keeping its value through a code block, between a pair of braces.
- MauranKilom 4y agoWhat I meant was *For atomics*, rust does not encode the difference between "is true" and "was, at least briefly, true" in the type system. Obviously, rust has many ways to track this kind of distinction in a compile-time manner (and yes, the borrow checker is one of them). That was not in question.
- tialaramex 4y agoWhat's nice about Rust here is that the coercion can be silent but it isn't by default. So open("file") works even though not all file names are strings, but matrix + filename is a compile error rather than doing something nobody wants. That results in a cultural difference (new type idiom) that makes UnsafeString viable while in some languages you could do it but you wouldn't
- spaceywilly 4y agoThank you, I had the same fuzzy thought in the back of my mind while reading this but couldn’t quite put it into words. The idea of depending on developers to understand “usFoo” means this is an unsafe string and “sFoo” means this is a safe string seems error prone. Those rely on the developer knowing what “us” and “s” represent. A much better idea would be to give that information to the compiler, so the developer can get a useful error if they try to do something unsafe. We should try to turn these onto compiler errors as much as possible so if a developer does something bad, it wont even compile. This seems like a much more fool proof way to accomplish what the author is trying to do.
- deleted 4y ago[deleted]
- BryantD 4y ago100% true. It’s a sign of evolving understanding of software engineering — in 2005, it was still common to believe that the best way to prevent errors was to help fallible human beings learn to detect them better. Now, well, it’s still common but we’re overall getting smarter about letting computers protect us from ourselves. (And the kind of technique described here still matters because you should understand why the guardrails are where they are.)