On May 10, 2014, at 8:54 PM, David Brown wrote: > On Sat, May 10, 2014 at 09:02:08PM +0200, Robbert van Dalen wrote: >> >> from what i’ve learned from the source code so far: >> >> variables are the most used mutable entities, and they point mostly to >> immutable stuff. >> the only weird case is when variables point to other variables. >> >> i don’t believe there is such a thing as mutable ‘class’ fields, except when >> such fields are variables. >> >> .. i may be completely wrong here - but that’s because i’m a newbie. > > It's perfectly happy with: > > Class "class name" extends object > with mutable fields > first field : ...; > > I can then do > > item's first field := value; > > and update it. > > David
The class declaration specifies a mutable field, but that doesn't affect the
underlying Avail semantics; the generated code just puts together structures
provided by the VM in a different way. When a class declaration defines a
mutable field, the object type that it generates (in the zero-argument method
that's the name of the class) has a suitable variable type in its field type
map. The constructor generates code that accepts either the ":=" syntax or the
"::=" syntax for such a slot. In the former case, an initial value is
supplied; in the latter, the actual *variable* can be provided (otherwise a new
variable gets created). That's handy when you want two objects to share some
variable. Similarly, the getter for a mutable field traverses the embedded
variable and fetches its current contents. The class declaration also causes
generation of setters for every mutable field (like "_'s⁇first field:=_" in
your example).
Let's look at the class declaration message to see what else I may have
missed...
"«Public»?«Explicit|explicit»?\
\|Class|class_extends_\
\|«with
immutable⁇field|fields««public»?«reconstructible»?_:_‡,»»\
\|«with mutable
field|fields««public»?«shared»?«referable»?«read-only»?_:_‡,»»\
\|«with reconstructor|reconstructors««public»?(«_‡,»)‡,»»",
The public flags (separately for the class, individual fields, and individual
reconstructors) indicate that the appropriate generated names must have been
explicitly listed in the Names section of the module; otherwise it's a
compile-time error.
Explicit subclassing I covered in an earlier message. The "extends_" part
allows you to specify the type being specialized. If you want to extend
several types (called "multiple inheritance" in those other quaint languages),
just extend the intersection of some types like "...extends burger ∩ cheesy...".
The immutable keyword is optional, but allows you to be verbally explicit about
the fields that are not mutable.
The reconstructible keyword identifies which fields should be named in
one-field-at-a-time reconstructors (a new Avail term for a uniquely Avail
concept). For example, a three dimensional point might declare x, y, and z as
reconstructible fields. Then if p is some three dimensional point, we can say
"p2 ::= p's x ::= 0;", which projects p onto a new point p2 in the yz plane.
The first ::= is initializing the constant p2, and the second one is part of
the generated reconstructor message "_'s⁇x::=_". If we want to provide a
convenient way to project a point onto a line parallel to the z axis we would
use the reconstructor keyword (after all fields), and specify (x,y) as the list
of fields to be reconstructed together. That defines a method
"_'s⁇x::=_,y::=_" that produces a new object having the specified x and y
fields, plus any other fields that the given point already has. Note that this
works even if we later define a four-dimensional point class, since the w
coordinate would simply be carried forward into the new object. As you can
see, this is a much more powerful mechanism than traditional object oriented
concepts like constructors, or even abstract factories.
Back to the field definitions, the referable keyword (for a *mutable* field)
indicates that a "`↑_'s⁇x" will be generated, which allows one to get to the
actual variable embedded in the object. At least that's what it's called as of
a couple of days ago (Friday, 2014.05.09). Prior to that commit, the leading
back-tick was not present.
Specifying read-only indicates that the setter method should not be generated.
And finally, the shared flag for a mutable field indicates that reconstructors
should *not* copy that mutable field. If this is absent, then the variable in
a mutable field will be copied (having the same initial content) into the new
object.
It should be noted that all of these syntactic mechanisms are constructed in
Avail code, purely in terms of Avail's simple object model (field map, field
type map, instance-of semantics, subtype semantics), without any special
primitive support. Which means that if you don't like the higher-order
concepts that we've provided in the class declaration method, you can simply
create your own. Which we're pretty sure will happen in sufficiently
specialized domains and DSLs, just to avoid the tiny amount of boilerplate that
this syntax introduces, or possibly to restrict its power. The actual
underlying core mechanisms are parse-tree building, method generation from
parse trees, object type construction from a field type map, object
construction from a field map, field extraction/replacement, map manipulation,
built-in object and object type semantics, variables, semantic restrictions,
and of course modules, names, and modularity.
signature.asc
Description: Message signed with OpenPGP using GPGMail
