Strong/static typing in Java and C/C++

D

Digital Puer

I'm a bit confused by the terms {strong vs. weak} typing and
{static vs. dynamic} typing. Are they orthogonal terms? ie.
are there 4 combinations of these types of typing?

From my understanding, static typing means that a variable's type
is always known at compile-time and that the compiler checks for
improper operations on a type at compile-time.

Also, AFAICT, strong typing means that improper operations on a type
are not allowed to happen. Does strong typing occur at compile time
or runtime? If a language is statically typed, thereby preventing
illegal type operations at compile time, would you even need
strong typing at runtime?

I've read that C and C++ are statically typed but not strongly
typed. I've also read that Java is statically and strongly typed.
Is this correct?

Suppose I have a simple program:
int i;
double j;
int result;

i = 2;
j = 3.0;

result = i+j;


This will compile in C/C++ (albeit with a warning). This will not
even compile in Java. What does this show about each language's
type-ness? Thank you for any help.
 
J

James Rogers

(e-mail address removed) (Digital Puer) wrote in
I'm a bit confused by the terms {strong vs. weak} typing and
{static vs. dynamic} typing. Are they orthogonal terms? ie.
are there 4 combinations of these types of typing?
Yes.


From my understanding, static typing means that a variable's type
is always known at compile-time and that the compiler checks for
improper operations on a type at compile-time.

Static typing means that the type is fixed when the variable is
declared. It does not specifically imply any set of correctness
tests.

Dynamic typing means a variable has no fixed type. In fact, the
variable may have no explicit declaration expression. It may
contain any type.
Also, AFAICT, strong typing means that improper operations on a type
are not allowed to happen. Does strong typing occur at compile time
or runtime? If a language is statically typed, thereby preventing
illegal type operations at compile time, would you even need
strong typing at runtime?

Strong typing does mean a separation of operations on types.
Strong statically typed languages can perform some checks at
compile time. Some checks can be performed at run time.
Strong dynamically typed languages are only checked at run time.
I've read that C and C++ are statically typed but not strongly
typed. I've also read that Java is statically and strongly typed.
Is this correct?

Strong typing is not a binary state. There are degrees of strong
typing. C has some elements of strong typing. C++ has more elements
of strong typing (mostly related to the use of classes). Java
claims to be strongly typed, but is not much different from C++.

One of the most strongly typed languages is Ada.
Suppose I have a simple program:
int i;
double j;
int result;

i = 2;
j = 3.0;

result = i+j;


This will compile in C/C++ (albeit with a warning). This will not
even compile in Java. What does this show about each language's
type-ness? Thank you for any help.

The warning in C and C++ indicates that you are attempting something
that is not correct. Java compilers provide a stronger error message.
Both languages retain some of the weak typing features of C relating
to implicit conversions between numeric types. As an example I will
slightly modify your code above. The following example will compile
without warning or error in C, C++, and Java:

int i;
float j;
double result;

i = 2;
j = 3.0;

result = i + j;

All three languages allow you to mix two different types to create
a value of a third type. By comparison, such mixing cannot be done
implicitly using Ada.

i : integer;
j : float;
result : long_float;

i := 2;
j := 3.0;

result := i + j; <- Compiler will issue error message here

The GNAT Ada compiler complains that the operator "+" has improper
operands.

If the example is changed to:

i : float;
j : float;
result : long_float;

i := 2.0;
j := 3.0;

result := i+j;

The same GNAT Ada compiler complains that the right hand side
of the argument expected type long_float but found type float.

Jim Rogers
 
C

Christopher Barber

James Rogers said:
Static typing means that the type is fixed when the variable is
declared.

Not quite. It means that declarations have a static type, known at compile
time. The variable's exact type does not need to be identical to the static
type at runtime, but it must be a subtype.
Dynamic typing means a variable has no fixed type. In fact, the
variable may have no explicit declaration expression. It may
contain any type.

This is only true for languages which do not mix dynamic and static typing.
 
P

Peter Ammon

Digital said:
I'm a bit confused by the terms {strong vs. weak} typing and
{static vs. dynamic} typing. Are they orthogonal terms? ie.
are there 4 combinations of these types of typing?

