Avail's different from most languages – as I'm sure you've noticed.  There is 
no fixed list of operations that are accessible everywhere in the code (by 
design, for DSLs), so technically there are no base methods that objects 
(values) respond to.  You're always free to import and define as many or as few 
methods as you want that accept an argument of type "any" (the highest usable 
type).

That said, there is a definition of "_=_" early in the graph of modules which 
provides, via a trivial primitive P_060_Equality, access to the notion of 
equality that Avail's VM already fully defines for all Avail values.  
Similarly, "_’s⁇type" provides access through primitive P_030_Type to Avail's 
type system, which is fully implemented by the VM.

Unlike meta-object protocols and their ilk which exist just to allow a 
programmer to make limited patches to a feeble, unusable type system, Avail 
instead provides a fully usable, complete type system.  This may seem contrary 
to the way object-oriented programming is normally organized... because it is.

Your remaining case, "_’s⁇hash", is slightly different.  While we could provide 
access to it in a matter of minutes through a primitive as trivial as 
P_060_Equality, we are currently choosing not to.  We have quite a bit of deep 
infrastructure in place to support pure mathematical notions of sets and maps, 
and we feel that exposing hash values directly may cause two problems:

(1) People might build their own hashed structures that provide no more actual 
power than sets and maps, and
(2) Exposing the hash values may lead to pathologically hashed sets and maps.  
Imagine manually building a bin-like structure in a misguided attempt to 
improve the performance of sets.  Such a structure would segregate values based 
on their hash values, potentially placing them into sets acting as bins of this 
construction.  Those sets would have hash values that were highly correlated, 
which can degrade performance.

Quick story:  We recently uncovered a bug that caused a lot of values to have 
the same hash value.  I don't recall what sort of values had this problem (it's 
described in the commit notes somewhere within the last month or two), but it 
led to a situation in which a Bagwell ideal hash tree was forced to have seven 
hashed levels (5 bits of hash at each level), and failed while attempting to 
use a linear bin at the bottom.  It was a simple off-by-one error in the set 
implementation that caused the failure, but we were lucky that it failed rather 
than simply degrading performance.  We fixed both the poor hash distribution 
problem and the off-by-one bug related to bin depth in the set implementation.  
I believe maps had the same problem, but I don't recall.

There's a third, minor issue as well: (3) exposing the hash value also exposes 
the fact that it fits in a 32-bit int.  If we expose that, then we'll have to 
break working user-written code if we change the number of bits to 64, or 
provide some horribly kludgey "_’s⁇NEW hash" method (heh, like "The New iPad" 
or "Scott Joplin's New Rag").  Worse, Avail may eventually be picked up for use 
"in the small", and some space-constrained implementations of Avail may 
ultimately choose to compute and store fewer hash bits, like 24 or even 16.  Or 
eliminate hashing entirely if there aren't going to be any large hashed 
structures.  They are just a VM optimization, after all.

The Avail VM already does a lot with hash values and equality semantics.  It 
coalesces equal objects.  It caches hash values within complex objects for 
performance without sacrificing good hash distribution.  These cached hash 
values are automatically invalidated or recomputed when a mutable 
representation of an object changes (it only has one reference, so it can't be 
the key of a set or map).  It (sometimes) compares cached hash values as an 
early check for equality to speed up unequal comparisons (equal comparisons are 
sped up by coalescence).  The specific hash functions we've implemented allow 
very rapid computation when manipulating tuples (replacing element(s), 
concatenating, extracting subranges), sets (adding/removing elements), etc.  
The cached hash values are sometimes updated during these "mathematical 
identity" shortcuts during quasi-destructive operations on mutable objects.  
But the most beautiful part of this design is that these things are completely 
hidden from the Avail programmer.  An Avail programmer gets zero-effort, 
reliable, efficient sets and maps – assuming we did our job right!

To answer your second point, however, you might want to include the subtype 
test "_⊆_" in your list.  This, like the others, uses a paper-thin primitive 
(P_033_IsSubtypeOf) to access Avail's built-in, complete rules about 
compatibility of types.  See implementors of o_IsInstanceOf() and its numerous 
helpers for the vast variety of ways in which types comparisons actually happen.

You might want to add some other basic operations to your list as well, like 
"<«_‡,»>" and "{«_‡,»}", since any value can be put in a tuple or set.  Also 
"“_”" (the inner quotes are smart double-quotes), the user-overridable 
stringification operation.  The VM gets told what to name this in the very 
first module, Origin.avail.  The default implementation for [any]→string simply 
asks the value's descriptor to produce something somewhat suitable, but the 
Avail method should be overridden for types of values that can be presented 
more appropriately in some other way.



On May 19, 2014, at 2:10 PM, Robbert van Dalen wrote:

> hi,
> 
> i wonder what’s the base set of methods that (any type of )object responds to:
> these are likely candidates:
> 
> _=_
> _’s⁇hash
> _’s⁇type
> 
> are there any more?
> 
> cheers,
> Robbert.

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to