[Grace-core] Immutability in Grace

James Noble kjx at ecs.vuw.ac.nz
Sat May 17 22:56:35 PDT 2014


(replyto list cut to grace-core) 

> The repository is indeed at https://github.com/cgizmo/minigrace. I'm not sure I mentioned this last time, but the interesting files are:
>  _ gracelib_threads.* - pthread state, startup and destruction routines
>  _ gracelib_msg.* - thread mailboxes
>  _ gracelib_gc.* - threaded(-ish) modification of the GC
>  _ actors_prim.c - Grace module for low level actor functions (spawn, poll, post, etc.)
>  _ actors.grace - Thin "Erlang like" wrapper around actors_prim, to see what it would look like

OK yep...

> > Ok yep. In general I prefer the idea of annotations to new language constructs. 
> > I can see how defs could be used in immutable objects - but surely not vars?  
> 
> Since def/var represent the mutability of the reference, the "is immutable" annotation would apply to the referred data. Then it would be valid to have a "var x is immutable" point to immutable objects, as long as that "var" was not itself within an immutable scope.

so again, I don't think this should be an annotation on the var or def declaration itself - perhaps on the type of the declaration 

var x :  Foo is immutable  

> > - (in that sense I think immutable is also *brand* 
> > - look at the grace brands paper in the GracePapers/Brands svn direction under review, not yet accepted anywhere. 
> 
> I have read the Grace brands paper, but I don't think the implementation is present in minigrace yet.

ask Tim!   It should be somewhere. 
> 
> Regarding the two immutability proposal ("immutable rules - static version" and "immutable rules - dynamic version" in your previous email), both would require some sort of knowledge about methods to ensure that they do not modify the state (the "purity" annotation). 

more or less yes, but that's true of any proposal - unless you introduce a whole new sort of thing into the language.
I mean: O'CAML is great. 

> As far as I can tell, neither approach would be able to make any deductions about the purity code without the help of the user, since there is no simple way of knowing (especially with the foreign C modules) whether data will be modified or not.

that's true, though, for *every* proposal, and every C module. 
the dynamic system can work without annotations - 
calling in to an immutable sets a bit in the interpreter context, any write we have control over checks the bit.

> I'm not sure how one would go about omitting annotations (to "give some static checking when warranted", in the spirit of gradual typing) and still have the system throw a runtime error when necessary. Because of this, I fail to see how the dynamic approach could be applied in this case.

it can be applied, and I think Donald Gordon did it - his stuff shoiuld be around somewhere,
if Google can't find it I can hunt it up (not sure the publication covered this part of things).

> On another note, I think it be possible to solve the problem that Michael brought up by further restricting the definition of pure methods to "referentially transparent". The issue regarding inheritance, as far as I understand it, would disappear as that code would simply not be allowed.

certainly the inheritance issue can go away like that. 
other ones, I'm not so sure.  I'm not sure what you mean precisely by "referentially transparent"
(especially as its in quote marks) --- does not read *any* mutable state, perhaps?
(which is subtly different to conditions like "does not read my mutable state, or 
does not read or write any mutable state :-)

> I do not think it would be too problematic a restriction, because objects that need to travel could then be structured in a "data object"/"IO wrapper object" way.
> 
> method makeDataObject {
>   object {
>     // I am immutable
>     def x = 1
>     method size { x } // Referentially transparent
>     // post(otherThread, self) - not referentially transparent, not allowed
>   }
> }
> 
> method makeDataObject2 {
>   object {
>     // I am immutable
>     inherits makeDataObject
>     def y = 2
>     method size { y } // Referentially transparent
>   }
> }
> 
> method makeIOObject(dataObject) {
>   object {
>     // Not immutable anymore
>     post(otherThread, dataObject) // Safe
>   } 
> }
> 
> Since the IO wrapper does not directly depend on the data, it can just be re-wrapped around the dataObject by the other thread on arrival to access its functionality. Of course, the wrapper will only have read-only access to the data, so any impure method operating on the fields of the dataObject will need to make a copy.

sure. ugly but sure. 

You should also look at other options about what to do with object references sent to other actors.
There's an OOPSLA 31 paper ?? someone and Gruber I think ?? that has a nice twist - you can *send*
references yourself or other objects to other actors, but those other actors *cannot request methods*
on those references. The references are only useful once they're sent back to their "owning" actor. 
This again is quite amenable to dynamic checks...

James


> Charlie
> 
> Le 15 mai 2014 à 11:56:39, James Noble (kjx at ecs.vuw.ac.nz) a écrit:
>> 
>> > So I have added Tim to CC... 
>> 
>> oops sorry. In fact this can go to Gracecore, really: 
>> if anyone doesn't get two copies of this email, then they should sign up to grace-core: 
>> I've set reply-to grace-core 
>> 
>> >> I copied in an older email from me below 
>> >> 
>> >> there are at least two different ways we could layer immutability on top of existing Grace objects. 
>> >> 
>> >> A) immutable rules - static/algebraic/implementation version (cribbed from newspeak as per email below) 
>> >> 
>> >> * immutable object/class can have no vars (fields), only defs, methods (& types ?) 
>> >> * All its defs must contain immutable objects. 
>> >> * it can't close over any vars 
>> >> 
>> >> OR 
>> >> 
>> >> B) immutable rules - dynamic/coalgebraic/specifcation version (I think some systems have done this, like constrainedBeanShell or something, obcure dynamic ownership langauge we did 10+ years ago) 
>> >> 
>> >> * any method request on an immutable must be evaluted "purely" 
>> >> * any attempted to read a field (i.e. a var) in pure mode raises an error 
>> >> 
>> >> the dynamic rule is nice in that it's gradual; put "is immutable" on any object you're defining, 
>> >> and the runtime must check. The catch is you now have to compile methods differently for 
>> >> immutable and non-immutable objects - probably best to just follow Newspeak and say 
>> >> that immutable objects must inherit from ImmutableObject... 
>> > I don't think an immutable object is necessarily the same thing as an 
>> > object whose methods are completely pure, even conceptually. 
>> 
>> I guess it depends on what we mean by "immutable" doesn't it? 
>> 
>> one definition is: requesting a method from an immutable object 
>> with the same arguments (for some suitable definition of "the same") 
>> always returns the same result. (carefully ignoring side effects). 
>> 
>> Bart Jacobs The Elder has looked at this coalgebraically 
>> but I don't think his treatment covers every practical situation. 
>> 
>> >> in order to give some static checking (when warranted) you could add in an immutable annotation 
>> >> on both objects and types, that would work like this: 
>> >> - immutable objects/classes may be annotated "as immutable" 
>> >> - it's an error to annotate as immutable if your object class doesn't meet the immutable rules we picked above 
>> >> - types can be annotated as immutable too, in which case they only match immutable objects 
>> >> - (in that sense I think immutable is also *brand* 
>> >> - look at the grace brands paper in the GracePapers/Brands svn direction under review, not yet accepted anywhere. 
>> >> 
>> >> Charlie - does this help? 
>> >> OK, that's probably asking a bit much, so: does this make any sense? 
>> > You also have to deal with inheritance somehow. I'm not sure which way 
>> > addresses that better. 
>> 
>> the obvious rule is that immutables can only inherit from immutables. 
>> 
>> > I can inherit from something that looks like it's immutable where I 
>> > wrote it and have my object be mutable, 
>> 
>> so the "something" can be immutable, and now your thing is mutable. 
>> 
>> > and then there are the cases 
>> > Andrew's pointed out where you get nondeterministic uninitialised-field errors: 
>> > Any immutability design has to at least think about how it plays with those. 
>> 
>> yes there are issues with initialisation where our naive rule doesn't always do what you like. 
>> I'll only be nondeterministic when you have threads - I see that as an issue of threading. 
>> Notably, Charlie's working with an actor model which could finesse some of these issues. 
>> 
>> James




More information about the Grace-core mailing list