Yes. Note that I seem to have a different understanding than some other
posters.
From my understanding, static typing means that a variable's type
is always known at compile-time
Yes.

and that the compiler checks for
improper operations on a type at compile-time.

No. There's yet another distinction: a language can be type safe or
type unsafe (or somewhere in between). In a type safe language, type
errors (performing an operation that the object does not support) are
impossible. They may be blocked at compile time, which is typical but
not required of statically typed languages, or they may be blocked at
runtime. Java uses a mixed approach, while C and C++ have no runtime
checking. As a result, Java is type safe while C and C++ are not.
Also, AFAICT, strong typing means that improper operations on a type
are not allowed to happen.

No, that is type safe. Strong typing means that every expression has a
well defined type.
Does strong typing occur at compile time
or runtime?

Yes. (It can be either.)
If a language is statically typed, thereby preventing
illegal type operations at compile time,

Thus you mean statically typed *and* typesafe.
would you even need
strong typing at runtime?

No (except possibly for debugging purposes), and this is a strong
advantage of statically typed languages. However, there are reasons to
want to avoid statically typed languages; see below.
I've read that C and C++ are statically typed but not strongly
typed.

This is wrong. C and C++ are strongly typed because every expression
has a well defined type (or has type void, which is technically an
incomplete type and so counts). They are statically typed because the
types are known at compile time, which is why sizeof can do what it does.

C++ has some (weak) dynamic typing features, in addition.
I've also read that Java is statically and strongly typed.
Is this correct?

Yes, for the same reason. It also has dynamic typing features.
Suppose I have a simple program:
int i;
double j;
int result;

i = 2;
j = 3.0;

result = i+j;


This will compile in C/C++ (albeit with a warning). This will not
even compile in Java. What does this show about each language's
type-ness?

This demonstrates two things.

In Java the binary + operator is very heavily overloaded. It can accept
the following pairs of types.

int, int
long, long
float, float
double, double

But that's just for arithmetic. When you add in the String type, things
get much uglier. In C, it's even worse; the rules are very complicated
and I won't try to give them all here. (C++ is a downright Gordian knot
in this regard.) Overloading of operators is not strictly related to
type checking or type safety, but languages that place a large emphasis
on static type safety prefer to not overload operators (e.g. Ada or ML).

It also shows that, in both languages, there is the possibility for
implicit type conversions. In C, C++, and Java, integral types can be
implicitly converted to either float or double, and that is what is
happening here: the value of i is promoted to double, and then the
double, double form of the + operator is invoked.

In Java, however, there is no implicit type conversion from double to
int, and that is why it fails to compile. C and C++ do allow implicit
type conversions (that is, without a typecast) from double to int, which
is why the code compiles.

Implicit type conversions weaken the strong-typing aspect of a language:
the more implicit type conversions, the weaker the typing. They do not
affect type safety. So in this regard, Java is more strongly typed than
C or C++.
Thank you for any help.

To be very sure:

In a statically typed language, the types are known at compile time.
In a dynamically typed language, the types are discovered at runtime.

In a strongly typed language, every expression has a well defined type.
In a weakly typed language, the types of expressions are undefined, or
malleable, or determined by context, etc..
Languages can also be totally untyped. Assembly is an example.

In a type safe language, operations that a type does not support are
impossible.
In a type unsafe language, operations that a type does not support are
possible.

A few examples:

SML is strongly typed, statically typed, and type safe.
C is strongly typed, statically typed, and type unsafe.

Smalltalk is strongly typed, dynamically typed, and type safe.
____ is strongly typed, dynamically typed, and type unsafe. (I can't
think of an example, since dynamically typed languages are typically
type safe).

Perl is weakly typed, dynamically typed, and type safe.
Assembly is untyped and type unsafe.

And a few weirdos:

Objective-C is weakly typed (expressions can have a well defined compile
time type, but this type is permitted to be wrong!), has *optional*
static typing, and is typesafe.
Dylan has *optional* strong typing, *optional* static typing, and is
type safe.

