On 9/30/10 12:25 PM, Graydon Hoare wrote:
Part #1 of the proposal is to split the concept we're currently calling
an effect in two pieces: the "effect" concept should have a concept I'm
calling a "stratum"[1] split off and handled independently. The stratum
of a type is the class of storage it belongs to: "immutable, shareable,
pure" vs. "local, mutable, non-shareable". Where we currently say that
"every type has an implied effect", the revised statement under this
proposal would be "every function has an implied effect, every type has
an implied stratum".
Perhaps we could allow the programmer to annotate the stratum of an
object? If the annotation is present, it's checked for accuracy; if not,
it's inferred from the type. So, instead of an *implied* stratum, we'd
have an *inferred* stratum. I was always a little uncomfortable with the
stratum of a type being something hard for the programmer to discern at
a glance, since it's such a critical aspect of the language.
Part #2 of the proposal is a bit juicier: add a third stratum back in,
"gc". We had this briefly a year or so ago, called "cyclic" back then,
but I think "gc" is a pithier qualifier. We merged the concept into
"state" when devising the current effect system, but I suspect that was
a mistake.
How do we enforce that a state, but non-gc, type remains acyclic?
- State values could be frozen and thawed, reasonably, to and from
stateless values. State means acyclic-and-mutable, after all, so
in the singly-referenced case this would even wind up a no-op. This
is the easy case of freeze/thaw, and it'd be formally denoted in
the type system. This would provide a great utility for two idioms
we currently have no good way to support: freeze-and-apply-predicate
and freeze-and-transmit-over-channel.
If we support this, it might be useful to have a compile-time "type
function", say, "frozen", that takes a state, non-gc type and returns a
deeply immutable non-state version of it. For example:
frozen int == int
frozen mutable int == int
frozen rec(int foo, mutable int bar) == rec(int foo, int bar)
I could see this being handy when declaring predicates over large,
complex, stateful types. To write a predicate "p" over a complex type
"foo", the programmer could simply write:
fn p(frozen foo x) { ... }
This would avoid forcing the programmer to copy and paste the type of
"foo" and perform s/mutable//g in order to type the predicate.
- State values could also have a our structural comparison definition
extended to them. Again, acyclicality wins here.[2]
Yup, sounds good, assuming we can actually enforce the restriction.
[2] we could even extend comparison to gc types if we say "gc types are
compared by address". It would be a little unpredictable though; I'm
tempted to define a "std.util.addrcmp[gc T](&T a, &T b) -> order" that
compares anything by address, along with a memcmp that compares by
memory-content, and make the "built-in" operators <, =, etc. structural
on acyclic types and errors when applied to a gc type. Safer, no?
+1
Patrick
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev