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

Reply via email to