As an interesting factoid, type checking is related to the Halting
Problem, and it's known that no static type checker can determine
exactly which programs will produce a type error: they will either
reject some correct ones or admit some illegal ones. Dynamic type
checking does not have that problem.

I'm sure it's much clearer now. ;)

-Peter
 
P

Peter Ammon

Peter said:
Objective-C is weakly typed (expressions can have a well defined compile
time type, but this type is permitted to be wrong!), has *optional*
static typing, and is typesafe.
Dylan has *optional* strong typing, *optional* static typing, and is
type safe.

Sorry, I got entangled in my own definitions. Both Objective-C and
Dylan should be considered strongly typed, as every expression has a
well defined type and there are not type conversions; whether the type
is known at compile time or runtime is orthogonal.

-Peter
 
D

Digital Puer

Thank you for writing such a detailed write-up. I'll have to read
it a few more times to digest all of it, though. :)

Have you considered putting this in a FAQ or webpage on this subject?
I'm sure others will find it helpful.
 
G

Gary Labowitz

Peter Ammon said:
Digital Puer wrote:
It also shows that, in both languages, there is the possibility for
implicit type conversions. In C, C++, and Java, integral types can be
implicitly converted to either float or double, and that is what is ^^^^^^^
happening here: the value of i is promoted to double, and then the ^^^^^^^
double, double form of the + operator is invoked.

Here I have a "quibble" question (say five times fast).
You appear to use convert and promote interchangeably. Are they?
I have always taught conversion implies changing the internal coding
structure (as in double converts to int) and promotion implies extending the
range of values available (as in int promotes to long). Promotion is the
opposite of truncation with this idea. There is no opposite of conversion.
What say you?
 
R

Roedy Green

You appear to use convert and promote interchangeably. Are they?
I have always taught conversion implies changing the internal coding
structure (as in double converts to int) and promotion implies extending the
range of values available (as in int promotes to long). Promotion is the
opposite of truncation with this idea. There is no opposite of conversion.

Conversion requires something explicit to make it happen, where
promotion is implicit.
 
P

Peter Ammon

Gary said:
Here I have a "quibble" question (say five times fast).
You appear to use convert and promote interchangeably. Are they?

A conversion is any change from one type to another, and a promotion is
a particular sort of conversion among primitive types. It happens with
some binary operators so that they can operate on two of the same type,
which keeps the language simpler. It also occurs with some unary
operators, I suspect because that's how processors work.
I have always taught conversion implies changing the internal coding
structure (as in double converts to int)

Well, a cast from String to Object is a conversion, but no internal
structures need be changed; in fact, nothing needs to be done at runtime
at all.
and promotion implies extending the
range of values available (as in int promotes to long).

This is my understanding too. But note that a promotion can also change
the internal structure. For example, with 3.5 == 5, the value 5, an
int, is promoted to the type of 3.5, which is a double. Converting an
int to double requires bit fiddling and internal structure changing.
Promotion is the
opposite of truncation with this idea. There is no opposite of conversion.
What say you?

Agreed!

-Peter
 
P

Peter Ammon

Roedy said:
Conversion requires something explicit to make it happen, where
promotion is implicit.

No, I don't think that's quite right. For example, in

"My age is " + 139;

The particular conversion is from the int 139 to the String "139", which
is classed under string conversion (not a promotion). But in

125.7 + 139;

we have a conversion from the int 139 to the double of the same value,
and that is classed under numeric promotion. I would argue that both
examples are equally explicit, but promotion only occurs in the second.

-Peter
 
R

Roedy Green

Let me try again.

Promotions are implicit. They imply a widening. The new bucket to hold
the value has greater capacity.

So you can have promotions from byte -> short -> int -> long
also byte -> short -> int -> float -> double.

And also char fits in there too.

Then there are explicit casts which are often truncating conversions.
e.g. (int)aLong;
long -> int.

There are also casts which don't do any conversion calculation, just
let you look at an object in a brighter light e.g. (Dalmatian) fido;

Then there are explicit conversions like Integer.toString( int )

Then there are implicit conversions like the magic power concatenation
operator has to turn both objects and primitives into Strings.

