namgk / ambienttalk

Automatically exported from code.google.com/p/ambienttalk
0 stars 0 forks source link

Soft Typing #18

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
Dynamic typing is cool because it allows for so-called ad hoc polymorphism 
(also known as 
“duck typing”), where any variable can contain any value, and code will 
work as long as an object 
can respond to all messages sent to it.

Unfortunately, dynamic typing detects errors very latently, which results in 
sometimes confusing 
selector not found exceptions.

Static typing the way C and Java introduce them is bad, it couples interface to 
specific 
implementation and inhibits reuse. Therefore, we propose to extend AmbientTalk 
with a 
structural typing mechanism, where a type only defines an interface. Any object 
that 
“implements” that interface can be bound to a variable of the abstract type.

Good examples in the literature are the type system of Emerald and that of 
Strongtalk. In 
StrongTalk, a protocol defines the interface to an object, so the type system 
is based on 
structure. It also has good support for parameteric types (generics). Also, it 
features the notion 
of a brand which allows for nominal typing where necessary.

One step further is the consideration of being able to annotate variables with 
guards, as in E. A 
guard is a boolean expression that should evaluate to true each time a value is 
bound to it. A 
false evaluation is a ‘type error’. This is called soft typechecking 
because type checks are still 
done very latently, but the advantage over regular typing is that you can use 
arbitrary runtime 
state to perform your “type check”.

Proposal is to be able to annotate formal parameters to 
methods/functions/blocks and defined 
variables with a guard:

def x : guardexpression := value
def m(par : guardexpression) : returnguardexpression { ... }
{ |a:guard : returnguard| body }

For variables, the guard is evaluated each time the variable is assigned. For 
formals, it is checked 
upon binding. The return guard is checked upon function return if the function 
returns normally. 
Idea is that the guard is simply an expression. If the expression evaluates to 
true, the guard 
passes and nothing happens. If the expression evaluates to false, the 
interpreter raises an 
exception. If the expression evaluates to an object, the object is sent a 
message to check 
conformance of the actual arg (e.g. .checkConformance(arg)). The idea is that 
different kinds of 
types can be implemented like this (i.e. type tags check conformance by 
checking whether arg is 
tagged with them, structural types check the object’s interface, etc.)

We might even use this feature to add metadata in the sense that the guard 
could be used to 
annotate its field.

Original issue reported on code.google.com by tvcut...@gmail.com on 16 Sep 2008 at 1:59

GoogleCodeExporter commented 8 years ago
Example guards:

Simple "type" guards like
def m(x : Number); // x must be an AmbientTalk number

Ranges:
def y := 10;
def m(x : Between(1,y)); // x must be between 1 and 10
def n(x : PositiveNumber);
// maybe we want 'anonymous guards', e.g. instead of having to define 
PositiveNumber we could define:
def n(x: Number.and: { _ > 0 });

Near/Far ref distinction (as in E):
def m(x : Near); // guarantees that using x.method is allowed

Original comment by tvcut...@gmail.com on 16 Sep 2008 at 2:03