Newsgroups: comp.lang.eiffel,comp.lang.ada,comp.lang.c++,comp.lang.smalltalk,comp.lang.objective-c,comp.lang.java,comp.object
Path: cantaloupe.srv.cs.cmu.edu!rochester!cornellcs!newsstand.cit.cornell.edu!news.acsu.buffalo.edu!news.uoregon.edu!leto!hammer.uoregon.edu!arclight.uoregon.edu!feed1.news.erols.com!howland.erols.net!newsxfer3.itd.umich.edu!chi-news.cic.net!ftpbox!mothost.mot.com!schbbs!news
From: shang@corp.mot.com (David L. Shang)
Subject: Re: Combining dynamic and static typing
Reply-To: shang@corp.mot.com
Organization: MOTOROLA 
Date: Wed, 29 Jan 1997 16:53:58 GMT
Message-ID: <1997Jan29.165358.16783@schbbs.mot.com>
References: <5cloqm$9kn@csugrad.cs.vt.edu>
Sender: news@schbbs.mot.com (SCHBBS News Account)
Nntp-Posting-Host: 129.188.128.126
Lines: 158
Xref: glinda.oz.cs.cmu.edu comp.lang.eiffel:17952 comp.lang.ada:56797 comp.lang.c++:244187 comp.lang.smalltalk:50377 comp.lang.objective-c:6313 comp.object:60549

In article <5cloqm$9kn@csugrad.cs.vt.edu> nurban@csugrad.cs.vt.edu (Nathan M.  
Urban) writes:
> In article <1997Jan28.160420.28915@schbbs.mot.com>, shang@corp.mot.com wrote:
> 
> > The advantage of static type checking is type error prevention:
> > to prevent type errors before it can happen.
> 
> > Therefore, Objective-C cannot give the benefit of a static typing
> > system. Objective-C detects the type errors such as "Not a String"
> > at run-time. It does detection, not prevention! Detection is usually
> > not a solution to a problem. It is like an irresponsible doctor saying:
> > "Now I find what is wrong with you, it's your responsibility to figure
> > how to fix it. Want my suggetion? -- peace die -- crash!"
> 
> Compile-time detection _is_ prevention.  If you get build errors all
> over the place, you fix them.  Now, there are circumstances under which
> you need to generate method dispatches at runtime -- which C++ cannot
> do -- that can't be detected at compile-time.  Objective-C gives you
> the power to do that, and if you send a bad message, you can trap the
> exception and do something with it.  You can even check to see if an
> object responds to a message before you send it, if you don't want to
> trap it.  This is a better solution than not being able to have that
> power at all.  Programs don't have to crash on a runtime exception.
> 
> If you want total safety without the possibility of generating a
> runtime exception, then if you don't need dynamic message generation in
> your program, it is trivial to write code that does not generate method
> dispatches at runtime, just like C++; if you don't need the extra power
> of Objective-C, then you don't have to write your code to use it.
>

There are some confusions about run-time type check or dynamic
dispatch with static type safety. They are not contradictory.
When a language uses run-time type check or allows dynamic
dispatch,  the language does not necessariy have to report type
errors at run-time.

A language should use run-time type check for type-error prevention.
But unfortunately, most dynamic languages use run-time type check
for error detection only. Objective-C is among them.

"type error" is a kind of soft definition to human beings.
When a type check fails, is that a type error? some people
would say yes, some people would say no. Consider a example.
Suppose we select oranges from a heterogeneous fruit bag:
take out a fruit, check whetehr it is an orange, if it is,
accept it. If it is not, throw it away. When the orange-
type check fails, is it a type error? No! It is an expected
situation. Consider another example. Imagine we want to put
an orange into a fruit box that accept orange. Now we got
a box with a lable telling us that it is a fruit box. Since
an orange is a fruit, of cause we can put the orange in.
But it happens to be a box accept apples only. Is this
a type error? Yes! It is an unexpected event.

Fortunately, we have a formal definition for what is a
type error. A type error is such an incorrect binding of
an object to a name that the type of the object does not
conform to the declared type of the name.

With this definition, let's review the above two examples:

1. Selecting Orange (in Transframe):

	fruit_bag: 	bag of Fruit;
	orange_bag:     bag of Orange;
	foreach (fruit in fruit_bag)
	{
	   inspect (typeof(fruit))
	   {
		case Orange: orange_bag.put(fruit);
		default: // do nothing
	   }
	}

The above code uses run-time type check, but should not raise
a run-time type error. 

2. Put Orange (in Java):

	Fruit[] fruit_box;
	Orange  orange;
	if (some_condition) fruit_box = new Apple[100]; ...
	fruit_box[0] = orange;

The above code will raise a run-time type error. The problem is
that "Apple[100]" is not a subtype of "Fruit[]":

   Fruit[]: an array whose elements can be any kinds of fruits
   Apple[]: an array whose elements can be apples only

Think for a while. You'll find even by your intuitive logic, Apple[]
should not be a subtype of Fruit[]! (Perhaps Java designers have
a uncommon logic than our ordinary people).

If I ask my 7-year old daugther to bring me a box that can hold any
kinds of fruit, she would certainly not bring me the box that can
hold apples only!

In Transframe, the code

	fruit_box: Fruit[] ;
	Orange  orange;
	if (some_condition) fruit_box := Apple[100](); ...
	fruit_box[0] := orange;

cannot get compiled, because the binding:

	fruit_box := Apple[100]();

is invalid. It is definitely (even my 7-year old daugther can judge)
a wrong binding.

So where can we get the array polymorphism? Transframe allows
correct array polymorphism only. Consider the following (in
Transframe):

	fruit_box: array #(ElementType: type of Fruit);
	orange: Orange;
	apple:  Apple;
	new_kind_of_fruit: Fruit;

	if (some_condition2) fruit_box := Apple[100] ();
	else if (some_condition2)  fruit_box := Orange[100] ();
	else fruit_box := Fruit[100] ();

	inspect (typeof(fruit_box).ElementType)
	{
		case Orange:
			fruit_box[0]:= orange;
		case Apple:
			fruit_box[0]:= apple;
		case Fruit:
			fruit_box[0]:= new_kind_of_fruit;
			fruit_box[1]:= orange;
			fruit_box[2]:= apple;
	}
	
The above code is correct. "fruit_box" is a polymorphic array
variable. It can represent a fruit_box that contains oranges
only, or a fruit_box that contains apples only, or a fruit_box
that contains any kinds of apples.

When you put an orange into the fruit box, you have to check
whether the fruit box accept an orange or not! It is the basic
requirement!

If you have a 7-year old kid, make a test. Tell him or her that
there are some fruit boxes, some may contain apples only, some
may contain orange only. And ask him or her to put an orange
into on of the fruit boxes. See whether she or he check the
contents of the box before puting the orange in.

David Shang




