Tim Jansen's blog


2005/10/31
Property Constraints
I have written a lot about Eek's constraint system for methods, but I rarely even mentioned property constraints. Maybe that is because I was never really happy about the property constraint system. It looked really simple, but in reality it was full of quirks.
Until last week my plan was allow "with" expressions for each property, just like method constraints. The "with" expressions are validated after setting the property. They would be executed in the object's context, thus with "this" pointing to the object. This approach looks simple and powerful, but unfortunately it is full of traps. One of the traps is making it possible for properties to depend on each other. Let's look at the following class:
class ThreeNumbers
 int a
  with a < b, a < c
 int b
  with a < b, b < c
 int c
  with a < c, b < c

 setAll(int newA, int newB, int newC)
  a = newA
  b = newB
  c = newC
end
Each property has two constraints which specify that at any given time the values must be a < b < c. The method setAll() is supposed to assign new values to the properties. So what's wrong with this? Let's look the following code:
 ThreeNumbers o(1, 5, 10)
 o.setAll(6, 7, 10) // error!
This does not work: in the method setAll()'s first line the value "6" is assigned to "a", which will fail because it violates the constraint "a < b" ("6 < 5"). It turns out that making properties depend on each other is not that simple, because it becomes really hard to update them.
There are several solutions for the problem of interdependent properties. One approach is that the property constraints are only validated when the method finished. Unfortunately that would mean that the class's code needs to be capable of handling properties that violate their constraints for a limited amount of time, and then constraints wouldn't be very useful anymore.
A second solution, the one that I favoured in the last year, was to introduce a special syntax that allows setting several properties simultanously and delay the checking of the constraints. This put a dent into Eek's complexity budget, but at least made them usable.
Unfortunately it wasn't the only problem. The next one is that in order to allow constraints to access properties in a natural way, the value must be assigned to the property and then the constraint expression can be executed. This will, again, allow the property value to violate the constraint for a short time. Maybe there are three expressions, and only the last one fails. Then two expressions are executed on an instance that has an invalid state. And if a constraint fails, the old value needs to be restored.
Things get even worse with accessor methods: return values of getter methods can not easily be constraint-checked if the constraints need to read the value themselves. An infinite recursion would be the result. The work-arounds made things so much more complex that I decided against constaint validation for reading properties, again reducing the usefulness of constraints.

So yesterday I rewrote property constraints in the specification and solved these problems by declaring the 'this' pointer to point to the constructor object (in Eek the constructor object is a singleton that contains the constructors and constants of a class). This will drastically reduce the functionality of constraints, because properties can not depend on each other anymore, but it also solves all the problems that I had until now. The constraint expression gets just a single argument, which has the name of the property, but the expression can not access any members of the object. Here's a example (which is kind of pointless, because it's hard to show what you can NOT do):
int age 
 with age >= 0
The property constraint is executed before the new value is assigned to the property (or the settor method id executed), as well as after reading the value (or invoking the gettor method). Thus it is always guaranteed that the property contains and returns a valid value (it is possible that you set a valid value to a property, and by the time you read it the property became invalid - this may happen when you use an external value in the constraint, such as a value that's provided by a singleton).
An alternative syntax that I originally considered was to call the new value in the constraint expression 'it', like the special variable that I use in anonymous closures. I am not sure whether that may be a good idea: it would makes it more obvious that you can not access the object's members, but it also feels more awkward. Anyway, I am quite happy with the new solution. Getting rid of 'this' makes property constraints so much simpler and less error prone. The new solution also allow an important optimization compared to the old one, because now constraints can be used as a guarantee for a restricted value range, but that may be the topic of a future blog entry..



Mix-ins
Several months ago I promised to write about Eek's mix-in implementation as soon as I have it in the specification. Well, I did finish the specification part, but was never in the right mood to blog about it. The reason for this is that Eek's mixins are actually quite boring. I just renamed interfaces to mixins and gave them the same syntax and capabilities that regular Eek classes have. Like Java interfaces they can still be used as reference types. This, and allowing mix-ins to have non-virtual properties, makes them quite different from many other mix-in (traits etc) implementations, but I think it's the simplest and most powerful way to implement them in a statically typed language. I thought about many other options, like making 'virtual' default for all mixin members (in classes the default is non-virtual) and so on, but eventually I came to the conclusion that consistency is more important than syntactic sugar.

So a Eek mixin could look like this (based on the Cedric Beust example, but with an extra method because Eek does not need accessors):
public mixin Namable
 String shortName
 String longName

 getBothNames(): String
  return "{shortName} ({longName})"
end
To import the mixin, the new "mix" keyword is used instead of "implements":
public class Employee mix Namable
end


And, finally, I did one small but important change to the member modifiers: a member can be "private" and "virtual" at the same time. This has almost same effect as "protected" in C++ and Java, with the difference that only those sub-classes that override the member can access it. I have never liked 'protected' in base classes, but for mixins it actually makes sense.



 

This blog is my dumping ground for thoughts and ideas about Eek. Someday Eek will be a programming language and system, somewhat comparable to Java in scope. It is my attempt to bring sanity to the world of computing.
At least I hope so. Right now it is far from being finished and I can't guarantee that it ever will be. I am still working on the specification, but I won't release anything before I got my first prototype running. The world does not need more vapourware and unusable beta-software. All publicly available information about Eek is contained in this blog. You can find the latest summary here.
This page is powered by Blogger. Isn't yours? Creative Commons License
This work is licensed under a Creative Commons License.