Conversions and casts are a STINKING MESS in Java, rivaled in
bizarreness by French verbs. They need to be regularised. I fulminate
in http://mindprod.com/jgloss/gotchas.html#CONVERSION

I suspect they have been left the way they are for the same reason the
art of venery was practiced by knights and pages of old, as a sort
game of one upmanship to haze the newbies.

What is venery? see http://rinkworks.com/words/collective.shtml
http://www.hintsandthings.co.uk/kennel/collectives.htm
 
G

Gary Labowitz

Peter Ammon said:
A conversion is any change from one type to another, and a promotion is
a particular sort of conversion among primitive types. It happens with
some binary operators so that they can operate on two of the same type,
which keeps the language simpler. It also occurs with some unary
operators, I suspect because that's how processors work.


Well, a cast from String to Object is a conversion, but no internal
structures need be changed; in fact, nothing needs to be done at runtime
at all.

Here I would say that the String is cast to Object. No conversion. No
promotion. Just a cast.
A cast, to be clear, I describe as a way to tell the compiler that for this
particular statement's use, treat the class of the object as if it were of
the class of the cast. Agreed that nothing changes -- so I don't call it a
conversion. Actually, the notion of "converting" an object has been a source
of confusion for a lot of my students so I don't like to use the word with
casting of class types. I would say, "At this point, and for this one use,
the compiler will treat the reference variable as if it were of the class of
the cast. This limits it to the members of the cast class."
OTOH, casting a primitive type from (say) an int to a double actually
creates a temporary double of the value of the int and so it IS a
conversion. But again, only for the purposes of the compilation of that one
statement's use.
This is my understanding too. But note that a promotion can also change
the internal structure. For example, with 3.5 == 5, the value 5, an
int, is promoted to the type of 3.5, which is a double. Converting an
int to double requires bit fiddling and internal structure changing.

Your usage here follows your definition of promotions being a subset of
conversion. I hadn't thought of it that way and will have to consider this
for a while.
In any event, in response to Roedy's comment in this thread I would say
Implicit or explicit changes of type
byte to short to int to long = promotions
char to int ... = promotion
integer values (any of the above) to float to double = conversions
Explicit changes of type
casting inexact values back to exact types = conversion
casting exact types to smaller exact types = demotions
casting double to float = I DON'T KNOW; it's not simply a truncation and
it's not a complete conversion. Hmmmm.....maybe just demotion.

Do you see the flavor of my point here? Does this make sense? How would you
change it to be rigorous, understandable, and correct?
Thanks,
 
P

Programmer Dude

Gary said:
...casting a primitive type from (say) an int to a double actually
creates a temporary double of the value of the int and so it IS a
conversion. But again, only for the purposes of the compilation of
that one statement's use.

