The Artima Developer Community
Sponsored Link

Weblogs Forum
Mutable Types

10 replies on 1 page. Most recent reply: Feb 6, 2006 5:57 AM by James Watson

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 10 replies on 1 page
Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Mutable Types (View in Weblogs)
Posted: Feb 2, 2006 8:33 AM
Reply to this message Reply
Summary
In of itself not that exciting, but it can enable some interesting paradigms.
Advertisement
I was looking for a solution to two problems. First I wanted an abstraction sufficiently powerful to allow programmers to develop their own "const" checking mechanism (or its inverse a "mutable" checking mechanism) without hard wiring such a thing in the language. Second I wanted an abstraction which a programmer could use for checking at compile-time (or at least rely on the type-system) whether or not a variable had been "initialized".

The problem is that hard-wiring things like const, or non-null pointers, or regions (ala Cyclone), introduce significant complexity into a language design. These are powerful abstractions, but because they are hard-wired they are inelegant and contribute to overall language complexity and its inability to adapt to new paradigms.

A clue to a possible solution occured to me recently when examining Cyclone. A memory-safe dialect of C. It uses the type-system (at compile-time and run-time) primarily to assure that the program is type-safe.

What occured to me, was that the Cyclone group developed a more sophisticated static type system. What I want to see is this kind of system generalized so that a C dialect can have an easily extended type-system. (I have this nagging feeling that I am just reinventing OCaml in small steps, but at least I am approaching it as a software developer and not an academic simply interested in lambda calculus and type-safety proofs).

At this point is where my flight-of-fancy begins. I believe that a language where all variables (including the "this" pointer) can have their type redeclared, would be sufficient to cover many abstractions such as "const" or "is-initialized". Consider the following pseudo-code:

class Initialized<type T> {
  subtypes {
    T;
  }
}

class Const<type T> {
  subtypes {
    T;
  }
}

class FuBar {
  public 
  {
    def Init() { 
      assert(!is_initialized(this)) 
      reassign_type<Initialized<FuBar>>(this);  
    } 
    def Fu() { 
      assert(is_initialized(this)) 
    } 
    def Bar() { 
      assert(is_const(this)) 
      assert(is_initialized(this)) 
    } 
  }
}

FuBar a;
a.Fu(); // boom, not initialized
FuBar b;
b.Init(); 
b.Fu();
b.Bar(); // boom, not const
Const<FuBar> c;
c.Init();
c.Fu();
c.Bar(); 
This is just the rough beginning of an idea, but perhaps someone can tell me more about ML or other languages with flexible type-systems and how they compare with these kinds of abstractions.


Kresimir Cosic

Posts: 6
Nickname: kreso
Registered: Jan, 2006

Re: Mutable Types Posted: Feb 2, 2006 12:08 PM
Reply to this message Reply
When I was thinking about programming language design, I noticed the same set of problems that you describe, but found completely different solutions.

First, I don’t agree that 'const' should be handled through library, because in the end you might be missing some functionality. For example: some compile-time checks, and some compiler optimizations.

