JanC <usenet_spam at janc.invalid> writes:
> Jacek Generowicz <jacek.generowicz at cern.ch> schreef:> > > * (defmethod foo ((x integer))> > > * (defmethod foo ((x string))> > > The ANSI standard for the _dynamically typed_ language shown above,> > Maybe someone can explain,
Sure ...
> but the above doesn't look like "dynamic typing" to me...?
In order to preserve us from a long thread full of irrelevancies,
maybe I should first ask you to tell me what _you_ mean by dynamic
typing.
However, I'll take the plunge ...
My definition of dynamic typing can be summarized as follows: "Objects
know their own type. Variables do not have a type."
So, let's try the following code
(defmethod foo (x)
(format t "~&~s has some type or other." x))
(defmethod foo ((x integer))
(format t "~&~s is an integer." x))
(defmethod foo ((x string))
(format t "~&~s is a string." x))
(loop for item in (list 1
"hmm"
(list 1 2)
(make-hash-table)
(vector))
do (foo item))
And we get the output:
1 is an integer.
"hmm" is a string.
(1 2) has some type or other.
#<EQL hash table, 0 entries {4819DEFD}> has some type or other.
#() has some type or other.
- Note that item (a variable) is undeclared; nowherere do you specify
it's type. (That doesn't mean that it's dynamically typed though -
see implicitly statically typed languages such as ML, for
counterexamples.)
- Note that item is bound to objects of completely different types
(integer, string, list, hash-table and array, in this case) at
different times. (This _does_ mean that it's dynamically typed.)
Perhaps you thought that it doesn't look like dynamic typing because
of superficial similarities with C++ method overloading:
void foo(std::string x) {
std::cout << x << " has type string." << std::endl;
}
void foo(int x) {
std::cout << x << " has type int." << std::endl;
}
The important difference is that C++ does this "dispatch" at _compile
time_, and in order to do it, you must tell the compiler, in the
source code, a priori, the type with which you will be calling the
function, by providing a type declaration of the variable which you
will be passing to the function.
For example:
int i; // I'm telling the compiler that i will always be an int
...
foo(i) // The compiler decides (at compile-time) which version of foo
// will be called (at run-time), on the basis of the type
// I gave above.
i = "hello" // Error, I promised the compiler that i would always be
// an int and now I'm breaking my promise.
Contrast this to our mystery language:
(let ((i 2)) ; No type declaration
(foo i) ; Dispatch done at runtime
(setq i "hello") ; Variable rbound to object of different type
(foo i)) ; Another runtime dispatch, different method called
Does this help ?