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..


 

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.