The problem with const is that it is some kind of fundamental concept, which allows programming language to have more control over aliasing (like in pure functional languages: it doesn't matter if you alias const object; so problems with aliasing disappear). I think that C++ way of handling 'const' is the right way, although it sill lacks some functionality. And it can be done extremely elegantly.

Changing types at run-time: I think I heard about this idea several times before. At start it looks great. But then you run into problem with compile-time type checks (can't be done) and memory management (what if new type is larger than old type...). In the end it boils down to: are you creating dynamically typed language or statically typed? If it's statically typed, then don't change types at runtime.

But I also noticed the problem with initialization. I don’t like suggesting incomplete solutions, but here I will make an exception: Constructors kind-of solve this problem. But I don't like constructors too much because they limit the ways in which you can initialize an object (whole initialization must be done in a single function call). So I thought (here I go controversial) that it would be a good thing to add a state machine to objects (where states and transitions would be declared in classes), and then require a certain state to call certain functions... then you can have complex initialization patterns, and it turns out that a lot can be checked at compile time. I don't want to go into more detail here.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Mutable Types Posted: Feb 2, 2006 1:29 PM
Reply to this message Reply
I would argue that making const pat of the language makes it easier for developers using that language. Maybe it complicates the language design but it simplifies use. I guess you have to ask yourself if you are designing the language for the users of the language or the designers of the language.

Have you looked into self-types in Scala? This seems vaugely similar.

Terje Slettebø

Posts: 205
Nickname: tslettebo
Registered: Jun, 2004

Re: Mutable Types Posted: Feb 3, 2006 3:27 AM
Reply to this message Reply
> The problem is that hard-wiring things like const, or
> non-null pointers, or regions (ala Cyclone), introduce
> significant complexity into a language design. These are
> powerful abstractions, but because they are hard-wired
> they are inelegant and contribute to overall language
> complexity and its inability to adapt to new paradigms.

Hm, do you mean to say that this:
class FuBar {
public
{
def Init() {
assert(!is_initialized(this))
reassign_type<Initialized<FuBar>>(this);
}
def Fu() {
assert(is_initialized(this))
}
def Bar() {
assert(is_const(this))
assert(is_initialized(this))
}
}
}
is more elegant than:

class FuBar {
public:
FuBar(...) {
// ...
}

void Fu() {
// ...
}
void Bar() const {
// ...
}
}
?

To me, having a lot of asserts at the beginning of a function, rather than using language abstractions like constructors and "const" as part of the type system, is more inelegant.

In your version, if someone forgets to use "assert(is_initialised(this))" at the start of a function, they risk operating on uninitialised data, invoking possibly undefined behaviour. By initialising the object in the constructor, you don't run the risk of using an uninitialised object. Furthermore, having all these asserts lead to duplication.

This seems more like a pre C++-system (like C, where you don't have constructors or "const"), than a post-C++ one...

Also, "const", used for member functions, is an either-or thing: Either the function is const or it's not (or you can't use the constness of the object it's invoked on, to check with), and as such, a const declaration (however it is done) arguably more belong in the function declaration, rather than in the function body.

In short, it seems to me more like "simulating" const (for languages that doesn't have it), than improving on it...

>I have this nagging feeling that I am just reinventing OCaml

Or C++, perhaps. :)

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Mutable Types Posted: Feb 3, 2006 6:42 AM
Reply to this message Reply
> > The problem is that hard-wiring things like const, or
> > non-null pointers, or regions (ala Cyclone), introduce
> > significant complexity into a language design. These
> Hm, do you mean to say that this:

<snip>

> is more elegant than:

<snip>

No. I said the language design is simpler. The lanugage specification however would be considerably simplified.

The syntax proposed here is more intended to be demonstrative of the underlying processes. I am looking at ways to improve on it. One possibility is that "def" is actually a template class, so perhaps we would write instead:


public
{
def<Initialization> Init() {
}
def Fu() {
}
def<Const> Bar() {
}
}


The assertions could then be hidden in the constructors of the various specializations of the def template.

> To me, having a lot of asserts at the beginning of a
> function, rather than using language abstractions like
> constructors and "const" as part of the type system, is
> more inelegant.

But what if you want two stage constructors, or to distinguish between logical and physical constness? What if you want to label non-constness, rather than constness. Or what if you want new categories of functions, such as "published", which might mean that it is made available externally using some kind of RMI mechanism. There are other abstractions one can imagine, above and beyond initialization and const. If you simply solve each problem one by one, you are no closer to the goal of a language which can adapt easily to new paradigms.

> In your version, if someone forgets to use
> "assert(is_initialised(this))" at the start of a function,
> they risk operating on uninitialised data, invoking
> possibly undefined behaviour. By initialising the object
> in the constructor, you don't run the risk of using an
> uninitialised object.

The problem with the constructor approach, is the issue that some objects have trivial constructors, and some objects don't. Detecting this is hard, and makes it hard to write truly generic algorithms. Too often I see C++ classes which are optimized for POD's etc.

> Furthermore, having all these
> asserts lead to duplication.

It's just long-hand. There are more convenient syntaxes one could imagine.

> This seems more like a pre C++-system (like C, where you
> don't have constructors or "const"), than a post-C++
> one...

Sure, I'll buy that. Improvement on C++, doesn't neccessarily entail moving forward in the same directions. But I do like constructors, and Heron does have them, I simply want every object to have a default constructor.

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Mutable Types Posted: Feb 3, 2006 6:50 AM
Reply to this message Reply
> I would argue that making const pat of the language makes
> it easier for developers using that language. Maybe it
> complicates the language design but it simplifies use. I
> guess you have to ask yourself if you are designing the
> language for the users of the language or the designers of
> the language.

This is not neccessarily a decision one has to make. I think one can have both.

> Have you looked into self-types in Scala? This seems
> vaugely similar.

I don't think they will allow what it is I want to do. They can only be specified once. For those interested see: http://scala.epfl.ch/intro/selfrefs.html

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Mutable Types Posted: Feb 3, 2006 7:46 AM
Reply to this message Reply
There are two possibile directions for the line of reasoning that I am pursuing. One is the more obvious run-time typing. Which is not my preferred choice, but it would make it much easier to implement Heron.

Another possibility, is the idea that every member function could redefine the "this" type.

Here is something that may or may not make sense, consider the intrepetation of the following code:


my_class a;
a.f();
a.g();
a.h();


If I decide finally that every function is in fact a member type then this could be translated to the following C++ code:


my_class a;
my_class::f()(&a);
my_class::g()(&a);
my_class::h()(&a);


The next change I could do is rewrite classes so that they take their own type as a template parameter.


my_class<my_class> a;
my_class<my_class>::f()(&a);
my_class<my_class>::g()(&a);
my_class<my_class>::h()(&a);


That is unexciting but important for the next step.

Every function class could then have a transition meta-function. This takes a type as a parameter, and returns a new type as output. This represents the transition between types.


my_class<my_class> a;
typedef my_class<my_class> T0;
T0::f()(&a);
typedef my_class<T0::f::transition<T0>::new_type> T1;
T1::g()(&a);
typedef my_class<T1::g::transition<T1>::new_type> T2;
T2::h()(&a);


This system of creating new temporary types in between every method call could emulate mutable types.

In terms of translation to C++, I fear that it might put a massive strain on the C++ compiler and not be practical for HeronFront.

Howard Lovatt

Posts: 321
Nickname: hlovatt
Registered: Mar, 2003

Re: Mutable Types Posted: Feb 3, 2006 8:16 AM
Reply to this message Reply
I like the idea of allowing the programmer to write their own language like features, e.g. const. I like this idea because it is what my own pet project:

http://pec.dev.java.net/nonav/frontpage.html

does :). In my project, Pattern Enforcing Compiler (PEC), I have written an Immutable type and a Value type (Mutable) that are alternatives to const. Note I didn't follow the const semantics of C++ or the final semantics of Java because that wasn't what I wanted, i.e. I find Immutable types more useful than const or final. I think many other people will be the same, they will want different semantics and it is nice to allow that choice rather than hard wire it into the language.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Mutable Types Posted: Feb 3, 2006 3:06 PM
Reply to this message Reply
> I like the idea of allowing the programmer to write their
> own language like features, e.g. const. I like this idea
> because it is what my own pet project:

It's loads of fun but I think pragmatically it makes no sense. You end up with everyone writing in their own language. It's like if I made up my own words and you made up your own words and try to read each other's posts.

Forbla irthy uuldpat,

-James Watson

Howard Lovatt

Posts: 321
Nickname: hlovatt
Registered: Mar, 2003

Re: Mutable Types Posted: Feb 3, 2006 5:20 PM
Reply to this message Reply
@James Watson

> It's loads of fun but I think pragmatically it makes no
> sense. You end up with everyone writing in their own
> language. It's like if I made up my own words and you
> made up your own words and try to read each other's
> posts.

Take a look at my pet project:

http://pec.dev.java.net/nonav/frontpage.html

I think I have tackled the important point you raise, EG in my system there is no new syntax. I think any Java programmer would understand what is going on, e.g.:
class ImmutableInteger implements Imutable {
  private final int value;
  ImmutableInteger( final int value ) { this.value = value; }
  ImmutableInteger plus( final ImmutableInteger rhs ) { new ImmutableInteger( value + rhs.value ); }
}

In this example Java is extended to have immutable types and yet I think that a Java programmer would understand the above code and if not they can take a look at the Javadoc for Immutable.

I would be interested in your thoughts, thanks for posting a comment.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Mutable Types Posted: Feb 6, 2006 5:57 AM
Reply to this message Reply
> Take a look at my pet project:
>
> http://pec.dev.java.net/nonav/frontpage.html
>
> I think I have tackled the important point you raise, EG
> in my system there is no new syntax.

I've looked at it briefly in the past. It seems like a pretty good approach for what you are trying to do. I am not sure if it solves a problem that really matters to me. Maybe I'll look at it again later.

Flat View: This topic has 10 replies on 1 page
Topic: Is your Sybase Java application running out of memory? Previous Topic   Next Topic Topic: If You're Not Going to Upgrade It, Don't Use It

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use