On Tue, Dec 23, 2014 at 9:20 AM, Geoffrey Irving <[email protected]> wrote:
Could you give a brief description of what the mutability inference or > lack of it would look like? Not really, no. As anybody here can attest, I probably can't give a brief description of the time of day. :-) In BitC v0, "mutable" and "readonly" (might have been "const") could be prefixed at any type. So you'd get things like: let x : mutable T = *initializer* in ... let x : mutable 'a = *initializer* in ... If you fail to state explicitly whether a parameter or variable is readonly, as in let x : T = *initializer* in ... then the best way to think of it is that you wrote (I'm making up notation): let x : ?mutable?(T) = *initializer* in ... with the result that mutability will be inferred. Mainly from the presence of assignment or as a result of passing *x* at an explicitly mutable by-reference parameter position. Mutability is not strongly contagious. Given an assignment of the form: x : 'lhs := *expr* : 'rhs obviously requires a mutable type for 'lhs, but the type compatibility requirement is merely that 'lhs and 'rhs be "copy compatible". Which is to say that they have compatible types excluding considerations of shallow mutability. All of this is pretty much what happens in BitC v0 today. I don't like the verbosity of the syntax, so I suspect that a convenience syntax such as one of let !x = *initializer* in ... let x := *initializer* in ... // Note := in binding might be worthwhile. In languages where mutability is the default, but an annotation is > possible, I generally find myself adding const / final / similar in > front of every single variable declaration to catch errors. > I agree that's a potential concern. For structure and union fields, the default is readonly, though there are some interesting issues with what "list 'a" should mean given that 'a can bind a mutable type. > I think there may be a distinction between simple variable mutability > and deep data structure mutability, though. Actually, it's way worse than that. It's not as simple as shallow vs. deep. There are valid use cases for deep *partial* mutability, and genericity over that presents some interesting challenges. You very rapidly get into the const vs. non-const vs. generic-over-mutability methods sort of problem. > In imperative languages I > often find myself wanting to write routines which are as generic over > mutability as possible (e.g., take three arrays, one of which has to > be mutable, one of which has to be deep immutable (because we store it > in a lazy closure, say), one of which can and should be either one). > Here mutability inference sounds lovely. > That's not generic over mutability. That sounds like an example of a procedure whose parameters are copy-compatible and which therefore doesn't care whether they are mutable or not. You're stumbling blissfully into the heart of one of the problems in BitC v0, which is that we failed to distinguish *immutable* (variable or field does not change) with *readonly* (variable is not modified by this consumer). I don't see why lazy closures require deep immutability. They may or may not require *shallow* immutability. Actually, I'm not sure why we're getting into lazy closures at all. > In contrast, I'd personally be fine without a notation of mutability > of simple variables, as long as the unboxing support is good enough > that a mutable cell is as fast as a mutable language variable would > be. Mutability and unboxing in BitC are completely orthogonal. We reject, as a strong design principal, any argument that starts with "well, it's okay to rely on the compiler to unbox this". The problem with it is that (a) the specification must now state an escape analysis algorithm so that we fully know the contract about what will/won't be unboxed, and (b) we lose the ability to obtain a diagnostic when unboxing does not proceed as we expect. > I.e., use ocaml's ref type, but unbox it. That's exactly the solution we seek to avoid at all costs. It's categorically non-viable in a systems language. > Mutability of simple variables is fragile in the presence of closures... I'm not sure why you say this. Fragile in the sense that the compiler can readily get the closure construction wrong, or fragile in the sense that the presence of a mutable thing in a closure leads to surprising programming consequences? From the compiler perspective there's no difficulty building a closure that contains a mutable variable. If that wasn't intended, the tip-off that this occurred is that the resulting procedure will not be typed as pure. > Python just gets in > wrong, Java disallows it entirely, and I spent half an hour on Friday > tracking on a bug in some Scala code that tied a var into a closure. Can you describe what each language does before we decide that it's wrong? shap
_______________________________________________ bitc-dev mailing list [email protected] http://www.coyotos.org/mailman/listinfo/bitc-dev
