A property is used like a variable.


temp_fahrenheit ← 70;

The meaning of this single statement changes when some additional code is prepended.


<Real> temp_celsius;
temp_fahrenheit = temp_celsius * 9/5 + 32; //make an equality constraint

temp_fahrenheit ← 70; //assigns 190/9 to temp_celsius;


Angle := type {
	<Double> radians;
	degrees = radians / Math.pi * 180;

Angle right;
right.degrees ← 90;
rint(right.radians); //prints 1.5707963268

Each time a value is read from or written to a property additional processing occurs. Under-constrained properties are read only:


Rectangle := type {
	<Real> left;
	<Real> top;
	<Real> width;
	<Real> height;
	right = left + width; //read only property
	bottom = top + height; //read only property

The examples above represent the first class of properties, pure properties, which are modeled as relations. The second class, imperative properties, are built from get and set accessors, which resemble functions:


<String> saved_username := { 
	get := { return File.read_text("username.txt"); }, 
	set := { File.write_text("username.txt", value); }

Each time an imperative property is accessed (read from or written to) control passes to the get or set accessor functions (respectively) rather than accessing a memory location. Access is transparent to the calling program. Get and set accessors execute within their defining execution context. The space within the outermost curly braces { } also permits the definition of additional symbols, such as hidden value storage or helper functions which are not accessible from outside the property's scope. The presence of the get or set keywords in a statement scope causes that scope to be interpreted as a property.


<Double> clamped := {
	<Double> v;
	get := { return v; }
	set := { v ← value < 0 ? 0 : value > 1 ? 1 : value; }

† dependency injection (and other late binding) is limited when the target binary is stripped. This may be considered a security feature and/or a design flaw.

copyright © Brent Lewis 2017