In C++ a cast can actually result in a new object (albeit, as you
say, for the single statement (and anything that takes and keeps
the value of that statement).

class SomeObject {
public:
operator unsigned long () const
{
unsigned long val = Obtain_ULONG_Version_Of_Self();
return val;
}
operator SomeOtherObject () const
{
SomeOtherObject obj = Obtain_SOO_Version_Of_Self();
return SomeOtherObject;
}
};


void Test_The_Above_Class ()
{
SomeObject my_object;

unsigned long n = (unsigned long) my_object;

SomeOtherObject o = (SomeOtherObject) my_object;
}


Spooky, eh? (-:
 
P

Peter Ammon

Gary said:
Here I would say that the String is cast to Object. No conversion. No
promotion. Just a cast.
A cast, to be clear, I describe as a way to tell the compiler that for this
particular statement's use, treat the class of the object as if it were of
the class of the cast.
Agreed that nothing changes -- so I don't call it a
conversion. Actually, the notion of "converting" an object has been a source
of confusion for a lot of my students so I don't like to use the word with
casting of class types. I would say, "At this point, and for this one use,
the compiler will treat the reference variable as if it were of the class of
the cast. This limits it to the members of the cast class."
OTOH, casting a primitive type from (say) an int to a double actually
creates a temporary double of the value of the int and so it IS a
conversion. But again, only for the purposes of the compilation of that one
statement's use.

I see how this could be a source of confusion! When you write
(double)someInt, you are actually making a new value of type double, but
when you write (Object)someString, you are not making any new value.
Same with parameter passing, I suppose.
Your usage here follows your definition of promotions being a subset of
conversion. I hadn't thought of it that way and will have to consider this
for a while.

I think this is how the Java language spec treats them. In case you
haven't already found it, the page is here:
In any event, in response to Roedy's comment in this thread I would say
Implicit or explicit changes of type
byte to short to int to long = promotions
char to int ... = promotion
integer values (any of the above) to float to double = conversions
Explicit changes of type
casting inexact values back to exact types = conversion
casting exact types to smaller exact types = demotions
casting double to float = I DON'T KNOW; it's not simply a truncation and
it's not a complete conversion. Hmmmm.....maybe just demotion.

Do you see the flavor of my point here? Does this make sense? How would you
change it to be rigorous, understandable, and correct?
Thanks,

Yes, I think I see what you are trying to say. I don't have any
experience teaching this material, so my advice might be poor, but
here's what I think. I might say that a conversion is like a function
(method?) that accepts a value of one type and returns as close as it
can to the same value, but with a different type; treating it as a
function might help with the idea that the value or type inside the
variable does not change, but the value and type "returned" may be
different.

You classify changes as "promotions" or "demotions." It looks like the
Java language spec's notion of a widening conversion is roughly what you
call a promotion, and a narrowing conversion is a demotion. You can
apply the same idea to reference types: treating a String as an Object
is a promotion, since an Object reference can refer to more objects than
a String reference, whereas treating an Object reference as a String
would be a demotion.

You might say that promotions are automatic, in the sense that they do
not require a cast, and demotions always require a cast.

Incidentally, my instructor when I was in school never used the term
"conversion." Rather he called them "implicit casts" or "explicit
casts." I was a bit put out when I discovered that there's no such
thing as an "implicit cast," but the notion of the compiler inserting a
cast for you might help.

-Peter
 
M

Michiel Konstapel

Digital Puer said:
Thank you for writing such a detailed write-up. I'll have to read
it a few more times to digest all of it, though. :)

Have you considered putting this in a FAQ or webpage on this subject?
I'm sure others will find it helpful.

Indeed, would you (Peter) consider adding it as an entry in the Jinx
wiki (http://jinx.swiki.net)?
Michiel
 
G

Gerry Quinn

No. There's yet another distinction: a language can be type safe or
type unsafe (or somewhere in between). In a type safe language, type
errors (performing an operation that the object does not support) are
impossible. They may be blocked at compile time, which is typical but
not required of statically typed languages, or they may be blocked at
runtime. Java uses a mixed approach, while C and C++ have no runtime
checking. As a result, Java is type safe while C and C++ are not.

And Java crashes due to passing the wrong type aren't really crashes -
they just look that way to your customer.

A major benefit of testing at compile time is that compile time occurs
on your system whereas runtime usually occurs on somebody else's.

Gerry Quinn
 
C

Chris Smith

Christopher said:
Not quite. It means that declarations have a static type, known at compile
time. The variable's exact type does not need to be identical to the static
type at runtime, but it must be a subtype.

I much prefer James' terminology, and I think it's far more commonly
used. You seem to be mixing the concept of a variable's type with some
kind of "the type of the value" concept. I'd rather the word "type" not
be used in imprecise ways like that... for example, in the case of
object references in Java (where I assume you're getting this from), the
common terminology would be to talk about the class of the object. The
variable (a reference) still has a type that doesn't change.

I suppose it would be possible to invent a statically typed language
where James' statement is strictly false, by allowing explicit changing
of a variable's type at different scopes; but that sounds really
confusing.
This is only true for languages which do not mix dynamic and static typing.

Well, it's true so far as they are dynamically typed, anyway. How did
you envision this mix occurring? There are a few languages that are
mostly statically typed but allow special declarations of untyped
variables. In that case, James' statement is true for untyped
variables, but not for typed ones. Did you have a different mix in
mind?

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
C

Christopher Barber

Chris Smith said:
I much prefer James' terminology, and I think it's far more commonly
used. You seem to be mixing the concept of a variable's type with some
kind of "the type of the value" concept. I'd rather the word "type" not
be used in imprecise ways like that... for example, in the case of
object references in Java (where I assume you're getting this from), the
common terminology would be to talk about the class of the object.

Right, but that is because Java does not support subtypes other than
subclasses. In languages with more general type systems, such as Curl, you
cannot get away with using the terms "type" and "class" to distinguish between
runtime and static types. I suppose you can say the "variable type" is the
static type and the "value type" is the dynamic type, and I think that is
something like what you are suggesting, but I think it is clearer to speak of
the "static" or "compile-time" type vs. the "runtime" or "dynamic" type and
thus avoid having to distinguish the difference between a variable and a
value.
I suppose it would be possible to invent a statically typed language
where James' statement is strictly false, by allowing explicit changing
of a variable's type at different scopes; but that sounds really
confusing.

It doesn't have to be all that confusing. For instance, in Curl, there is a
way to distinguish between a variable intended to be able to hold a null and
one that is not, and there is a 'if-non-null' syntax that essentially does
exactly what you suggest:

{define-proc public {foo str:#String}:void
{assert {compile-time-type-of str} == #String}
{if-non-null str then
{assert {compile-time-type-of str} == String}
}
}

As long as the inner scope uses a subtype of that used by the outer scope, I
don't think it is very confusing.
Well, it's true so far as they are dynamically typed, anyway. How did
you envision this mix occurring? There are a few languages that are
mostly statically typed but allow special declarations of untyped
variables. In that case, James' statement is true for untyped
variables, but not for typed ones. Did you have a different mix in
mind?

I think of dynamic typing as referring to the ability to make decisions based
on the runtime type of values. Thus, to my mind languages which support to
some degree the ability to determine the runtime type of a value are at least
somewhat dynamically typed. Languages with no support for static type
declarations, such as Python, are purely dynamically typed. Languages with no
support for runtime type information, such as C, are purely statically typed.
Languages in the C++ family, are somewhere in between.

The Curl language has an abstract type called 'any', which is the supertype of
all other types. Omitting a type declaration in Curl is equivalent to
explicitly declaring it to be of type 'any'. Such variables do have a fixed
static type of 'any', but may hold a value with any runtime type. So the
above definition would not work for Curl or other languages with a similar
type system.

- Christopher
 
J

James Rogers

Right, but that is because Java does not support subtypes other than
subclasses. In languages with more general type systems, such as
Curl, you cannot get away with using the terms "type" and "class" to
distinguish between runtime and static types. I suppose you can say
the "variable type" is the static type and the "value type" is the
dynamic type, and I think that is something like what you are
suggesting, but I think it is clearer to speak of the "static" or
"compile-time" type vs. the "runtime" or "dynamic" type and thus avoid
having to distinguish the difference between a variable and a value.

The concept of a variable type being different than the type of its
current value is not a feature of static typing. Curl appears to allow
you to define where a variable is defined within a type hierarchy. It
then allows you to assign to that variable any value that meets an
is-a relationship to the variable.

Ada, a very strongly typed language, does have the concept of subtypes.
It also makes a strong distinction between subtypes and types. There is
no single type hierarchy in Ada. If you define your own numeric type
it is not a member of a type hierarchy with any other type. On the
other hand, you can define subtypes of numeric types. The primary
use of this capability is to define a restricted value range for the
subtype. The subtype does maintain an is-a relationship with its parent
type.

Example:

type Days is (Monday, Tuesday, Wednesday, Thursday, Friday,
Saturday, Sunday);

subtype Weekend is Days range Saturday..Sunday;

Today : Days;

A Weekend value is also a valid Days value. Not all Days values are
valid Weekend values.

Ada does provide a proper membership test:

if (Today in Weekend) then
Put_Line("Go Fishing.");
else
Put_Line("Go to work.");
end if;

None of this is applicable to Java or C. Neither of those languages
provide the ability to define primitive types or subtypes.

It doesn't have to be all that confusing. For instance, in Curl,
there is a way to distinguish between a variable intended to be able
to hold a null and one that is not, and there is a 'if-non-null'
syntax that essentially does exactly what you suggest:

{define-proc public {foo str:#String}:void
{assert {compile-time-type-of str} == #String}
{if-non-null str then
{assert {compile-time-type-of str} == String}
}
}

The point here is quite clear. Curl variables are really pointers or
references to values. They do not specify a storage type, but rather
a reference to a hierarchy of storage types.

If this is static typing, then it is just barely static typing.
As long as the inner scope uses a subtype of that used by the outer
scope, I don't think it is very confusing.


I think of dynamic typing as referring to the ability to make
decisions based on the runtime type of values. Thus, to my mind
languages which support to some degree the ability to determine the
runtime type of a value are at least somewhat dynamically typed.
Languages with no support for static type declarations, such as
Python, are purely dynamically typed. Languages with no support for
runtime type information, such as C, are purely statically typed.
Languages in the C++ family, are somewhere in between.

Not all dynamically typed languages allow such a decision.
Perl is a wonderful example. A Perl scalar can hold any kind of value,
varying upon every assignment. There is no simple way to determine
what kind of value is held. Perl does not make such a distinction about
types.
The Curl language has an abstract type called 'any', which is the
supertype of all other types. Omitting a type declaration in Curl is
equivalent to explicitly declaring it to be of type 'any'. Such
variables do have a fixed static type of 'any', but may hold a value
with any runtime type. So the above definition would not work for
Curl or other languages with a similar type system.

The Curl 'any' type seems very close to the Java Object class.
The big difference seems to be that Object only applies to classes
while 'any' also includes what Java calls primitive types.

Jim Rogers
 
C

Christopher Barber

James Rogers said:
The concept of a variable type being different than the type of its
current value is not a feature of static typing.

Right, I would say that is a dynamic typing feature.
Curl appears to allow
you to define where a variable is defined within a type hierarchy. It
then allows you to assign to that variable any value that meets an
is-a relationship to the variable.

Yes, and this is true of C++ and Java as well.
The point here is quite clear. Curl variables are really pointers or
references to values. They do not specify a storage type, but rather
a reference to a hierarchy of storage types.

That is not the point at all. Static type declarations do specify a storage
type and not all Curl data types are reference types. In the above example,
the underlying representation of the variable doesn't change, but within the
non-null block of code, the compiler will assume that the underlying pointer
will not be null. Of course, another way to think about this is that the
if-non-null is just introducing a new variable with the same name, which hides
the outer variable, but it really makes no difference to the programmer.
If this is static typing, then it is just barely static typing.

I still think you are using a strange definition of static typing. Static
typing just means that variables have type information known at compile-time
which can be used to do compile-time type checking and allow the compiler to
perform a number of useful optimizations. Under this definition, clearly the
Curl programming language supports static typing. How does your definition
differ from this?
Not all dynamically typed languages allow such a decision.
Perl is a wonderful example. A Perl scalar can hold any kind of value,
varying upon every assignment. There is no simple way to determine
what kind of value is held. Perl does not make such a distinction about
types.

I suppose another example is Tcl, in which string is really the only type, but
there are functions that assume the string contains something that looks like
an integer, float, etc and the compiler can choose to use a more efficient
representation if it can figure out that the variable is just being used for
those types of operations. It is hard to characterize type systems like this,
but they are definitely dynamic.
The Curl 'any' type seems very close to the Java Object class.
The big difference seems to be that Object only applies to classes
while 'any' also includes what Java calls primitive types.

Curl also has an Object class that plays the same role as Java's. In addition
to allowing a variable to contain any reference, the 'any' type declaration
also causes the compiler to defer all method dispatches until runtime with no
compile-time checks. For example:

let foo:Foo = {Foo}
let any-foo:any = foo
let obj-foo:Object = foo

{foo.bar} || invokes bar method
{any-foo.bar} || as does this, using runtime dispatch
{obj-foo.bar} || compile-time error: Object has no bar method

This allows you to mix dynamic and static typing idioms in the same program.

- Christopher
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top