Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

dynamic vs. static: the age-old debate

4 views
Skip to first unread message

Curtis W

unread,
Aug 14, 2006, 8:30:30 PM8/14/06
to
This basically sums up my thoughts on dynamic and static typing.
Discuss as you wish.

The topic of dynamic and static typing has been the hotbed of debate in
many programming language arguments. Many times a good amount of FUD is
thrown around, unfortunately tending to come from the dynamic side,
which I'll address first.

The first, and generally most significant misconception, has to do with
the concept of latent attribute lookup. In this example, it can be seen
that any file-like object is accepted, and this is precisely what makes
most dynamic languages so powerful:

def reverse_lines(file):
lines = file.readlines()
lines.reverse()
return lines

In actuality, this is not limited to dynamically-typed language; in
fact, it has a name: structural subtyping. If you were to translate
this into (object-orientized) OCaml, a statically typed language, you'd
get this:

let reverse_lines file =
file#readlines()#reverse()


The second misconception is that runtime errors aren't much worse than
compile time errors. First of all, one must define the term "error"; in
this case, an error is assumed to mean any unintended action by the
program. Now, with this in mind, it should be obvious that, even if you
do run the code that causes the error, you will have caught it at a
later time than if it had be brought to your attention at compile/edit
time. The longer it takes for an error to be discovered, the harder
it's going to be to fix, which should make it obvious that a lack of
compile-time error notification is a bad thing.


The third and final misconception is that static typing forbids the
presence of heterogenous containers and other oddly-typed objects.
There are two different types of heterogenous containers, so this
misconception will be dealt with in two parts.

The most common case by far is where the elements do actual share a
conceptual commonality but aren't related in a class hierarchy. This
can be readily seen in python, where tangible interfaces are frowned
upon. A suitable static type system can, in fact, acheive the exact
same goal with the same amount of typing through the use of a type
inferencer and structural subtyping.

The second case is when the objects in the container are only related
on an extremely basic level, e.g. if you only want to use the memory
address of each one ('id()' in python). This isn't an instrinsic
feature of dynamic typing, but rather of any type system which has a
type that matches any value, e.g. Object in Java, void* in C, etc. This
is similar to the first approach in that a common interface is used (a
truly heterogenous container would be useless), but it differs in that
this common interface is built into the language in some way.


Now that those myths have been dispelled, I'd like to get on to the
main topic--why I believe dynamic typing is superior to static typing
(I wonder how many of you thought I was on the side of static typing).

Aside from brevity, the main advantage of dynamic typing is the sheer
flexibility it provides. Runtime errors are guaranteed to only be
generated when there's an actual error, and even then they can be
caught or ignored by the programmer (can't find this module? no big
deal, just ignore it). This may seem like it conflicts with what I said
earlier about compile-time notification being good, and it does.

As previously stated, the faster a bug comes to light, the easier it
will be to fix and more likely that said fix is complete.

To understand why warnings are a proper supplement for errors, consider
this. An experienced programmer that has enough experience to recognize
his own faults as a human and work around them. This includes listening
to errors and warnings and trying to introduce as little bugs as
possible. As such, the difference between an error and a warning isn't
much--errors are simply more forceful than warnings. The only time this
distinction is useful is when you're trying to minimize the damage the
programmers have rather than enabling him to write good code in an
efficient manner. The corporate world is often cited as a user of such
languages, but it's my belief that if you need to actively prevent your
programmers from writing bad code by crippling the language, you need
to find better programmers.

To sum it all up: many arguments for dynamic typing are invalid as well
as many arguments against it, dynamic typing is useful because of its
flexibility, and warnings are just as good as errors at assisting most
programmers (the ones that matter).

Comments, praise, and hate mail is welcome,
Curtis

cr88192

unread,
Aug 14, 2006, 10:01:57 PM8/14/06
to

"Curtis W" <cwar...@gmail.com> wrote in message
news:1155601829....@i3g2000cwc.googlegroups.com...

> This basically sums up my thoughts on dynamic and static typing.
> Discuss as you wish.
>

yes.


> The topic of dynamic and static typing has been the hotbed of debate in
> many programming language arguments. Many times a good amount of FUD is
> thrown around, unfortunately tending to come from the dynamic side,
> which I'll address first.
>
> The first, and generally most significant misconception, has to do with
> the concept of latent attribute lookup. In this example, it can be seen
> that any file-like object is accepted, and this is precisely what makes
> most dynamic languages so powerful:
>
> def reverse_lines(file):
> lines = file.readlines()
> lines.reverse()
> return lines
>
> In actuality, this is not limited to dynamically-typed language; in
> fact, it has a name: structural subtyping. If you were to translate
> this into (object-orientized) OCaml, a statically typed language, you'd
> get this:
>
> let reverse_lines file =
> file#readlines()#reverse()
>

note, however, that not all languages can do this.
many, when they think or consider static typing, are considering something
like C or C++.

it is often the proposition: C++ vs "something else" (python, scheme, ...).


>
> The second misconception is that runtime errors aren't much worse than
> compile time errors. First of all, one must define the term "error"; in
> this case, an error is assumed to mean any unintended action by the
> program. Now, with this in mind, it should be obvious that, even if you
> do run the code that causes the error, you will have caught it at a
> later time than if it had be brought to your attention at compile/edit
> time. The longer it takes for an error to be discovered, the harder
> it's going to be to fix, which should make it obvious that a lack of
> compile-time error notification is a bad thing.
>

yes, I agree here.


>
> The third and final misconception is that static typing forbids the
> presence of heterogenous containers and other oddly-typed objects.
> There are two different types of heterogenous containers, so this
> misconception will be dealt with in two parts.
>

again, think C++ and friends...

> The most common case by far is where the elements do actual share a
> conceptual commonality but aren't related in a class hierarchy. This
> can be readily seen in python, where tangible interfaces are frowned
> upon. A suitable static type system can, in fact, acheive the exact
> same goal with the same amount of typing through the use of a type
> inferencer and structural subtyping.
>

but these are rare if one looks at most languages.


> The second case is when the objects in the container are only related
> on an extremely basic level, e.g. if you only want to use the memory
> address of each one ('id()' in python). This isn't an instrinsic
> feature of dynamic typing, but rather of any type system which has a
> type that matches any value, e.g. Object in Java, void* in C, etc. This
> is similar to the first approach in that a common interface is used (a
> truly heterogenous container would be useless), but it differs in that
> this common interface is built into the language in some way.
>

within some annoying limits, they exist.
extending this further, in java afaik one would have to check and cast
before they can use the object as before.

C, by default, does not have any real means to represent type information
(however, this can be done, along with GC, if one feels willing to write/use
a specialized memory manager).

more so, C does not guerantee that one does anything sane with the pointer,
as one can cast it to whatever they want (and still have to cast before they
can use it).

actually, in C there are 2 major ways one can do all this:
declare 'void *' as the universal type, and have a mechanism for
typechecking;
using tagged references.

the advantage of void pointers here is that, in C, this is particularly easy
to work with...

using a kind of tagged reference scheme. this has a few advantages over the
previous:
a whole lot more information can be represented in the tagged value itself,
thus greatly reducing the number of primitive types that need to be stored
on the heap;
one can make use of a highly uniform means for working with these objects
(the only other real option is a horrible mess);
you can highly abstract the data from its representation at the api level;
often, this makes possible a lot more precise and accurate treatment of the
data;
...

but, a few disadvantages exist as well:
all this can be fairly awkward and inconvinient in C;
one ends up writing code that consists quite heavily on usage of macros for
even the most basic tasks (the code may no longer even really resemble C by
this point);
depending on the implementation, it can be cumbersome to correctly manage
the treatment of the pointers;
...


as such, it is much better to have a language with a real dynamic
typesystem...


>
> Now that those myths have been dispelled, I'd like to get on to the
> main topic--why I believe dynamic typing is superior to static typing
> (I wonder how many of you thought I was on the side of static typing).
>

yeah.


> Aside from brevity, the main advantage of dynamic typing is the sheer
> flexibility it provides. Runtime errors are guaranteed to only be
> generated when there's an actual error, and even then they can be
> caught or ignored by the programmer (can't find this module? no big
> deal, just ignore it). This may seem like it conflicts with what I said
> earlier about compile-time notification being good, and it does.
>

not necissarily, it would be good if both are allowed by control of the
programmer (if the compiler does all this, however, then the conflict
stands).


> As previously stated, the faster a bug comes to light, the easier it
> will be to fix and more likely that said fix is complete.
>
> To understand why warnings are a proper supplement for errors, consider
> this. An experienced programmer that has enough experience to recognize
> his own faults as a human and work around them. This includes listening
> to errors and warnings and trying to introduce as little bugs as
> possible. As such, the difference between an error and a warning isn't
> much--errors are simply more forceful than warnings. The only time this
> distinction is useful is when you're trying to minimize the damage the
> programmers have rather than enabling him to write good code in an
> efficient manner. The corporate world is often cited as a user of such
> languages, but it's my belief that if you need to actively prevent your
> programmers from writing bad code by crippling the language, you need
> to find better programmers.
>

agreed.

then again, family members have argued that I have no chance in commercial
programming (eg, because I use C, of all languages, and not something like
VB or Java...).

I don't know, commercial or hobbyist isn't really what is important here.
I didn't spend all these years coding with an intent of "big money" or
whatever, but more because programming can be, and continues to be,
interesting...

parents only seem to think of money sometimes though...

in all likelyhood, I would need a job in some other domain, eg, IT,
education, ... but, being payed to write code (in my style) would be nice.
but it is my opinion that if it is low-end vb stuff vs some other job domain
(and remaining as a hobbyist), it is probably better to pick the later...


> To sum it all up: many arguments for dynamic typing are invalid as well
> as many arguments against it, dynamic typing is useful because of its
> flexibility, and warnings are just as good as errors at assisting most
> programmers (the ones that matter).
>

yes.

a fantasy of mine right now is for the unification of static and dynamic
typing, and also for imperative, oo, and functional programming, into a
language with ok performance and has a reasonable applicability domain (both
scripting and general purpose coding).

the language I have implemented recently more or less follows this design
premise, along with a number of others.

eg, the syntax is a "functionalized" variant of the c style. personally, I
feel the C style syntax as being an 'elegant' expression of human thought
and common notions in the form of syntax, wheras many others fall a little
short of this, or, alternatively, because it is one of the most well-known
styles...

this is different than more 'pure' syntaxes, which have elegance by
simiplicity (but may often have many oddball quirks), but I feel this is a
rather different notion (I guess I could draw an analogy to the slightly
different notions of 'elegance' found in physics and nature, and those found
in mathematics...).

statements and expressions are different, but not as drastically as one
might think, and the difference is kept where it matters (many
functional-ish languages treat everything as an expression, and may miss on
some meaningful aspects of statement semantics and similar...).

or such...

Robbert Haarman

unread,
Aug 15, 2006, 1:33:00 AM8/15/06
to
On Mon, Aug 14, 2006 at 05:30:30PM -0700, Curtis W wrote:
> This basically sums up my thoughts on dynamic and static typing.
> Discuss as you wish.

Hmm, I remember having a quite extensive discussion about this topic on
this group recently, which has taught me a thing or two.

First of all, and this goes for _any_ debate, it's _very_ important to
define exactly what you're talking about. What do you really mean by
static typing, and what by dynamic typing? I've seen static typing
defined as "variables can hold values of only one type", and dynamic
typing as "variables can hold values of more than one type". This leads
to a very different debate than my personal favorite definitions, where
static typing means "you will not be allowed to run your program, unless
you have convinced the type checker that your types are correct",
whereas dynamic typing means no such restriction is imposed.

Also note that there are two distinct things that types do: first of
all, they describe what can be done to values; e.g. a language could let
you divide two numbers, but not a string and a number. Secondly, types
may relate to representations, which may affect the memory requirements,
speed, results, or correctness of your program. E.g. many languages have
fixed-precission integers and floating point numbers, both of which can
be worked with efficiently on common hardware, but neither of which can
precisely represent irrational numbers, very large numbers, or very
small ones. In some languages, types _are_ representations (C?), in
other languages, types _are_ behaviors (Scheme?), and in many languages,
types are some mix of these two.

I lean towards the view that the behavior is all that should really
matter to program correctness, with representations being an
implementation or optimization issue. However, this is obviously not how
things are in many languages.

Now, static typing has the desireable property that it restricts the
programs you can write and run to those that are correct w.r.t. to the
type system. In other words, it will reject some buggy programs, never
allowing them to run, and hopefully informing the programmer of where
the bugs are and what they are. This is fantastic; I can't think of any
better way to deal with bugs.

It is this very same property of restricting the programs that can be
written and run that is the disadvantage of static typing. Static type
checkers may require programs to carry extra information beyond the
algorithms and magic values; for example, type annotations. This leads
to unnecessary verbosity. The type system may also reject some programs
that wouldn't actually exhibit bad behavior when accepted and run, thus
limiting the expressive power of a language.

Both the verbosity and the limited expressive power may actually be
desired, e.g. some people feel that type annotations should be
mandatory, and many of the programs a given type system would reject
could be considered bad style. However, arguably, this is mostly a
matter of personal preference, not technical merit.

How good or bad static typing is depends entirely on the type system.
Some type systems require lots of extra code, put lots of restrictions
on the programs that you can write, and allow many bugs to go undetected
(I would consider C an example here), whereas others catch many bugs
with little work and restrictions (I would say Ocaml provides an example
of that).

Since dynamic typing is, in some sense, the complement of static typing,
it stands to reason that the advantages of static typing are the
disadvantages of dynamic typing, and vice versa. This is true to some
extent. Indeed, since there is no need to convince the type checker your
program is correct, before you will be allowed to run it, dynamic typing
should not require the extra verbosity of type declarations and
annotations, nor limit the expressive power of the language to what can
be shoehorned into the type system.

On the other hand, the benefit of catching type errors at compile time
may be had with dynamic typing as well. An implementation couldn't
reject (i.e. refuse to run) a program based on type information (that
would be static typing), but it could emit warnings before the program
were run. This is called soft typing.

The above sounds like, with dynamic typing, you can have your cake and
eat it, too. This is true to an extent. You get to have possible bugs at
compile time, but you can still run your program despite them; thus no
restrictions on the expressive power of the language are imposed.
However, without these restrictions, and without extra type declarations
and annotations, compile time type checking can only take you so far.
Not all errors in the program may lead to compile time warnings, and not
all compile time warnings may indicate actual errors, and the reporting
is almost certain to be worse in the absence of a restrictive type
system.

So which is better, static or dynamic typing? I don't know. I program
mostly in dynamically typed languages, but not because they are
dynamically typed. I don't feel I often run into situations where static
typing would be a big win, but I rather like the idea behind it. Perhaps
there would be something to a language that allowed both: you could
write your program using dynamic typing, without the need for type
declarations and annotations, or, if you prefer, have your types checked
at compile time.

Just my two cents.

Bob

---
/* A piece of code that a friend sent to me */
while(x && y) { int t = x % y; x = y % x; x = t; } return x | y;

Robbert Haarman

unread,
Aug 15, 2006, 1:41:57 AM8/15/06
to
On Mon, Aug 14, 2006 at 05:30:30PM -0700, Curtis W wrote:
>
> The second case is when the objects in the container are only related
> on an extremely basic level, e.g. if you only want to use the memory
> address of each one ('id()' in python). This isn't an instrinsic
> feature of dynamic typing, but rather of any type system which has a
> type that matches any value, e.g. Object in Java, void* in C, etc. This
> is similar to the first approach in that a common interface is used (a
> truly heterogenous container would be useless), but it differs in that
> this common interface is built into the language in some way.

I just feel compelled to point out that neither Object in Java, nor
void* in C can refer to any type of value. In both cases, what Java
calls "primitive types" aren't covered: int, char, etc.

Bob

---
You know you should *really* get a life when you find yourself in the
middle of a flamemar about which vi clone is best.

cr88192

unread,
Aug 15, 2006, 4:00:36 AM8/15/06
to

"Robbert Haarman" <comp.la...@inglorion.net> wrote in message
news:2006081505...@morgenes.shire.sytes.net...

> On Mon, Aug 14, 2006 at 05:30:30PM -0700, Curtis W wrote:
>>
>> The second case is when the objects in the container are only related
>> on an extremely basic level, e.g. if you only want to use the memory
>> address of each one ('id()' in python). This isn't an instrinsic
>> feature of dynamic typing, but rather of any type system which has a
>> type that matches any value, e.g. Object in Java, void* in C, etc. This
>> is similar to the first approach in that a common interface is used (a
>> truly heterogenous container would be useless), but it differs in that
>> this common interface is built into the language in some way.
>
> I just feel compelled to point out that neither Object in Java, nor
> void* in C can refer to any type of value. In both cases, what Java
> calls "primitive types" aren't covered: int, char, etc.
>

one ugly thing I had done before was to grab chunks of address space, and
map the addesses to particular values. part is small integers, ...

anything else ends up allocated on the heap.


one can use tagged references (where one can encode quite a bit in those
ints), but then the whole 'void *' argument is gone, and one has a type
which is more or less permanently tied to the usage of a bunch of
preprocessor macros and runtime functions...

using just a few bits, one can have a fairly decent integer space, several
categories of primitive types, ...

an example mapping for a 3 bit tag:
0/4: fixnums (30 bit);
1: flonum (a float absent 3 mantissa bits);
2: misc values (a further subdivided space)
3: (something or another)
4: (as above)
5: cons cells
6: heap-based objects
7: (something or another)

so, in misc, you can put a lot of other things: special constants, character
values, ...

even for a 31 bit fixnum things are ok:
0/2/4/6: fixnums (31 bit);
1: flonum (a float absent 3 mantissa bits);
2: (as above)
3: misc values (a further subdivided space)
4: (as above)
5: cons cells
6: (as above)
7: heap-based objects


(in my vm, I left fixnums as 29 bits, though I could easily make them 30).

or such...


Marco van de Voort

unread,
Aug 15, 2006, 4:16:49 AM8/15/06
to
On 2006-08-15, Curtis W <cwar...@gmail.com> wrote:
> This basically sums up my thoughts on dynamic and static typing.
> Discuss as you wish.

First I think you should limit the application area, specially if you make
statements like

> The second misconception is that runtime errors aren't much worse than
> compile time errors. First of all, one must define the term "error"; in
> this case, an error is assumed to mean any unintended action by the
> program.

Not all computer language systems go through the cycle build-deploy-run.

While I'm a die hard static typed and compiled language user in general
software development, i've used math tools and MUD stuff that were a lot
laxer in every aspect, which raised their ease (and speed) of use
considerably.

Marco van de Voort

unread,
Aug 15, 2006, 4:42:50 AM8/15/06
to
On 2006-08-15, cr88192 <cr8...@NOSPAM.hotmail.com> wrote:

> then again, family members have argued that I have no chance in commercial
> programming (eg, because I use C, of all languages, and not something like
> VB or Java...).

They are right, you don't. But they calculate this from job adds that cite
years of relevant experience, and it is hard to fill that in an initial job
anyway.

But that is not a problem. If you know your programming fundaments well, and
enough languages (preferably different types and paradigma's), you'll easily
learn it, and have an edge over people that only "use" a language (contrary
to understand it)

The only thing that I'd recommend is a big project. To be a good programmer
you must have handled a big project before, and hit your nose on a lot of
little things, both technical and the ones related to project management,
scale, and preferably teamwork.

My hobbying with FPC was a perfect school to become a Delphi programmer.

Make sure you have some formal CS education though, and preferably, don't
wait with your first job in something commercial till you are on the other
side of 25. (that is not a hard limit, but it makes it easier)

Message has been deleted

Robbert Haarman

unread,
Aug 15, 2006, 7:30:06 AM8/15/06
to
On Tue, Aug 15, 2006 at 10:05:21AM +0000, Stefan Ram wrote:
> Robbert Haarman <comp.la...@inglorion.net> writes:
> >type annotations. This leads to unnecessary verbosity.
>
> One also might regard this as documentation.

Yes. In fact, this is exactly what I had in mind when I wrote that the
added verbosity may not be undesireable.

> Without static types:
>
> bind( first, second ){ return new Bind( first, second ).composition(); }
>
> With static types:
>
> Operation<IntValue,MemoryState> bind
> ( Operation<IntValue,MemoryState> first,
> ParameterizedOperation<IntValue,MemoryState,IntValue> second )
> { return new Bind<IntValue,MemoryState,IntValue>
> ( first, second ).composition(); }
>
> Which one is more readable? The second one looks more
> difficult to read at first sight, but it also provides more
> information at the second sight, for example about the kind of
> value returned.

Uhh...I'm not sure this is the best example you could have picked. I
find the second one hard to read because of all the punctuation and
capitalization and the absence of spaces, and even after I manage to
parse it, I have no idea what it's supposed to do. Not that I know what
the first one does, either, but I could argue that that's because of bad
naming, rather than missing type annotations (i.e. first, second, and
possibly bind aren't the most helpful names).

Consider the following example:

/* Test if a collection contains an item */
contains(x, y) { ... }

Is x the collection and y the item, or the other way around?

/* Test if a collection contains an item */
contains(Collection x, Item y) { ... }

Ah! That's clearer. But then, so is

/* Test if a collection contains an item */
contains(collection, item) { ... }

or even

/* Test if the collection x contains the item y */
contains(x, y) { ... }

so I would say there are plenty of alternatives to type annotations as
documentation. Given the extra work of typing in type annotations, and
especially the work of replacing them if I ever want to change a type
(not uncommon, in my experience), I prefer them not to be mandatory. Of
course, if they aren't mandatory, people are going to omit
them...possibly leaving you without any clue as to what the arguments to
some functions should be. There's something to be said for both sides.

Regards,

Bob

---
Reality is that which, when you stop believing in it, doesn't go away.

-- Philip K. Dick


Message has been deleted

Curtis W

unread,
Aug 15, 2006, 10:25:24 AM8/15/06
to
> First of all, and this goes for _any_ debate, it's _very_ important to
> define exactly what you're talking about. What do you really mean by
> static typing, and what by dynamic typing? I've seen static typing
> defined as "variables can hold values of only one type", and dynamic
> typing as "variables can hold values of more than one type". This leads
> to a very different debate than my personal favorite definitions, where
> static typing means "you will not be allowed to run your program, unless
> you have convinced the type checker that your types are correct",
> whereas dynamic typing means no such restriction is imposed.
My definitions of static and dynamic typing are the same as the last
ones you provide.

> Also note that there are two distinct things that types do: first of
> all, they describe what can be done to values; e.g. a language could let
> you divide two numbers, but not a string and a number. Secondly, types
> may relate to representations, which may affect the memory requirements,
> speed, results, or correctness of your program. E.g. many languages have
> fixed-precission integers and floating point numbers, both of which can
> be worked with efficiently on common hardware, but neither of which can
> precisely represent irrational numbers, very large numbers, or very
> small ones. In some languages, types _are_ representations (C?), in
> other languages, types _are_ behaviors (Scheme?), and in many languages,
> types are some mix of these two.

Types are, and can be, both. The concrete representation of a value is
a property of a type just as the routines which operate on it are.

> I lean towards the view that the behavior is all that should really
> matter to program correctness, with representations being an
> implementation or optimization issue. However, this is obviously not how
> things are in many languages.

Be careful with that thinking. While it is true implementation, etc.
are optimization issues, they can really only be done effectively by
the programmer. While it's a good idea to provide sensible defaults, a
language without the ability to fine-tune properties like that would be
very inflexible in certain situations.

> Now, static typing has the desireable property that it restricts the
> programs you can write and run to those that are correct w.r.t. to the
> type system. In other words, it will reject some buggy programs, never
> allowing them to run, and hopefully informing the programmer of where
> the bugs are and what they are. This is fantastic; I can't think of any
> better way to deal with bugs.

Rejection is such a forceful approach. Do you really need to be forced
to be a good programmer?

> It is this very same property of restricting the programs that can be
> written and run that is the disadvantage of static typing. Static type
> checkers may require programs to carry extra information beyond the
> algorithms and magic values; for example, type annotations. This leads
> to unnecessary verbosity. The type system may also reject some programs
> that wouldn't actually exhibit bad behavior when accepted and run, thus
> limiting the expressive power of a language.

Type annotations are possible, and indeed desirable in some situations,
in dynamic typing. Among other things, they can be used to help speed
up a program, and coupled with a dependent type system they can provide
a very powerful means for reducing code bloat. For an example of this,
consider that most public get/set routines are generally emulating
variable constraints (in a very verbose way).

> Both the verbosity and the limited expressive power may actually be
> desired, e.g. some people feel that type annotations should be
> mandatory, and many of the programs a given type system would reject
> could be considered bad style. However, arguably, this is mostly a
> matter of personal preference, not technical merit.

Yes.

> How good or bad static typing is depends entirely on the type system.
> Some type systems require lots of extra code, put lots of restrictions
> on the programs that you can write, and allow many bugs to go undetected
> (I would consider C an example here), whereas others catch many bugs
> with little work and restrictions (I would say Ocaml provides an example
> of that).

In a theoretical discussion such as this it's a good idea to assume the
best possible situation for each entity.

> On the other hand, the benefit of catching type errors at compile time
> may be had with dynamic typing as well. An implementation couldn't
> reject (i.e. refuse to run) a program based on type information (that
> would be static typing), but it could emit warnings before the program
> were run. This is called soft typing.

Hmm, I don't think that's right. Soft typing is basically dynamic
typing with type checks (the ones that are possible) done at compile
time. If it's proven that it will error out at compile time, an error
will be issued at compile time, otherwise runtime checks are inserted.
Warnings are much more passive than this, which is why I believe it's
still dynamic typing.

> The above sounds like, with dynamic typing, you can have your cake and
> eat it, too. This is true to an extent. You get to have possible bugs at
> compile time, but you can still run your program despite them; thus no
> restrictions on the expressive power of the language are imposed.
> However, without these restrictions, and without extra type declarations
> and annotations, compile time type checking can only take you so far.
> Not all errors in the program may lead to compile time warnings, and not
> all compile time warnings may indicate actual errors, and the reporting
> is almost certain to be worse in the absence of a restrictive type
> system.

Define "restrictive." In my mind, a type system need not be restrictive
in order to assist the programmer.

cr88192

unread,
Aug 15, 2006, 10:26:43 AM8/15/06
to

"Marco van de Voort" <mar...@stack.nl> wrote in message
news:slrnee3291....@snail.stack.nl...

> On 2006-08-15, cr88192 <cr8...@NOSPAM.hotmail.com> wrote:
>
>> then again, family members have argued that I have no chance in
>> commercial
>> programming (eg, because I use C, of all languages, and not something
>> like
>> VB or Java...).
>
> They are right, you don't. But they calculate this from job adds that cite
> years of relevant experience, and it is hard to fill that in an initial
> job
> anyway.
>

yes.


> But that is not a problem. If you know your programming fundaments well,
> and
> enough languages (preferably different types and paradigma's), you'll
> easily
> learn it, and have an edge over people that only "use" a language
> (contrary
> to understand it)
>

yes, makes sense...

I know C and assembler fairly well, and to a lesser extent C++.

I also have some experience with scheme, and a few other
functional-imperative languages (usually implemented by myself though for my
own uses...).

some experience writing scripts in a postscript variant at one point.

however, nearly all my practical code it seems ends up being in C.

none of my custom languages has featured a fully working jit compiler as of
yet though (typically, they are bytecoded...).


> The only thing that I'd recommend is a big project. To be a good
> programmer
> you must have handled a big project before, and hit your nose on a lot of
> little things, both technical and the ones related to project management,
> scale, and preferably teamwork.
>

yeah, scale is difficult.
it seems right now that project coherency starts to break down after I much
exceed about 25-50kloc (if that).

so, I have a 300kloc project consisting of a number of different pieces, but
the project itself doesn't seem to be much of anything in particular (and
progress in core areas has become exeeedingly slow).

I keep going off and implementing dubious side-projects (often a few kloc or
so). a recent example was a larger-window variant of deflate (ratios exceed
those of gzip, but are often, but not always, worse than those of bzip2),
and the compression speed isn't so good either.

on my computer, compressor often pulls off about 1-2MB/s, and the
decompressor often about 130MB/s.

the bitsteam is based on a modified form of deflate, and it is designed such
that the decoder will decode both this format and conventional deflate. for
now I am using a 1MB sliding window (the main adaptation was allowing larger
dictionaries and longer matches...).


> My hobbying with FPC was a perfect school to become a Delphi programmer.
>
> Make sure you have some formal CS education though, and preferably, don't
> wait with your first job in something commercial till you are on the other
> side of 25. (that is not a hard limit, but it makes it easier)

maybe. I still have a few years to go there...

actually, I was going for a CS major, but parents decided to move me to a
different college and change it over to being an english major (thinking
that this would be more practical for jobs and similar).

Curtis W

unread,
Aug 15, 2006, 10:35:59 AM8/15/06
to
> >type annotations. This leads to unnecessary verbosity.
>
> One also might regard this as documentation.
>
> Without static types:
>
> bind( first, second ){ return new Bind( first, second ).composition(); }
>
> With static types:
>
> Operation<IntValue,MemoryState> bind
> ( Operation<IntValue,MemoryState> first,
> ParameterizedOperation<IntValue,MemoryState,IntValue> second )
> { return new Bind<IntValue,MemoryState,IntValue>
> ( first, second ).composition(); }
>
> Which one is more readable? The second one looks more
> difficult to read at first sight, but it also provides more
> information at the second sight, for example about the kind of
> value returned.
Yes, it does provide more information. You forgot to mention, though,
that said information is easily derivable from the body of the
function. If it's already available to the computer, doesn't it make
sense to just have it display it to you, rather than forcing you to
write it manually?

On the other hand, explicit typing shows intent, which I believe might
be what you're trying to get at. Certainly it has its uses--when one
wants to artificially restrict values for, e.g. speed reasons, the
compiler certainly cannot derive this. The problem with intent, though,
is that you're introducing more sources for errors by duplicating code:
is this type wrong, or is the code wrong? In the end, I find that type
annotations are good in certain (rare) situations, but if you truly
need to second-guess the compiler it's a good idea to put in a comment
stating your reasons for doing so.

Curtis W

unread,
Aug 15, 2006, 10:39:53 AM8/15/06
to

Marco van de Voort wrote:
> On 2006-08-15, Curtis W <cwar...@gmail.com> wrote:
> > This basically sums up my thoughts on dynamic and static typing.
> > Discuss as you wish.
>
> First I think you should limit the application area, specially if you make
> statements like
There is no "application area." I'm speaking in general.

> > The second misconception is that runtime errors aren't much worse than
> > compile time errors. First of all, one must define the term "error"; in
> > this case, an error is assumed to mean any unintended action by the
> > program.
>
> Not all computer language systems go through the cycle build-deploy-run.

Whether or not they do is irrelevant; simply displaying warnings at
edit-time is fine for what I'm talking about. If anything, it's the
preferred method due to the effectiveness of graphics at displaying
associations (between error and location).

Curtis W

unread,
Aug 15, 2006, 10:56:54 AM8/15/06
to

Robbert Haarman wrote:
> On Mon, Aug 14, 2006 at 05:30:30PM -0700, Curtis W wrote:
> >
> > The second case is when the objects in the container are only related
> > on an extremely basic level, e.g. if you only want to use the memory
> > address of each one ('id()' in python). This isn't an instrinsic
> > feature of dynamic typing, but rather of any type system which has a
> > type that matches any value, e.g. Object in Java, void* in C, etc. This
> > is similar to the first approach in that a common interface is used (a
> > truly heterogenous container would be useless), but it differs in that
> > this common interface is built into the language in some way.
>
> I just feel compelled to point out that neither Object in Java, nor
> void* in C can refer to any type of value. In both cases, what Java
> calls "primitive types" aren't covered: int, char, etc.
You're right about Java, but void* does cover primitives when you use
pointers. Alternatively, if you know you'll be storing primitives of a
fixed size, you can just use an int and cast it.

Robbert Haarman

unread,
Aug 15, 2006, 12:13:43 PM8/15/06
to Curtis W

Alright, we're picking nits here, but just because you can store a
_pointer_ to any value in a variable declared void* does not mean you
can store any _value_ in such a variable. And there's definitely a
difference between those (pass by value vs. pass by reference, etc.).
Casting doesn't fly either; apart from the fact that the casting incurrs
extra work, you can't store a double or a long long in a void* variable
under most ABIs. All in all, I can't agree that void* variables can hold
any value in C.

Bob

---
I don't believe in ghosts, but ghosts believe in me.


Curtis W

unread,
Aug 15, 2006, 12:17:45 PM8/15/06
to
Well, if you want to get that pedantic, I'll rephrase it:

"This isn't an instrinsic feature of dynamic typing, but rather of any
type system which has a type that matches any value, e.g. Object

matches any class in Java, void* any pointer in C, etc."

Robbert Haarman

unread,
Aug 15, 2006, 12:47:37 PM8/15/06
to
Curtis,

> "This isn't an instrinsic feature of dynamic typing, but rather of any
> type system which has a type that matches any value, e.g. Object
> matches any class in Java, void* any pointer in C, etc."

Why don't you just get rid of the example that doesn't work? You were
talking about heterogenous containers. You're saying that being able to
put values of any number of different types in the same container isn't
"an intrinsic feature of dynamic typing, but rather of any type system
which has a type that matches any value". So far, so good. But Object
doesn't match any value in Java, nor does void * match any value in C: a
container that accepts Objects won't accept ints in Java, and a
container that accepts void*s won't accept ints in C.

The only languages I can name from the top of my head that have a type
that matches any value are Common Lisp (T), Smalltalk (Object) and Ruby
(Object). But these are all dynamically typed...

Having said all that, suppose that, in some statically typed language,
one did make, say, a list of Objects, with an Integer, a String, and a
UsefulType object in it. Would that be a heterogenous container? Or
would it be a list containing elements of type Object, with only the
functions that apply to Objects allowed to be called on them?

Regards,

Bob

---
Time flies like an arrow.
Fruit flies like a banana.


Curtis W

unread,
Aug 15, 2006, 12:57:45 PM8/15/06
to
> Why don't you just get rid of the example that doesn't work? You were
> talking about heterogenous containers. You're saying that being able to
> put values of any number of different types in the same container isn't
> "an intrinsic feature of dynamic typing, but rather of any type system
> which has a type that matches any value". So far, so good. But Object
> doesn't match any value in Java, nor does void * match any value in C: a
> container that accepts Objects won't accept ints in Java, and a
> container that accepts void*s won't accept ints in C.
Object will match any boxed value, just as void* will match any pointer
value. Read on to see what this has to do with anything.

> The only languages I can name from the top of my head that have a type
> that matches any value are Common Lisp (T), Smalltalk (Object) and Ruby
> (Object). But these are all dynamically typed...

OCaml has open data types, which can be used to create heterogenous
lists.

> Having said all that, suppose that, in some statically typed language,
> one did make, say, a list of Objects, with an Integer, a String, and a
> UsefulType object in it. Would that be a heterogenous container? Or
> would it be a list containing elements of type Object, with only the
> functions that apply to Objects allowed to be called on them?

No list is truly heterogenous; after all, what would you do with a list
where all the objects share nothing in common? You could say "just pass
it around," but then they're sharing a property in most languages, e.g.
in C they can all be converted into a raw bag of bytes and in python
you can still use several built-in functions on them: id, repr, dir,
etc. The point behind calling it "heterogenous" is that the type of
objects might change in the future, which means modifying two things in
most static languages--the type declaration and the actual routines
that deal with the values. This is why Object and void* are relevant;
they can represent an infinite amount of values, most not even needing
to be adapted to fit, and thus allow for extension of the list without
modifying its type signature.

Robbert Haarman

unread,
Aug 15, 2006, 2:02:55 PM8/15/06
to
On Tue, Aug 15, 2006 at 09:57:45AM -0700, Curtis W wrote:
>
> > Having said all that, suppose that, in some statically typed language,
> > one did make, say, a list of Objects, with an Integer, a String, and a
> > UsefulType object in it. Would that be a heterogenous container? Or
> > would it be a list containing elements of type Object, with only the
> > functions that apply to Objects allowed to be called on them?
> No list is truly heterogenous; after all, what would you do with a list
> where all the objects share nothing in common? You could say "just pass
> it around," but then they're sharing a property in most languages, e.g.
> in C they can all be converted into a raw bag of bytes and in python
> you can still use several built-in functions on them: id, repr, dir,
> etc. The point behind calling it "heterogenous" is that the type of
> objects might change in the future, which means modifying two things in
> most static languages--the type declaration and the actual routines
> that deal with the values. This is why Object and void* are relevant;
> they can represent an infinite amount of values, most not even needing
> to be adapted to fit, and thus allow for extension of the list without
> modifying its type signature.

Alright, but in typical dynamically typed languages, you can make
heterogenous lists, and use more than just the operations defined on the
common base type (if any) on the elements. For example, in Ruby, it's
perfectly fine to say:

foo = ['is', 42, 'the answer']
n = 0
while n < foo[0].length
case foo[0][n].chr
when 'i'
foo[n + 1] = foo[n + 1] / 2
when 's'
foo[n + 1] = foo[n + 1].reverse
end
n = n + 1
end
puts foo[1]
puts foo[2]

I think it should be clear what it does. It should also be clear that
not all elements of foo have the same type. Not all of the operations
used in the while loop can be performed on all elements of foo: integers
can't be reversed, and strings can't be divided by 2. So, I think you
can rightly say foo is a heterogenous container. Yet, you won't get any
complaint from the type system, and the program will work fine. And if
foo had come out of some function that depended on user input or
whatever, instead of just being initialized from literals, it would
still work - provided, of course, that the format string accurately
described the contents of foo.

I'm not claiming the above is good programming style, but it's a fact
that it's easy to find dynamically typed languages that allow it, and
hard to find statically typed languages that do.

Of course, in Java, you could have foo be a list of Objects, make 42
into an Integer, and then cast foo[n + 1] to an Integer or a String
according to the format string, but I submit that

1. Casting, as in Java and C and C++ is cheating - you're overriding the
type system.

2. In Java, casting causes that part of your program to be dynamically
typed, because a run-time check will be inserted (in C, the compiler
just assumes you know what you're doing, and happily allows you to cause
mayhem).

3. It's still not a heterogenous container - it contains only values of
type Object, and you can only perform operations on them that can be
performed on instances of Object - casting being one of these.

Alright. You could argue that the list in Ruby isn't heterogenous,
either; that it only contains Objects, and that only operations that are
allowed on Objects can be performed on them, those being all operations
in the language - except that some will signal errors at run time. That
view would be entirely correct, and in that sense, dynamic typing is a
special case of static typing, namely the case where all values have the
same type. However, I'm not sure that view is useful, at least not as
useful as the view that 12 is of type Integer and "foo" is of type
String, and the method / works for Integers, but not Strings, whereas
reverse works for Strings but not Integers; and foo contains Strings and
Integers. Of course, this once again underscores the importance of
definitions.

Regards,

Bob

---
Programs should be written for people to read, and only incidentally for
machines to execute.

-- From: Structure and Interpretation of Computer Programs

Curtis W

unread,
Aug 15, 2006, 3:48:59 PM8/15/06
to
This has little to do with heterogenous lists. Rather, it has
everything to do with what I like to call "possible errors." These are
situations in which a specific operation might be correct, but it's
impossible to tell at compile time, hence they rely on runtime
information. Although your example does not (and, indeed, it can be
proven at compile time since foo is constant), I see what your getting
at. The difference between static and dynamic typing in this regard is
essentially that (strong) static typing forces you to acknowledge and
handle possible errors, whereas dynamic typing allows you to ignore
them and will insert runtime checks for you.

> I'm not claiming the above is good programming style, but it's a fact
> that it's easy to find dynamically typed languages that allow it, and
> hard to find statically typed languages that do.

Obviously. That's a major difference between dynamic typing and static
typing. You'd be similarly hard pressed to find a standard PC running
windows made by Apple.

> Of course, in Java, you could have foo be a list of Objects, make 42
> into an Integer, and then cast foo[n + 1] to an Integer or a String
> according to the format string, but I submit that
>
> 1. Casting, as in Java and C and C++ is cheating - you're overriding the
> type system.
>
> 2. In Java, casting causes that part of your program to be dynamically
> typed, because a run-time check will be inserted (in C, the compiler
> just assumes you know what you're doing, and happily allows you to cause
> mayhem).

Not all static languages have casting. OCaml doesn't; rather, it uses
pattern matching instead.

> 3. It's still not a heterogenous container - it contains only values of
> type Object, and you can only perform operations on them that can be
> performed on instances of Object - casting being one of these.

Did you even bother reading my definition of a heterogenous container
earlier? _No_ container is heterogenous in the way you think of it. The
whole idea isn't that they contain several different types--indeed, if
they only contained a fixed amount then it would be trivial to include
the types in a union. Instead, heterogenous containers have to deal
with an ever-expanding amount of types without requiring the programmer
to update a union type containing them all.

Curtis W

unread,
Aug 15, 2006, 3:52:57 PM8/15/06
to
> > The topic of dynamic and static typing has been the hotbed of debate in
> > many programming language arguments. Many times a good amount of FUD is
> > thrown around, unfortunately tending to come from the dynamic side,
> > which I'll address first.
> >
> > The first, and generally most significant misconception, has to do with
> > the concept of latent attribute lookup. In this example, it can be seen
> > that any file-like object is accepted, and this is precisely what makes
> > most dynamic languages so powerful:
> >
> > def reverse_lines(file):
> > lines = file.readlines()
> > lines.reverse()
> > return lines
> >
> > In actuality, this is not limited to dynamically-typed language; in
> > fact, it has a name: structural subtyping. If you were to translate
> > this into (object-orientized) OCaml, a statically typed language, you'd
> > get this:
> >
> > let reverse_lines file =
> > file#readlines()#reverse()
> >
>
> note, however, that not all languages can do this.
> many, when they think or consider static typing, are considering something
> like C or C++.
>
> it is often the proposition: C++ vs "something else" (python, scheme, ...).
This isn't about C or C++, it's about static typing in general.

> > The most common case by far is where the elements do actual share a
> > conceptual commonality but aren't related in a class hierarchy. This
> > can be readily seen in python, where tangible interfaces are frowned
> > upon. A suitable static type system can, in fact, acheive the exact
> > same goal with the same amount of typing through the use of a type
> > inferencer and structural subtyping.
> >
>
> but these are rare if one looks at most languages.

This isn't a concrete comparison. Looking at most languages in a
discussion like this would do nothing but skew the results.

> as such, it is much better to have a language with a real dynamic
> typesystem...

Either that, or use a language that has a decent type system in
general. OCaml handles that situation fine, for example.

Robbert Haarman

unread,
Aug 15, 2006, 4:48:01 PM8/15/06
to
Curtis,

I seem to be misunderstanding what you mean by "heterogenous
containers". I'm going to review what you've said, and add my
interpretations and comments. Please tell me where I'm going wrong. What
you said was:

> No list is truly heterogenous; after all, what would you do with a
> list where all the objects share nothing in common? You could say
> "just pass it around," but then they're sharing a property in most
> languages, e.g. in C they can all be converted into a raw bag of bytes
> and in python you can still use several built-in functions on them:
> id, repr, dir, etc. The point behind calling it "heterogenous" is that
> the type of objects might change in the future, which means modifying
> two things in most static languages--the type declaration and the
> actual routines that deal with the values. This is why Object and
> void* are relevant; they can represent an infinite amount of values,
> most not even needing to be adapted to fit, and thus allow for
> extension of the list without modifying its type signature.

What I understand from that is that a "truly heterogenous" list has
elements of types that have absolutely nothing in common, except,
obviously, that they can be part of that list. You claim such lists
don't exist, because, at the very least, there will be some operations
supported by every element of the list. I dispute that claim; I gave an
example of a list with elements where the operations that are being
performed on the elements are not supported by all these elements. It is
true that there are also some operations that all these elements
support, but that just happens to be the case in Ruby; the example would
work the same way if there were no common operations supported by the
elements in the list. Hence, truly heterogenous lists, as you define
them, can exist in theory; unless I misunderstand you.

Then you go on to say that, since "truly heterogenous" lists can't
exist, "heterogenous list" should instead mean a list whose elements may
have different types in the future. As an example, you mention a list
whose elements are declared to be of type Object, which, we will assume,
allows any type of value. This, then, would be a "heterogenous list" in
a static language. I wonder, though, what is heterogenous about it. All
elements share a base type, Object, which, because the language is
statically typed, should mean that only the operations defined for
Object can be applied to them, right? So the list is heterogenous, but
all its elements support a certain set of operations, and those are the
only operations you can perform on the elements. Doesn't that make the
list homogenous?

Regards,

Bob

---
A policeman pulls Werner Heisenberg over on the Autobahn for speeding.

Policeman: Sir, do you know how fast you were going?
Heisenberg: No, but I know exactly where I am.


Curtis W

unread,
Aug 15, 2006, 4:59:39 PM8/15/06
to
> What I understand from that is that a "truly heterogenous" list has
> elements of types that have absolutely nothing in common, except,
> obviously, that they can be part of that list. You claim such lists
> don't exist, because, at the very least, there will be some operations
> supported by every element of the list. I dispute that claim; I gave an
> example of a list with elements where the operations that are being
> performed on the elements are not supported by all these elements. It is
> true that there are also some operations that all these elements
> support, but that just happens to be the case in Ruby; the example would
> work the same way if there were no common operations supported by the
> elements in the list. Hence, truly heterogenous lists, as you define
> them, can exist in theory; unless I misunderstand you.
They can exist in theory, but they don't. In reality, languages have a
'base' featureset of a value, whether it be simply because the language
is so low-level or because everything in that language is derived from
a single base class. Yes, it is possible that somebody out there has
created a truly heterogenous list, but what use is it? If none of the
elements support a similar interface then you can't even downcast them
to the correct type since you don't know what it is!

> Then you go on to say that, since "truly heterogenous" lists can't
> exist, "heterogenous list" should instead mean a list whose elements may
> have different types in the future. As an example, you mention a list
> whose elements are declared to be of type Object, which, we will assume,
> allows any type of value. This, then, would be a "heterogenous list" in
> a static language. I wonder, though, what is heterogenous about it. All
> elements share a base type, Object, which, because the language is
> statically typed, should mean that only the operations defined for
> Object can be applied to them, right? So the list is heterogenous, but
> all its elements support a certain set of operations, and those are the
> only operations you can perform on the elements. Doesn't that make the
> list homogenous?

Again, by that logic there is no such thing as a heterogenous list (or
at least, it becomes so useless to be impractical).

Robbert Haarman

unread,
Aug 15, 2006, 5:45:50 PM8/15/06
to
On Tue, Aug 15, 2006 at 01:59:39PM -0700, Curtis W wrote:
>
> Yes, it is possible that somebody out there has
> created a truly heterogenous list, but what use is it? If none of the
> elements support a similar interface then you can't even downcast them
> to the correct type since you don't know what it is!

And now we return to the topic we were discussing: static vs. dynamic
typing. Because, under dynamic typing, the elements of the list don't
_have_ to implement a common interface; as long as you only ever use
elements with operations that they support, you're fine (and you don't
ever have to cast - after all, it's the values themselves that have the
types, not the places that hold them). In a statically typed language,
you would be limited to those operations that are supported by all
elements - which, for a truly heterogenous list, would be none, and
thus, indeed, the list would be useless.

Of course, I'm talking about the general case here; in cases where you
can determine, at compile time, what the type of every element in the
list will be, and what operations will be applied to it, static typing
could accept the program.

As I've said before, static typing means that your program will be
rejected, unless you convince the type checker that the types are right,
whereas dynamic typing will let you run the program no matter what
(although it could be acceptible to reject a program if it can be proven
that it will never work under any circumstances). And that's why
heterogenous lists make (some) sense under dynamic typing: you may not
be able to prove that the operations you subject the elements to make
sense, but if that happens to be the case, your program will work.

Bob

---
There are two ways of constructing a software design. One way is to make
it so simple that there are obviously no deficiencies. And the other way
is to make it so complicated that there are no obvious deficiencies.

-- C.A.R. Hoare

Curtis W

unread,
Aug 15, 2006, 6:48:07 PM8/15/06
to
> And now we return to the topic we were discussing: static vs. dynamic
> typing. Because, under dynamic typing, the elements of the list don't
> _have_ to implement a common interface; as long as you only ever use
> elements with operations that they support, you're fine (and you don't
> ever have to cast - after all, it's the values themselves that have the
> types, not the places that hold them).
No. The only way you can work on a truly heterogenous list, even in a
dynamic language, without causing an error is to do different things
depending on the capability of each element. The latter part requires
at least some commonality, whether it be finding its type or listing
its methods.

> In a statically typed language,
> you would be limited to those operations that are supported by all
> elements - which, for a truly heterogenous list, would be none, and
> thus, indeed, the list would be useless.

No. If that were true, you'd be saying statically typed languages
aren't turing complete. Statically typed languages are able to do
anything dynamic languages can, so I'm not sure where you're getting
this from.

> As I've said before, static typing means that your program will be
> rejected, unless you convince the type checker that the types are right,
> whereas dynamic typing will let you run the program no matter what
> (although it could be acceptible to reject a program if it can be proven
> that it will never work under any circumstances). And that's why
> heterogenous lists make (some) sense under dynamic typing: you may not
> be able to prove that the operations you subject the elements to make
> sense, but if that happens to be the case, your program will work.

You know I'm for dynamic typing, right?

p.s. I wonder where Jon Harrop is. It'd almost be like that RAD vs.
performance thread with him here, and I know he definitely doesn't
agree that dynamic typing is better (although, if he doesn't respond,
maybe he does? ;-)

cr88192

unread,
Aug 15, 2006, 10:43:15 PM8/15/06
to

"Curtis W" <cwar...@gmail.com> wrote in message
news:1155671576....@75g2000cwc.googlegroups.com...

but then, what static typing?
the C/C++ notion is one possibility;
ocaml, haskell, ... have rather different definitions;
...

so, artifically narrowing it, I consider C/C++ and that particular notion of
static typing, because that is more likely what more are fammiliar with.

otherwise, you have to better define what notion it is you are defining.


>> > The most common case by far is where the elements do actual share a
>> > conceptual commonality but aren't related in a class hierarchy. This
>> > can be readily seen in python, where tangible interfaces are frowned
>> > upon. A suitable static type system can, in fact, acheive the exact
>> > same goal with the same amount of typing through the use of a type
>> > inferencer and structural subtyping.
>> >
>>
>> but these are rare if one looks at most languages.
> This isn't a concrete comparison. Looking at most languages in a
> discussion like this would do nothing but skew the results.
>

yet, it is "most languages" that people typically use as a basis for
understanding and comparison. one needs either specific examples, or a
specific definition.

C and OCaml are both statically typed, yes, but what then is the definition.

C only barely enforces its type model, and requires type declarations for
everything.

OCaml can skip on the declarations, and uses type inference for everything,
and otherwise has completely different semantics.

from the C perspective, the OCaml model looks like an optimization, and
fussier version, of dynamic typing.

from the other perspective, C is damn near untyped...


>> as such, it is much better to have a language with a real dynamic
>> typesystem...
> Either that, or use a language that has a decent type system in
> general. OCaml handles that situation fine, for example.
>

but, then, one faces the implications of using a language other than C or
C++...

community, tools, other code, and existing codebase, are big concerns, and
one does not leave their boat unless they have somewhere else good and solid
to stand...

for example, Java almost seems like a tolerable alternative to C++, but
then, one has to weight against the costs (loss of pointers, function
pointers, fact that code porting would be a horrible pita, not so great
ability to integrate with C APIs, ...).

so, it is not exactly something to be considered lightly...


Curtis W

unread,
Aug 15, 2006, 11:14:14 PM8/15/06
to
Static typing is when all type checking is done at compile time.

> the C/C++ notion is one possibility;
> ocaml, haskell, ... have rather different definitions;

No, they don't. They have different type systems in general, but
they're all statically typed.

> so, artifically narrowing it, I consider C/C++ and that particular notion of
> static typing, because that is more likely what more are fammiliar with.

It's not a "notion" of static typing; it is a weak, statically typed
language. OCaml is a strong statically typed language. OCaml also
happens to support a few other type constructs, which aren't usually
relevant.

> >> > The most common case by far is where the elements do actual share a
> >> > conceptual commonality but aren't related in a class hierarchy. This
> >> > can be readily seen in python, where tangible interfaces are frowned
> >> > upon. A suitable static type system can, in fact, acheive the exact
> >> > same goal with the same amount of typing through the use of a type
> >> > inferencer and structural subtyping.
> >> >
> >>
> >> but these are rare if one looks at most languages.
> > This isn't a concrete comparison. Looking at most languages in a
> > discussion like this would do nothing but skew the results.
> >
>
> yet, it is "most languages" that people typically use as a basis for
> understanding and comparison. one needs either specific examples, or a
> specific definition.

Static typing is well defined; if I had a different definition of the
word I would've stated so.

> from the C perspective, the OCaml model looks like an optimization, and
> fussier version, of dynamic typing.

Not if they've ever programmed in OCaml it doesn't.

Robbert Haarman

unread,
Aug 16, 2006, 3:31:26 AM8/16/06
to
Curtis,

> > And now we return to the topic we were discussing: static vs. dynamic
> > typing. Because, under dynamic typing, the elements of the list don't
> > _have_ to implement a common interface; as long as you only ever use
> > elements with operations that they support, you're fine (and you don't
> > ever have to cast - after all, it's the values themselves that have the
> > types, not the places that hold them).
> No. The only way you can work on a truly heterogenous list, even in a
> dynamic language, without causing an error is to do different things
> depending on the capability of each element. The latter part requires
> at least some commonality, whether it be finding its type or listing
> its methods.

Didn't my example demonstrate that, under dynamic typing, you can call
type-specific functions on your values _without_ calling commonly
supported methods first? Yes, you have to know what the type of your
values is, to prevent type errors, but you can get this information from
other sources than the values themselves, e.g. a format string.

> > In a statically typed language,
> > you would be limited to those operations that are supported by all
> > elements - which, for a truly heterogenous list, would be none, and
> > thus, indeed, the list would be useless.
> No. If that were true, you'd be saying statically typed languages
> aren't turing complete. Statically typed languages are able to do
> anything dynamic languages can, so I'm not sure where you're getting
> this from.

Being Turing complete just means that a certain set of operations are
supported, so that you can do everything a Turing machine can. It
doesn't mean there are no differences at all in the capabilities of
Turing complete languages. SK calculus is Turing complete, too.

> p.s. I wonder where Jon Harrop is. It'd almost be like that RAD vs.
> performance thread with him here, and I know he definitely doesn't
> agree that dynamic typing is better (although, if he doesn't respond,
> maybe he does? ;-)

I've been wondering why he's so silent, too. Maybe it's just that he
made all his points about static typing in RAD vs. performance, and
doesn't want to argue with me again, knowing that I'll never give in.
;-) Speaking of which, I'm not going to say more about heterogenous
lists in this thread; because I'm getting the feeling we're running in
circles. Seemingly, I believe I've given you an example of heterogenous
lists, and you don't believe so, which probably means we're using
different definitions. Or just not willing to admit we're wrong. :-)

Bob

---
The only thing you know for sure is that you never know anything for sure.


Curtis W

unread,
Aug 16, 2006, 9:42:47 AM8/16/06
to
> > > And now we return to the topic we were discussing: static vs. dynamic
> > > typing. Because, under dynamic typing, the elements of the list don't
> > > _have_ to implement a common interface; as long as you only ever use
> > > elements with operations that they support, you're fine (and you don't
> > > ever have to cast - after all, it's the values themselves that have the
> > > types, not the places that hold them).
> > No. The only way you can work on a truly heterogenous list, even in a
> > dynamic language, without causing an error is to do different things
> > depending on the capability of each element. The latter part requires
> > at least some commonality, whether it be finding its type or listing
> > its methods.
>
> Didn't my example demonstrate that, under dynamic typing, you can call
> type-specific functions on your values _without_ calling commonly
> supported methods first? Yes, you have to know what the type of your
> values is, to prevent type errors, but you can get this information from
> other sources than the values themselves, e.g. a format string.
Having an entry in a format string _is_ a commonality. If you don't
have one for one of the entries, it'll fail.

> > > In a statically typed language,
> > > you would be limited to those operations that are supported by all
> > > elements - which, for a truly heterogenous list, would be none, and
> > > thus, indeed, the list would be useless.
> > No. If that were true, you'd be saying statically typed languages
> > aren't turing complete. Statically typed languages are able to do
> > anything dynamic languages can, so I'm not sure where you're getting
> > this from.
>
> Being Turing complete just means that a certain set of operations are
> supported, so that you can do everything a Turing machine can. It
> doesn't mean there are no differences at all in the capabilities of
> Turing complete languages. SK calculus is Turing complete, too.

Sure it does. The whole point of being turing complete is that your
language can now do anything any other language can at runtime.
Obviously syntax differs, succinctness differs, but you can still do
exactly the same things. You can most certainly operate on elements of
a heterogenous list in statically typed languages, it just requires
some sort of casting or coercion mechanism.

> > p.s. I wonder where Jon Harrop is. It'd almost be like that RAD vs.
> > performance thread with him here, and I know he definitely doesn't
> > agree that dynamic typing is better (although, if he doesn't respond,
> > maybe he does? ;-)
>
> I've been wondering why he's so silent, too. Maybe it's just that he
> made all his points about static typing in RAD vs. performance, and
> doesn't want to argue with me again, knowing that I'll never give in.

Maybe. Hopefully it's just that he hasn't seen this thread yet :-) The
general discussion, if there ever was one, seems to be petering out.
Come to think of it, nobody seems to have commented on my opinion as a
whole, rather than nitpicking small parts of it.

> ;-) Speaking of which, I'm not going to say more about heterogenous
> lists in this thread; because I'm getting the feeling we're running in
> circles. Seemingly, I believe I've given you an example of heterogenous
> lists, and you don't believe so, which probably means we're using
> different definitions. Or just not willing to admit we're wrong. :-)

I'd like to say I have a rather compelling theoretical argument ;-)

cr88192

unread,
Aug 16, 2006, 11:15:37 AM8/16/06
to

"Curtis W" <cwar...@gmail.com> wrote in message
news:1155698054.0...@75g2000cwc.googlegroups.com...

what then of languages like Java?...

java is typically viewed as being a statically typed language, however, some
level of typechecking is done at runtime (checking that one class is derived
from another, ...).


>> the C/C++ notion is one possibility;
>> ocaml, haskell, ... have rather different definitions;
> No, they don't. They have different type systems in general, but
> they're all statically typed.
>

the semantics are different, and this is worth noting.

under your definitions, static typing is purely an implementation issue, and
no longer a semantics issue.

ok, why not then define a type-model, and a compiler, by which a language
like scheme could be termed statically typed?...

and then one goes and implements a variant of C where type-checking is done
at runtime.

and what then is the point of defining a particular language as staticly or
dynamically typed?...

what reason then does anyone have to argue the merits of one or the
other?...


my point here is that I feel you are generalizing beyond a level where
meaningful argument is possible. argument needs a solid basis on which to
argue...


>> so, artifically narrowing it, I consider C/C++ and that particular notion
>> of
>> static typing, because that is more likely what more are fammiliar with.
> It's not a "notion" of static typing; it is a weak, statically typed
> language. OCaml is a strong statically typed language. OCaml also
> happens to support a few other type constructs, which aren't usually
> relevant.
>

but, then again, they are very different in their treatment of types.

one uses declaration, and the other inference.

they are different in my oppinion, and this difference needs to be noted for
an argument of the sort presented in the toplevel post to hold any real
value.

after all, you were arguing about semantics, and not compiler
implementation, right?...


>> >> > The most common case by far is where the elements do actual share a
>> >> > conceptual commonality but aren't related in a class hierarchy. This
>> >> > can be readily seen in python, where tangible interfaces are frowned
>> >> > upon. A suitable static type system can, in fact, acheive the exact
>> >> > same goal with the same amount of typing through the use of a type
>> >> > inferencer and structural subtyping.
>> >> >
>> >>
>> >> but these are rare if one looks at most languages.
>> > This isn't a concrete comparison. Looking at most languages in a
>> > discussion like this would do nothing but skew the results.
>> >
>>
>> yet, it is "most languages" that people typically use as a basis for
>> understanding and comparison. one needs either specific examples, or a
>> specific definition.
> Static typing is well defined; if I had a different definition of the
> word I would've stated so.
>

but, it is a rather broad definition none the less.

the definition usually includes, not just the implementation (when
typechecking is done), but also the realization in terms of language
semantics. at this point, it is necessary to define in what way these
semantics are realised.


>> from the C perspective, the OCaml model looks like an optimization, and
>> fussier version, of dynamic typing.
> Not if they've ever programmed in OCaml it doesn't.
>

this is a side issue.

note that I said "from the C perspective", which does not imply any
fammiliarity with OCaml.

perspective is an inherently relativistic notion, and it is my opinion that
it is not useful to argue for a change of perspective in an argument based
on a particular perspective.

if I say "on earth during the day, the sky is blue", it is stated that the
perspective is on earth and during the day. one can argue "but not at
night", and this is true, but this is not part of the arguement.

so, specific semantics asside, from the C perspective, OCaml appears like an
optimization, and a fussy restriction, of an otherwise dynamicly-typed
language. the fact that typechecking is done at compile time is a side issue
here.


would you say it is impossible to write a version of an OCaml compiler that
does type checks at runtime, and would you say that this does not break your
definition?...


Curtis W

unread,
Aug 16, 2006, 11:47:18 AM8/16/06
to
When does java do this automatically?

> >> the C/C++ notion is one possibility;
> >> ocaml, haskell, ... have rather different definitions;
> > No, they don't. They have different type systems in general, but
> > they're all statically typed.
> >
>
> the semantics are different, and this is worth noting.

Not in a general debate like this.

> ok, why not then define a type-model, and a compiler, by which a language
> like scheme could be termed statically typed?...

It wouldn't be scheme any more.

> and what then is the point of defining a particular language as staticly or
> dynamically typed?...

It's a property that has immense effects on the rest of the language.
Gee, I wonder why it's so important.

> my point here is that I feel you are generalizing beyond a level where
> meaningful argument is possible. argument needs a solid basis on which to
> argue...

I'm not generalizing at all. I'm taking two specific properties of
languages and comparing them in isolation.

> >> so, artifically narrowing it, I consider C/C++ and that particular notion
> >> of
> >> static typing, because that is more likely what more are fammiliar with.
> > It's not a "notion" of static typing; it is a weak, statically typed
> > language. OCaml is a strong statically typed language. OCaml also
> > happens to support a few other type constructs, which aren't usually
> > relevant.
> >
>
> but, then again, they are very different in their treatment of types.

Not really.

> they are different in my oppinion, and this difference needs to be noted for
> an argument of the sort presented in the toplevel post to hold any real
> value.

Of course they're different, outside of the scope of static vs. dynamic
typing. It's a good thing that doesn't matter, since I'm only talking
about that precise quality and nothing more.


> > Static typing is well defined; if I had a different definition of the
> > word I would've stated so.
> >
>
> but, it is a rather broad definition none the less.

Of course it's a broad definition; you're dealing with a binary (or
close to it) property of all programming languages, what would you
expect?

> the definition usually includes, not just the implementation (when
> typechecking is done), but also the realization in terms of language
> semantics. at this point, it is necessary to define in what way these
> semantics are realised.

Not if you stick to comparing just the static and dynamic portions.
Certain comparisons do require the use of properties outside of that
scope, in which case the most ideal solution is used.

> >> from the C perspective, the OCaml model looks like an optimization, and
> >> fussier version, of dynamic typing.
> > Not if they've ever programmed in OCaml it doesn't.
> >
>
> this is a side issue.

And yours isn't?

> note that I said "from the C perspective", which does not imply any
> fammiliarity with OCaml.

Nor does it imply otherwise.

> so, specific semantics asside, from the C perspective, OCaml appears like an
> optimization, and a fussy restriction, of an otherwise dynamicly-typed
> language. the fact that typechecking is done at compile time is a side issue
> here.

Even if that's true, what's your point?

> would you say it is impossible to write a version of an OCaml compiler that
> does type checks at runtime, and would you say that this does not break your
> definition?...

It would be, since it wouldn't be OCaml any more.

cr88192

unread,
Aug 16, 2006, 8:35:25 PM8/16/06
to

"Curtis W" <cwar...@gmail.com> wrote in message
news:1155743238....@i3g2000cwc.googlegroups.com...

well, mostly when doing casts.
another example here is when dealing with objects in terms of interfaces.
...


>> >> the C/C++ notion is one possibility;
>> >> ocaml, haskell, ... have rather different definitions;
>> > No, they don't. They have different type systems in general, but
>> > they're all statically typed.
>> >
>>
>> the semantics are different, and this is worth noting.

> Not in a general debate like this.
>

I argue that a truely "general" debate about this topic is not reasonable,
and that any such argument requires a basis in terms of particular features
or semantics.


>> ok, why not then define a type-model, and a compiler, by which a language
>> like scheme could be termed statically typed?...
> It wouldn't be scheme any more.
>

but, if the type model is such that the code runs unmodified, it will still
conform with the spec, and still behave just as before.

I will assert that any code that is provably valid will have a possible
representation in terms of a static type model (even if deriving or
compiling using this model is impractical).

now, it seems you are saying that the definition of a languages' typedness,
and thus its definition as a language, depends on the inner workings of the
compiler, and is not a product of the language itself.

I will state here that I disagree.


>> and what then is the point of defining a particular language as staticly
>> or
>> dynamically typed?...
> It's a property that has immense effects on the rest of the language.
> Gee, I wonder why it's so important.
>

but, here, you are also mitigating the value of such semantics, claiming
this as being a "general" arguement, rather than an arguement based on the
particular semantics which are effected by such a decision.

there is nothing provable in saying that a particularly lazy implementation
of a static language can do checks at runtime, or that a particularly clever
compiler for a dynamic language can't accomplish all typechecks at compile
time (at least in some/many cases), as such, viewing it as solely a property
of the implementation is pointless, because we will have cases where a
fundamental aspect of the definition of language depends solely on the
program being compiled.

such a claim is unreasonable. as such, it would seem this is arguement would
be doomed to become more an argument over philosophy (the philosophy of
static typing, and the philosophy of dynamic typing), rather than an
argument based around static vs. dynamic typing, which imo depends on the
specifics of the implementations in question, and thus, more concrete,
rather than abstract, definitions.


>> my point here is that I feel you are generalizing beyond a level where
>> meaningful argument is possible. argument needs a solid basis on which to
>> argue...
> I'm not generalizing at all. I'm taking two specific properties of
> languages and comparing them in isolation.
>

and this is part of what I am complaining about.
languages are, and implementations are, a mass of features that interoperate
in a particular way.

arguing about things in isolation, and based on particularly shaky abstract
definitions, does not seem to be a meaningful approach imo.


>> >> so, artifically narrowing it, I consider C/C++ and that particular
>> >> notion
>> >> of
>> >> static typing, because that is more likely what more are fammiliar
>> >> with.
>> > It's not a "notion" of static typing; it is a weak, statically typed
>> > language. OCaml is a strong statically typed language. OCaml also
>> > happens to support a few other type constructs, which aren't usually
>> > relevant.
>> >
>>
>> but, then again, they are very different in their treatment of types.
> Not really.
>

I will say that they are.

declarations vs inferrence is not exactly a trivial difference, nor is
types-by-definition vs types-by-patterns a trivial difference.

though both statically typed, however, the means by which static typing is
realized are very different, and even the definition type veries by a wide
degree.

in one case, type flows from the definitions, through the code, and back
into further definitions. all is well so long as something doesn't try to go
into a place it doesn't fit.

in the other, types flow from the literals and operations, and the same
function will have different type definitions (in the concrete sense)
depending on how it is called.


and these differences are dealt with simply by stating that they don't
matter?...

I disagree.


>> they are different in my oppinion, and this difference needs to be noted
>> for
>> an argument of the sort presented in the toplevel post to hold any real
>> value.
> Of course they're different, outside of the scope of static vs. dynamic
> typing. It's a good thing that doesn't matter, since I'm only talking
> about that precise quality and nothing more.

aka: philosophy...


>> > Static typing is well defined; if I had a different definition of the
>> > word I would've stated so.
>> >
>>
>> but, it is a rather broad definition none the less.

> Of course it's a broad definition; you're dealing with a binary (or
> close to it) property of all programming languages, what would you
> expect?
>

so, it can be said that it is a definition of the language, as to how it is
implemented. how then do we prove that all implementations of a language
follows the definition given of the language, thus making it true?...

this definition is itself based on a large number of other factors, which in
themselves only change the probability of truth, but are in themselves
unable to prove it.

my stance is that, this property, itself, is a product of these other
factors, and not that these other factors derive from this property.


>> the definition usually includes, not just the implementation (when
>> typechecking is done), but also the realization in terms of language
>> semantics. at this point, it is necessary to define in what way these
>> semantics are realised.
> Not if you stick to comparing just the static and dynamic portions.
> Certain comparisons do require the use of properties outside of that
> scope, in which case the most ideal solution is used.
>

>> >> from the C perspective, the OCaml model looks like an optimization,
>> >> and
>> >> fussier version, of dynamic typing.
>> > Not if they've ever programmed in OCaml it doesn't.
>> >
>>
>> this is a side issue.
> And yours isn't?
>

I am attempting to point out something here:
you seem to be attempting to argue based on the provable nature of an
abstract concept, in isolation, and I am stating that, in isolation, this
concept does not hold.


>> note that I said "from the C perspective", which does not imply any
>> fammiliarity with OCaml.
> Nor does it imply otherwise.
>

yes, however any such fammiliarity is necissarily ignored when arguing from
a particular perspective.


>> so, specific semantics asside, from the C perspective, OCaml appears like
>> an
>> optimization, and a fussy restriction, of an otherwise dynamicly-typed
>> language. the fact that typechecking is done at compile time is a side
>> issue
>> here.
> Even if that's true, what's your point?
>

point given previously...

apart from a set of funky restrictions, from the C perspective, these two
definitions can't be distinguished. static or dynamic thus depends solely on
the implementation, and we can only infer (from the semantics and nature of
the restrictions imposed) that the implementation is statically typed.

and from the other, we can argue that C's treatment of pointers, for
example, would seem to imply some form of dynamic checking (if there is any
hope of type safety...). there is no way to prove, for example, that an
'int' variable is actually a static type, and not just a hint to the
compiler as to what representation would be most optimal (expressions being
checked and marshalled to this representation when being assigned).
we can only infer that C is statically typed due to the absense of any more
generic types, and the absence of any ability to check the present type of a
value or expression...

and, I will argue, it is this which defines static vs dynamic, and not the
inverse.


>> would you say it is impossible to write a version of an OCaml compiler
>> that
>> does type checks at runtime, and would you say that this does not break
>> your
>> definition?...
> It would be, since it wouldn't be OCaml any more.
>

you say this...

I say I disagree.


I say a language is a language so long as it is in every way compatible with
that language, and not simply a matter of implementation or definition.

what if we conform with every definition of a language, but vary in the ways
only implied, and result in an implementation which is incompatible. what
then?... do we say all the programs are broken and that anyone who disagrees
here is irrelevant. I wouldn't think so...


Curtis W

unread,
Aug 16, 2006, 10:54:28 PM8/16/06
to
Actually, my definitions of static and dynamic typing were a bit of a
simplification. Possibly the easiest way to figure out what people mean
by something is to look at the results of their classifications, e.g.
which languages are considered static and which are considered dynamic,
and compare the features that they have in common. If you really want a
textual definition, I suppose the following should suffice:

A language can be considered statically typed when code is required to
be correctly typed before being run. If it is not, an error will be
thrown and it cannot be compiled or run. As such, the
compiler/interpreter must have a typed version of the program, whether
it be from the programmer directly or from an inferencer, although
having type inference or type annotations doesn't necessarily mean a
language is statically typed.

Dynamically typed languages postpone everything until absolutely
necessary, including type checking, method lookup, etc. Compile time
errors or "possible errors" are strictly forbidden, barring what is
necessary to compile a program, e.g. syntax errors are ok.

Drawing from this, it should be obvious that code written in one
version will not work if the language is changed to use a different
kind of type system.

The second issue in your post is that discussing dynamic/static typing
brings the rest of the type system into the argument. For this to be
true, the other concepts in the type system would have to be
inseparably related to either dynamic or static typing, which certainly
is not the case. OCaml is a great example simply because of the large
amount of different concepts it has in its type system. Type inference
is possibly the most popular, but this isn't related to static typing
at all (indeed, type inference can be used for optimization purposes in
compilers for dynamically typed languages). Union types and structural
subtyping are two others, but these too aren't linked directly with
static typing, especially considering that dynamic typing implies
structural subtyping.

cr88192

unread,
Aug 17, 2006, 7:24:50 AM8/17/06
to

"Curtis W" <cwar...@gmail.com> wrote in message
news:1155783268.6...@m73g2000cwd.googlegroups.com...

> Actually, my definitions of static and dynamic typing were a bit of a
> simplification. Possibly the easiest way to figure out what people mean
> by something is to look at the results of their classifications, e.g.
> which languages are considered static and which are considered dynamic,
> and compare the features that they have in common. If you really want a
> textual definition, I suppose the following should suffice:
>
> A language can be considered statically typed when code is required to
> be correctly typed before being run. If it is not, an error will be
> thrown and it cannot be compiled or run. As such, the
> compiler/interpreter must have a typed version of the program, whether
> it be from the programmer directly or from an inferencer, although
> having type inference or type annotations doesn't necessarily mean a
> language is statically typed.
>

yes, I can agree with this.


> Dynamically typed languages postpone everything until absolutely
> necessary, including type checking, method lookup, etc. Compile time
> errors or "possible errors" are strictly forbidden, barring what is
> necessary to compile a program, e.g. syntax errors are ok.
>

they don't always postpone everything as much as possible.
often, some level of type inference will be used, when reasonable, in basic
attempts to optimize the performance of compiled code.


> Drawing from this, it should be obvious that code written in one
> version will not work if the language is changed to use a different
> kind of type system.
>

yes, within limits.


> The second issue in your post is that discussing dynamic/static typing
> brings the rest of the type system into the argument. For this to be
> true, the other concepts in the type system would have to be
> inseparably related to either dynamic or static typing, which certainly
> is not the case. OCaml is a great example simply because of the large
> amount of different concepts it has in its type system. Type inference
> is possibly the most popular, but this isn't related to static typing
> at all (indeed, type inference can be used for optimization purposes in
> compilers for dynamically typed languages). Union types and structural
> subtyping are two others, but these too aren't linked directly with
> static typing, especially considering that dynamic typing implies
> structural subtyping.
>

I am not entirely sure there is understanding here.

I am not saying that the features themselves are necissarily either static
or dynamic in nature. what I am saying is that such a distinction does not
exist in a purely fundamental sense, but that it arrises out of the
particular mass combination of features, but mostly as a "path of least
resistance" type feature, rather than any fundamental or golden rule.

I will argue that, with effort, one can make a dynamic implementation for an
otherwise static language, and with similar effort, can write a largely
static implementation of a dynamic language.

and this is where the details come in:
features that have a naturally "static" bias (for example, type declarations
or inference, a specific notion of type behavior, ...) will tend to imply a
natural bias that the implementation will use static typing, and is
classifiable as a static language;
wheras, a language with many dynamic features, will tend to imply an
implementation which uses dynamic typing, and is classifiable as a dynamic
language;
and in the middle category, we have soft typing and friends...


I hold similar views about functional, imperative, concurrent, and
object-oriented languages. no one can seem to fully agree as to what exactly
all these terms refer to, or what fundamentally defines them, yet most have
a worthwhile understanding as to the kinds of things these terms imply, and
the various ways in which these concepts can be realized.


all this is by no means an absolute...


Dr.Ruud

unread,
Aug 17, 2006, 5:54:12 PM8/17/06
to
Curtis W schreef:

> Actually, my definitions of static and dynamic typing were a bit of a
> simplification. Possibly the easiest way to figure out what people
> mean by something is to look at the results of their classifications,
> e.g. which languages are considered static and which are considered
> dynamic, and compare the features that they have in common.

Why switch from xxx type systems to xxx languages?

> If you
> really want a textual definition, I suppose the following should
> suffice:
>
> A language can be considered statically typed when code is required to
> be correctly typed before being run. If it is not, an error will be
> thrown and it cannot be compiled or run. As such, the
> compiler/interpreter must have a typed version of the program, whether
> it be from the programmer directly or from an inferencer, although
> having type inference or type annotations doesn't necessarily mean a
> language is statically typed.

How about languages that have both aearly and late binding, both
statical and dynamical typing? If you only use the early binding, the
statical typing, it works like a statical typed 'language'. (I don't
know any language that is 'exclusively statical typed'.)

--
Affijn, Ruud

"Gewoon is een tijger."


Curtis W

unread,
Aug 17, 2006, 6:47:53 PM8/17/06
to
> > Actually, my definitions of static and dynamic typing were a bit of a
> > simplification. Possibly the easiest way to figure out what people
> > mean by something is to look at the results of their classifications,
> > e.g. which languages are considered static and which are considered
> > dynamic, and compare the features that they have in common.
>
> Why switch from xxx type systems to xxx languages?
I'm not sure what you're trying to say. What is 'xxx'?

> > If you
> > really want a textual definition, I suppose the following should
> > suffice:
> >
> > A language can be considered statically typed when code is required to
> > be correctly typed before being run. If it is not, an error will be
> > thrown and it cannot be compiled or run. As such, the
> > compiler/interpreter must have a typed version of the program, whether
> > it be from the programmer directly or from an inferencer, although
> > having type inference or type annotations doesn't necessarily mean a
> > language is statically typed.
>
> How about languages that have both aearly and late binding, both
> statical and dynamical typing? If you only use the early binding, the
> statical typing, it works like a statical typed 'language'. (I don't
> know any language that is 'exclusively statical typed'.)

What language does this?

Dr.Ruud

unread,
Aug 17, 2006, 8:43:44 PM8/17/06
to
Curtis W schreef:

> Ruud:
>> Curtis:

[Attribution dammit! Also put a blank line between the old text and your
reply.]

>>> Actually, my definitions of static and dynamic typing were a bit of
>>> a simplification. Possibly the easiest way to figure out what people
>>> mean by something is to look at the results of their
>>> classifications, e.g. which languages are considered static and
>>> which are considered dynamic, and compare the features that they
>>> have in common.
>>
>> Why switch from xxx type systems to xxx languages?
>
> I'm not sure what you're trying to say. What is 'xxx'?

s!xxx!static/dynamic!g


>>> A language can be considered statically typed when code is required
>>> to be correctly typed before being run. If it is not, an error will
>>> be thrown and it cannot be compiled or run. As such, the
>>> compiler/interpreter must have a typed version of the program,
>>> whether it be from the programmer directly or from an inferencer,
>>> although having type inference or type annotations doesn't
>>> necessarily mean a language is statically typed.
>>
>> How about languages that have both aearly and late binding, both
>> statical and dynamical typing? If you only use the early binding, the
>> statical typing, it works like a statical typed 'language'.
>

> What language does this?


For example Visual Basic, which has "Variant", and "!" for late binding,
both of which you don't have to use.
There are still dynamics left, like

Dim i as Integer
Dim s as String
s = "41"
i = 1 + s

Curtis W

unread,
Aug 17, 2006, 10:25:17 PM8/17/06
to

Dr.Ruud wrote:
> Curtis W schreef:
>
> > Ruud:
> >> Curtis:
>
> [Attribution dammit! Also put a blank line between the old text and your
> reply.]
>
> >>> Actually, my definitions of static and dynamic typing were a bit of
> >>> a simplification. Possibly the easiest way to figure out what people
> >>> mean by something is to look at the results of their
> >>> classifications, e.g. which languages are considered static and
> >>> which are considered dynamic, and compare the features that they
> >>> have in common.
> >>
> >> Why switch from xxx type systems to xxx languages?
> >
> > I'm not sure what you're trying to say. What is 'xxx'?
>
> s!xxx!static/dynamic!g
I'm not "switching." I was using the concept of comparing languages to
help guide him in a direction where he could figure out what
static/dynamic typing meant himself.

> >>> A language can be considered statically typed when code is required
> >>> to be correctly typed before being run. If it is not, an error will
> >>> be thrown and it cannot be compiled or run. As such, the
> >>> compiler/interpreter must have a typed version of the program,
> >>> whether it be from the programmer directly or from an inferencer,
> >>> although having type inference or type annotations doesn't
> >>> necessarily mean a language is statically typed.
> >>
> >> How about languages that have both aearly and late binding, both
> >> statical and dynamical typing? If you only use the early binding, the
> >> statical typing, it works like a statical typed 'language'.
> >
> > What language does this?
>
>
> For example Visual Basic, which has "Variant", and "!" for late binding,
> both of which you don't have to use.
> There are still dynamics left, like

Variants, if I understand what you're talking about correctly, do not
make a language dynamically typed. I don't know what the second example
is, so I can't really comment on that.

> Dim i as Integer
> Dim s as String
> s = "41"
> i = 1 + s

This is an example of weak typing, not dynamic typing.

George Neuner

unread,
Aug 17, 2006, 11:38:34 PM8/17/06
to
On 17 Aug 2006 15:47:53 -0700, "Curtis W" <cwar...@gmail.com> wrote:

> Dr. Ruud wrote:
>
>> How about languages that have both early and late binding, both


>> statical and dynamical typing? If you only use the early binding, the
>> statical typing, it works like a statical typed 'language'.
>

>What language does this?

Dylan comes pretty close to this ideal. It has it own warts though.


George
--
for email reply remove "/" from address

cr88192

unread,
Aug 18, 2006, 12:15:42 AM8/18/06
to

"Curtis W" <cwar...@gmail.com> wrote in message
news:1155867917....@i42g2000cwa.googlegroups.com...

>
> Dr.Ruud wrote:
>> Curtis W schreef:
>>
>> > Ruud:
>> >> Curtis:
>>
>> [Attribution dammit! Also put a blank line between the old text and your
>> reply.]
>>
>> >>> Actually, my definitions of static and dynamic typing were a bit of
>> >>> a simplification. Possibly the easiest way to figure out what people
>> >>> mean by something is to look at the results of their
>> >>> classifications, e.g. which languages are considered static and
>> >>> which are considered dynamic, and compare the features that they
>> >>> have in common.
>> >>
>> >> Why switch from xxx type systems to xxx languages?
>> >
>> > I'm not sure what you're trying to say. What is 'xxx'?
>>
>> s!xxx!static/dynamic!g
> I'm not "switching." I was using the concept of comparing languages to
> help guide him in a direction where he could figure out what
> static/dynamic typing meant himself.
>

I don't feel I was the only one arguing with your definitions here...

actually, if you ask me, nothing clearly defined exists in a purely
fundamental sense, rather, such notions are abstractions. general properties
will form the basis of such ideas, and those ideas reflect reality, however,
these ideas neither exist on their own nor are they completely seperable
from the things for which they apply (any attempt to use an idea in a
different context thus requires a mapping of the idea to that context, at
the same time effectively creating an associative mapping between these
contexts).

now, it is my interpretation that you were attempting to argue the opposite
direction, that the idea itself was somehow fundamental and that reality
necissarily emerges from the idea (one defines a language as statically
typed, semantics are built around this idea, and the implementation is built
around these semantics).


now, I will say I know what both static and dynamic typing are, but the
difference is in terms of how such concepts are realised...


I say it is based on a product of the various design features and the
implementation, but neither by itself. a person will say "I will implement a
statically typed language", and will choose semantics consistent with this
statement, and implement a language consistent with this idea.
however, in effect, this changes little, it is the semantics and the
implementation that became real, and the idea is manifested by them, but the
idea as such is still an idea and not a thing in itself.


what I gathered from your side was the claim that it was a fundamental
property of a language that was invariantly represented in the
implementation.


I argued against this on the grounds that both static and dynamic typing are
capable of representing each other, and as such it is possible to break this
definition while still implementing the same language with the same rules
(the only major difference here being that this is less practical, not based
on some definition, but because a design intended for one case makes much
less sense in the other).

the difference it seems, imo, is more one of philosophy than anything
else...


>> >>> A language can be considered statically typed when code is required
>> >>> to be correctly typed before being run. If it is not, an error will
>> >>> be thrown and it cannot be compiled or run. As such, the
>> >>> compiler/interpreter must have a typed version of the program,
>> >>> whether it be from the programmer directly or from an inferencer,
>> >>> although having type inference or type annotations doesn't
>> >>> necessarily mean a language is statically typed.
>> >>
>> >> How about languages that have both aearly and late binding, both
>> >> statical and dynamical typing? If you only use the early binding, the
>> >> statical typing, it works like a statical typed 'language'.
>> >
>> > What language does this?
>>
>>
>> For example Visual Basic, which has "Variant", and "!" for late binding,
>> both of which you don't have to use.
>> There are still dynamics left, like

> Variants, if I understand what you're talking about correctly, do not
> make a language dynamically typed. I don't know what the second example
> is, so I can't really comment on that.
>

in my definitions, VB is soft typed.

basically, variant will hold whatever type you try to put in it...


>> Dim i as Integer
>> Dim s as String
>> s = "41"
>> i = 1 + s
> This is an example of weak typing, not dynamic typing.
>

I don't think it is that either.

VB likes to marshal types in this case, so it would convert the string to a
number and give a result of 42.


then again, I am no expert in VB here either for that matter...

Robbert Haarman

unread,
Aug 18, 2006, 10:16:59 AM8/18/06
to
On Thu, Aug 17, 2006 at 09:24:50PM +1000, cr88192 wrote:
>
> "Curtis W" <cwar...@gmail.com> wrote in message
> news:1155783268.6...@m73g2000cwd.googlegroups.com...
> >

cr88192,

I have the feeling you are not separating semantics and implementation;
theory and practice, to the degree that Curtis and I are. While you are
right that dynamically typed languages don't have to postpone absolutely
all type-related work to run time, this is what happens _semantically_,
or _theoretically_. The implementation, the actualy, practical code of
the compiler or interpreter may do things any way it pleases, as long as
it doesn't affect the semantics of your programs (although some effects
on the semantics are often accepted in practice, just to complicate
things). As an example, consider

greeting = "Hello, world!"
print greeting
a = greeting / 12
print a

Now, suppose that the operation of dividing a string by a number is not
defined in this language. If the language is statically typed, this
program will never compile or run, because it contains a type error, and
static typing dictates that such programs be rejected at compile time.
Dynamic typing dictates that the program is allowed to run, alttough, of
course, it will abort with an error as soon as the third line is
reached.

All this says nothing about the compiler being allowed to optimize the
program, e.g. by taking advantage of the knowledge that greeting
contains a string, and thus its value does not have to be converted to a
string before it can be printed. It also does not (at least using my
definition) preclude the compiler from emitting a warning about the
offending third line. So, a lot of work can be done at compile time...as
long as the program does compile and run (until the third line is
reached), because, otherwise, it would not be dynamic typing. The
semantics of the language (if dynamically typed) say that the program
must print "Hello, world!", and then abort, and so, as long as the
implementation ensures this, it is a correct implementation of the
language.

As for how the language designers come to the decission of making the
language statically or dynamically typed (or some hybrid form, or
anything else you can think of), I have no idea and will make no claims
about it. Nevertheless, static typing or dynamic typing are fundamental
features of a language, that can be examined in their own right; just
like other features, for example, if the language has a built-in +
operator or not, and if a language's print function (assuming one
exists) appends a newline or not.

Regards,

Bob

---
The optimist proclaims that we live in the best of all possible worlds,
and the pessimist fears this is true.


Curtis W

unread,
Aug 18, 2006, 10:20:02 AM8/18/06
to
> >> Dim i as Integer
> >> Dim s as String
> >> s = "41"
> >> i = 1 + s
> > This is an example of weak typing, not dynamic typing.
> >
>
> I don't think it is that either.
>
> VB likes to marshal types in this case, so it would convert the string to a
> number and give a result of 42.
>
>
> then again, I am no expert in VB here either for that matter...
That's the definition of weak typing.

Concering the rest of your post: what is your opposition to this
discussion? Do you feel that it's somehow impossible to compare static
and dynamic typing because of some dependency issue with other parts of
the language? If so, I can safely say that it's not the case; if you
still continue to think this, at least read over my original post and
point out where this matters.

Curtis W

unread,
Aug 18, 2006, 10:22:48 AM8/18/06
to
Do you have a specific example of this? I'm not very familar with
Dylan, so I don't really know what you mean.

Robbert Haarman

unread,
Aug 18, 2006, 10:30:31 AM8/18/06
to
On Fri, Aug 18, 2006 at 02:43:44AM +0200, Dr.Ruud wrote:
>
> For example Visual Basic, which has "Variant", and "!" for late binding,
> both of which you don't have to use.
> There are still dynamics left, like
>
> Dim i as Integer
> Dim s as String
> s = "41"
> i = 1 + s

Is that dynamic typing, or is that a + operator defined so that it
accepts strings as arguments? C++ isn't dynamically typed, but you can
certainly write something like (please excuse any errors in my C++):

int add(int x, int y) { return x + y; }

int add(int x, string y) {
istringstream s(y);
int n;
s >> n;
return x + y;
}

C++ also supports operator overloading (so you could do the same for the
+ operator, rather than defining a new function), but not for built-in
types, AFAIK.

Regards,

Bob

---
In theory there is no difference between theory and practice, but in practice
there is.


Robbert Haarman

unread,
Aug 18, 2006, 10:50:05 AM8/18/06
to
On Wed, Aug 16, 2006 at 06:42:47AM -0700, Curtis W wrote:
> > > > And now we return to the topic we were discussing: static vs. dynamic
> > > > typing. Because, under dynamic typing, the elements of the list don't
> > > > _have_ to implement a common interface; as long as you only ever use
> > > > elements with operations that they support, you're fine (and you don't
> > > > ever have to cast - after all, it's the values themselves that have the
> > > > types, not the places that hold them).
> > > No. The only way you can work on a truly heterogenous list, even in a
> > > dynamic language, without causing an error is to do different things
> > > depending on the capability of each element. The latter part requires
> > > at least some commonality, whether it be finding its type or listing
> > > its methods.
> >
> > Didn't my example demonstrate that, under dynamic typing, you can call
> > type-specific functions on your values _without_ calling commonly
> > supported methods first? Yes, you have to know what the type of your
> > values is, to prevent type errors, but you can get this information from
> > other sources than the values themselves, e.g. a format string.
> Having an entry in a format string _is_ a commonality.

Not in the operations that are available on the values you put in the
list. That format string also doesn't affect what types of values I can
store in the list, neither under static, nor under dynamic typing (it's
possible to devise mechanisms by which format strings do have that
property (e.g. sbcl checks arguments against format strings), but assume
that this is a format string that I made up out of thin air and that
doesn't have any significance to the type checker).

> If you don't have one for one of the entries, it'll fail.

It won't _necessarily_ fail, and that's why it's interesting: under
static typing, it will be rejected because it's not proven that the
types are correct, but under dynamic typing it will run, as long as the
types actually are correct (in both cases, correct. w.r.t. the
operations performed on the values).

> > > > In a statically typed language,
> > > > you would be limited to those operations that are supported by all
> > > > elements - which, for a truly heterogenous list, would be none, and
> > > > thus, indeed, the list would be useless.
> > > No. If that were true, you'd be saying statically typed languages
> > > aren't turing complete. Statically typed languages are able to do
> > > anything dynamic languages can, so I'm not sure where you're getting
> > > this from.
> >
> > Being Turing complete just means that a certain set of operations are
> > supported, so that you can do everything a Turing machine can. It
> > doesn't mean there are no differences at all in the capabilities of
> > Turing complete languages. SK calculus is Turing complete, too.
> Sure it does. The whole point of being turing complete is that your
> language can now do anything any other language can at runtime.
> Obviously syntax differs, succinctness differs, but you can still do
> exactly the same things. You can most certainly operate on elements of
> a heterogenous list in statically typed languages, it just requires
> some sort of casting or coercion mechanism.

Look, the definition of Turing completeness is being able to emulate
(produce the same outputs, given the same inputs) a Turing machine (when
given enough memory; the Turing machine has an infinite amount of that).
It says nothing about being able to do everything another language can
do. In Perl, I can add an integer to a string that happens to contain a
number, in C I can't. Still, both are Turing complete. Turing
completeness says nothing about heterogenous lists, it doesn't even
require your language to have a notion of types or lists.

> Maybe. Hopefully it's just that he hasn't seen this thread yet :-) The
> general discussion, if there ever was one, seems to be petering out.
> Come to think of it, nobody seems to have commented on my opinion as a
> whole, rather than nitpicking small parts of it.

If I haven't commented on the larger picture you presented, that's
because I agree with it. I think the presentation of the issue you gave
at the beginning is clear and correct.

Regards,

Bob

---
Cats land on their feet. Toast lands jellyside down. A cat glued to some
jelly toast will hover in quantum indecision.

(seen on slashdot)


Curtis W

unread,
Aug 18, 2006, 1:39:39 PM8/18/06
to
Yes, I know, but each element requires an entry in the format string
for it to work. Since this is required of all entries in the list no
matter what type they are, it can be seen as a commonality, so it's not
a heterogenous list.

> > If you don't have one for one of the entries, it'll fail.
>
> It won't _necessarily_ fail, and that's why it's interesting: under
> static typing, it will be rejected because it's not proven that the
> types are correct, but under dynamic typing it will run, as long as the
> types actually are correct (in both cases, correct. w.r.t. the
> operations performed on the values).

Let's take an example. Let's say the user enters the following for
'foo':

['iis', '1', '2', 'foo', 'bar']

_That_ is a heterogenous list, because there are no commonalities
between elements--the last one doesn't have an entry in the format
string. Are you telling me that won't produce an error at runtime when
you try and apply the algorithm to it? If it doesn't, I'd like to know
what language you're using so I can stay far away from it.

The property of turing completeness that's applicable here is that any
turing complete language can implement any other turing complete
language. For example, the perl interpreter is written in C, so it is
possible to add an integer to a string from C, even if it means
implementing a perl interpreter (it doesn't). You might make the case
that it's not nearly as easy in C as it is in perl, but then this isn't
about easy of use, but rather whether it's possible.

> If I haven't commented on the larger picture you presented, that's
> because I agree with it. I think the presentation of the issue you gave
> at the beginning is clear and correct.

Well that's always nice to hear :-)

Curtis W

unread,
Aug 18, 2006, 1:42:47 PM8/18/06
to

Robbert Haarman wrote:
> On Fri, Aug 18, 2006 at 02:43:44AM +0200, Dr.Ruud wrote:
> >
> > For example Visual Basic, which has "Variant", and "!" for late binding,
> > both of which you don't have to use.
> > There are still dynamics left, like
> >
> > Dim i as Integer
> > Dim s as String
> > s = "41"
> > i = 1 + s
>
> Is that dynamic typing, or is that a + operator defined so that it
> accepts strings as arguments? C++ isn't dynamically typed, but you can
> certainly write something like (please excuse any errors in my C++):
That's visual basic, which is statically typed. The specific property
shown there is called weak typing, which is basically when a language
has liberal automatic coercion policies. As you point out, it's
possible to do this in any language that supports operator overloading,
so the idea of weak typing really only reflects the default state of
the language.

Curtis W

unread,
Aug 18, 2006, 1:43:36 PM8/18/06
to

Robbert Haarman wrote:
> On Fri, Aug 18, 2006 at 02:43:44AM +0200, Dr.Ruud wrote:
> >
> > For example Visual Basic, which has "Variant", and "!" for late binding,
> > both of which you don't have to use.
> > There are still dynamics left, like
> >
> > Dim i as Integer
> > Dim s as String
> > s = "41"
> > i = 1 + s
>
> Is that dynamic typing, or is that a + operator defined so that it
> accepts strings as arguments? C++ isn't dynamically typed, but you can
> certainly write something like (please excuse any errors in my C++):

George Neuner

unread,
Aug 18, 2006, 5:13:56 PM8/18/06
to
On 18 Aug 2006 07:22:48 -0700, "Curtis W" <cwar...@gmail.com> wrote:

> George Neuner wrote:


>> Curtis W wrote:
>>> Dr. Ruud wrote:
>>>
>>>> How about languages that have both early and late binding, both
>>>> statical and dynamical typing? If you only use the early binding, the
>>>> statical typing, it works like a statical typed 'language'.
>>>
>>> What language does this?
>
>> Dylan comes pretty close to this ideal. It has it own warts though.
>

>Do you have a specific example of this? I'm not very familar with
>Dylan, so I don't really know what you mean.

In Dylan all data is a subclass of object and the default is to use
dynamic typing as in Lisp/Scheme. However, you can add type
annotations, which the compiler will enforce.

Whether the enforcement is performed at compile time or at run time
depends on the program and on the compiler options. If you assign an
unqualified (unannotated) object to a typed variable/field, the
compiler must use a runtime check (or fail). The more annotations the
program contains, the more the compiler checks and enforces
statically. This gives you freedom to avoid using types when you
aren't sure of them, and gives enhanced performance wherever you can
lock them down.

The big wart is that there is no type inference - checking is based on
program annotation.

Curtis W

unread,
Aug 18, 2006, 5:48:37 PM8/18/06
to
Ok, thanks for the clarification. It sounds like that would be
considered soft typing, which is another matter entirely. I tend to
just lump that in with static typing, since it still goes against the
theory behind dynamic typing, just to a lesser degree.

(To those of you who might be curious: I used to be a soft typing
supporter, until I realized there's no reason not to just use dynamic
typing.)

cr88192

unread,
Aug 18, 2006, 9:19:41 PM8/18/06
to

"Curtis W" <cwar...@gmail.com> wrote in message
news:1155910802.5...@p79g2000cwp.googlegroups.com...

>> >> Dim i as Integer
>> >> Dim s as String
>> >> s = "41"
>> >> i = 1 + s
>> > This is an example of weak typing, not dynamic typing.
>> >
>>
>> I don't think it is that either.
>>
>> VB likes to marshal types in this case, so it would convert the string to
>> a
>> number and give a result of 42.
>>
>>
>> then again, I am no expert in VB here either for that matter...
> That's the definition of weak typing.
>

my definition of weak typing is more that typechecking is not done, so, for
example, adding a string and a number gives you a garbage number as a
result, a modified pointer, ...

marshalling a string to a number in order to perform an addition classifies,
imo, as dynamic typing, however it also classifies, imo, as a rather dubious
choice in language semantics...

> Concering the rest of your post: what is your opposition to this
> discussion? Do you feel that it's somehow impossible to compare static
> and dynamic typing because of some dependency issue with other parts of
> the language? If so, I can safely say that it's not the case; if you
> still continue to think this, at least read over my original post and
> point out where this matters.
>

well, it was not your original post where the problem arose, but in the
posts following it.
the other part of this response here was a slight annoyance, partly by
gaining a sense of condescension (however, I can't claim complete innocence
of this either by any means).

I am not saying meaningful discussion is not possible, what I am saying is
that meaningful abstract discussion is not possible (and also that I feel
that some of your reasoning doesn't entirely hold up from a logic-based
perspective, or at least not from what I can tell...).

they seemed to lack a basis in experienced (implementational) reality,
instead following what seemed to be a philosophical basis, and personally I
have a few complaints about abstract/philosophical reasoning, or at least
when I feel there is insufficient basis in either reality or some other
recognizable framework...

or such...

but, I am still more than willing enough to argue about implementation
issues...


cr88192

unread,
Aug 18, 2006, 10:58:05 PM8/18/06
to

"Robbert Haarman" <comp.la...@inglorion.net> wrote in message
news:2006081814...@morgenes.shire.sytes.net...

> On Thu, Aug 17, 2006 at 09:24:50PM +1000, cr88192 wrote:
>>
>> "Curtis W" <cwar...@gmail.com> wrote in message
>> news:1155783268.6...@m73g2000cwd.googlegroups.com...
>> >
<snip>

yes, I will acknowlege this point.

my mindset, quite the opposite of some others it seems, will often make few
abstractions, and will often cause me to more often grind through a good
amount more information before comming up with a conclusion.

however, I don't personally feel this particularly degrades my ability to
code or argue about things. I still use theories and abstractions as well,
however, I limit my understanding to them as being such, and don't claim
that they are facts, as that is imo an unjustified claim...


as for the example, what happens when the third line is reached?...
this is an implementation detail, many language implementations will raise
an exception, and many will abort...


> All this says nothing about the compiler being allowed to optimize the
> program, e.g. by taking advantage of the knowledge that greeting
> contains a string, and thus its value does not have to be converted to a
> string before it can be printed. It also does not (at least using my
> definition) preclude the compiler from emitting a warning about the
> offending third line. So, a lot of work can be done at compile time...as
> long as the program does compile and run (until the third line is
> reached), because, otherwise, it would not be dynamic typing. The
> semantics of the language (if dynamically typed) say that the program
> must print "Hello, world!", and then abort, and so, as long as the
> implementation ensures this, it is a correct implementation of the
> language.
>

yes, this is reasonable.

I had failed to define the case where a purely static implementation is not
possible (eg: in the presence of either undefined cases or arrival of
external input, ...). that is partly why I wrote "largely static"...


> As for how the language designers come to the decission of making the
> language statically or dynamically typed (or some hybrid form, or
> anything else you can think of), I have no idea and will make no claims
> about it. Nevertheless, static typing or dynamic typing are fundamental
> features of a language, that can be examined in their own right; just
> like other features, for example, if the language has a built-in +
> operator or not, and if a language's print function (assuming one
> exists) appends a newline or not.
>

yes, agreed here.

in my case, most compilers I have written have been dynamically typed.
I had tried (but failed) in a few efforts to write statically typed
languages (I suspect partly because I was trying to keep too many dynamic
features).

however, I did achieve success in implementing a soft-typed language, which
in many cases was able to infer types well enough to eliminate a good deal
of typechecking.


I don't believe it impossible (in theory) for example, to use my current vm
as the basis for a soft-typed (or faux static-typed) variation of C, if I so
felt like it...

this, quite possibly, would not be true static typing, only the presence of
some static checking, and the general absence of dynamic features. a
problem, however, would be that it would still likely present many of the
same FFI issues as a dynamic language (given the fact that, quite likely,
the pointer and array semantics in such an implementation would have been
faked as well anyways...).

a problem here, however, is the absense of probable "good use", and that it
would likely be too much temptation to add dynamic features (or omit aspects
of the traditional semantics), thus destroying the whole purpose...

cr88192

unread,
Aug 18, 2006, 11:23:19 PM8/18/06
to

"Curtis W" <cwar...@gmail.com> wrote in message
news:1155937717.8...@p79g2000cwp.googlegroups.com...

> Ok, thanks for the clarification. It sounds like that would be
> considered soft typing, which is another matter entirely. I tend to
> just lump that in with static typing, since it still goes against the
> theory behind dynamic typing, just to a lesser degree.
>

soft-typing, some call it static, and some call it dynamic...

I say it is both, however, I view the whole issue as a spectrum myself...
of course, in the implementation of a language, there are hard limits, for
example, the chosen data representation, ...

I once beat against this problem in a rather "backwards" manner, so I can
see where there is a limit, and this limit is based primarily in the chosen
data representation...


> (To those of you who might be curious: I used to be a soft typing
> supporter, until I realized there's no reason not to just use dynamic
> typing.)
>


I can think of one:
the coder can explicitly limit what types of values allowed where, and get
the compiler to complain about it.

add(x, y)x+y;

will add any 2 items for which '+' is defined.

int add(int x, int y)x+y;

however, will tell the compiler to complain if it ever sees this function
being called with different arg types. also, my inferencer is stupid so
these clues help. it is like, "ok, I can't tell, I'll just make it variant",
and variant is sticky and if left unchecked will spread all over the place
(another power of declarations: getting rid of any variants that happen to
pop up...).

sadly as it is, there is no real way to verify in many cases if 'int+int'
will overflow, leaving the (imo crude) "overflow behavior is undefined"
semantics...

current implementation will just overflow them at 29 bits, about like a C
integer at 32...


however, I suspect static vs dynamic vs soft is likely to depend heavily on
personal preference...


Robbert Haarman

unread,
Aug 19, 2006, 12:22:25 AM8/19/06
to
(replying to both Curtis and cr)

On Sat, Aug 19, 2006 at 01:23:19PM +1000, cr88192 wrote:
>
> "Curtis W" <cwar...@gmail.com> wrote in message
> news:1155937717.8...@p79g2000cwp.googlegroups.com...
> > Ok, thanks for the clarification. It sounds like that would be
> > considered soft typing, which is another matter entirely. I tend to
> > just lump that in with static typing, since it still goes against the
> > theory behind dynamic typing, just to a lesser degree.
> >

I would say soft typing is closer to dynamic typing, because it accepts
programs with possible type errors, which is the essential
characteristic of dynamic typing, and conflicts with static typing,
where such programs would have to be rejected. There's an argument for
considering it another place in a spectrum (as cr does), though.

> soft-typing, some call it static, and some call it dynamic...
>
> I say it is both, however, I view the whole issue as a spectrum myself...
> of course, in the implementation of a language, there are hard limits, for
> example, the chosen data representation, ...

Which, of course, is an implementation issue...when your language
specification says the language is dynamically typed, you'd better make
sure you have a representation that makes run time type checks possible.

> > (To those of you who might be curious: I used to be a soft typing
> > supporter, until I realized there's no reason not to just use dynamic
> > typing.)
> >

What do you mean?



> I can think of one:
> the coder can explicitly limit what types of values allowed where, and get
> the compiler to complain about it.
>
> add(x, y)x+y;
>
> will add any 2 items for which '+' is defined.
>
> int add(int x, int y)x+y;

It can indeed be useful for a language to allow this, but it's
orthogonal to static/dynamic/soft typing.

> sadly as it is, there is no real way to verify in many cases if 'int+int'
> will overflow, leaving the (imo crude) "overflow behavior is undefined"
> semantics...

It depends. All CPUs I've written assembly code for had the ability to
detect and report integer overflow. Many languages detect overflow and
silently convert fixnums to bignums when it occurs. IIRC, Java has clear
specifications about the size of data types and the range of values they
can represent. So, actually, you can get predictable overflow, detect
overflow, and have well-defined behavior in case it occurs.

> however, I suspect static vs dynamic vs soft is likely to depend heavily on
> personal preference...

That, and probably also on what you're trying to do. I like dynamic
languages for explorative programming and rapid prototyping, but I can
imagine I'd find static languages (possibly even with mandatory type
annotations) a better fit for large projects developed by multiple
people. At this point, I can't tell, because my experience with static
languages for large projects is limited.

Regards,

Bob

---
A journey of a thousand miles starts under one's feet.
-- Lao Tze


cr88192

unread,
Aug 19, 2006, 2:08:32 AM8/19/06
to

"Robbert Haarman" <comp.la...@inglorion.net> wrote in message
news:2006081904...@morgenes.shire.sytes.net...

> (replying to both Curtis and cr)
>
> On Sat, Aug 19, 2006 at 01:23:19PM +1000, cr88192 wrote:
>>
>> "Curtis W" <cwar...@gmail.com> wrote in message
>> news:1155937717.8...@p79g2000cwp.googlegroups.com...
>> > Ok, thanks for the clarification. It sounds like that would be
>> > considered soft typing, which is another matter entirely. I tend to
>> > just lump that in with static typing, since it still goes against the
>> > theory behind dynamic typing, just to a lesser degree.
>> >
>
> I would say soft typing is closer to dynamic typing, because it accepts
> programs with possible type errors, which is the essential
> characteristic of dynamic typing, and conflicts with static typing,
> where such programs would have to be rejected. There's an argument for
> considering it another place in a spectrum (as cr does), though.
>
yes.

>> soft-typing, some call it static, and some call it dynamic...
>>
>> I say it is both, however, I view the whole issue as a spectrum myself...
>> of course, in the implementation of a language, there are hard limits,
>> for
>> example, the chosen data representation, ...
>
> Which, of course, is an implementation issue...when your language
> specification says the language is dynamically typed, you'd better make
> sure you have a representation that makes run time type checks possible.
>

yes, I once tried to use a C style data representation in a soft-typed
language (by starting implementation of a fancy system designed to gloss
over a lot of the issues).

unsurprisingly, it didn't go so well...

approaching it from the opposite direction (an optimized and analized
version of a dynamic vm) worked a lot better, but never really did solve a
lot of the FFI problems (eg: the hope for something other than code
generation).

one, if albeit even more dubious, option is that of using in-place
compilation (a lot of code that was written for a JIT compiler) to generate
all the FFI stubs (in this way, one could simply pass a pointer to a C
function and a string defining the args list, have direct calls between C
and the VM, ...).


>> > (To those of you who might be curious: I used to be a soft typing
>> > supporter, until I realized there's no reason not to just use dynamic
>> > typing.)
>> >
>
> What do you mean?
>
>> I can think of one:
>> the coder can explicitly limit what types of values allowed where, and
>> get
>> the compiler to complain about it.
>>
>> add(x, y)x+y;
>>
>> will add any 2 items for which '+' is defined.
>>
>> int add(int x, int y)x+y;
>
> It can indeed be useful for a language to allow this, but it's
> orthogonal to static/dynamic/soft typing.
>

it seems I am not sure what you mean...


>> sadly as it is, there is no real way to verify in many cases if 'int+int'
>> will overflow, leaving the (imo crude) "overflow behavior is undefined"
>> semantics...
>
> It depends. All CPUs I've written assembly code for had the ability to
> detect and report integer overflow. Many languages detect overflow and
> silently convert fixnums to bignums when it occurs. IIRC, Java has clear
> specifications about the size of data types and the range of values they
> can represent. So, actually, you can get predictable overflow, detect
> overflow, and have well-defined behavior in case it occurs.
>

but defining/handling these cases is often more expensive than not...

my problems are:
int in my language does not increase its size (it is, whatever will fit in a
fixnum);
long, however, will upgrade to a larger size (a 64 bit heap integer), and
then possibly to bignum.

int+int is defined to return int, but there is no proof it wont overflow.
long, however, is more expensive than int, and thus to be avoided.

would be nice if my ints were the same size as C, but they are not, so I
leave the rest of the definition generally undefined (in practice, they will
overflow, but I don't define this exactly...).


>> however, I suspect static vs dynamic vs soft is likely to depend heavily
>> on
>> personal preference...
>
> That, and probably also on what you're trying to do. I like dynamic
> languages for explorative programming and rapid prototyping, but I can
> imagine I'd find static languages (possibly even with mandatory type
> annotations) a better fit for large projects developed by multiple
> people. At this point, I can't tell, because my experience with static
> languages for large projects is limited.
>

I have had a good deal of C experience myself. I like both the things C can
give, but C has its costs as well.
on a larger scale, my code is largely a bunch of patchwork, with an ad-hoc
dynamic typesystem running through the whole mass.

a few previous vms were built on this system, but the new vm uses a new
system, and a system has been set up between them in an attempt to convert
types and facilitate communication (the system used by the vm is too
different and too anal to expect generic C code to use it).

or such...

Robbert Haarman

unread,
Aug 19, 2006, 5:01:41 AM8/19/06
to
On Sat, Aug 19, 2006 at 04:08:32PM +1000, cr88192 wrote:
>
> "Robbert Haarman" <comp.la...@inglorion.net> wrote in message
> news:2006081904...@morgenes.shire.sytes.net...
> > On Sat, Aug 19, 2006 at 01:23:19PM +1000, cr88192 wrote:
> >>
> >> "Curtis W" <cwar...@gmail.com> wrote in message
> >> news:1155937717.8...@p79g2000cwp.googlegroups.com...
>
> >> > (To those of you who might be curious: I used to be a soft typing
> >> > supporter, until I realized there's no reason not to just use dynamic
> >> > typing.)
> >> >
> >
> > What do you mean?
> >
> >> I can think of one:
> >> the coder can explicitly limit what types of values allowed where, and
> >> get
> >> the compiler to complain about it.
> >>
> >> add(x, y)x+y;
> >>
> >> will add any 2 items for which '+' is defined.
> >>
> >> int add(int x, int y)x+y;
> >
> > It can indeed be useful for a language to allow this, but it's
> > orthogonal to static/dynamic/soft typing.
> >
>
> it seems I am not sure what you mean...

I mean it can be useful for a language to allow type annotations to be
included or omitted, but this is independent from the language being
statically, dynamically, or softly typed. Given one of the above
definitions, and a function call add("foo", 12), you could get:

# Static typing
$ static-compiler program.source -o program
Error: add(string, int) not defined
$ ./program
no such file or directory: ./program

# Dynamic typing
$ dynamic-compiler program.source -o program
$ ./program
Error: add(string, int) not defined

# Soft typing
$ soft-compiler program.source -o program
Warning: add(string, int) not defined
$ ./program
Error: add(string, int) not defined

> >> sadly as it is, there is no real way to verify in many cases if 'int+int'
> >> will overflow, leaving the (imo crude) "overflow behavior is undefined"
> >> semantics...
> >
> > It depends. All CPUs I've written assembly code for had the ability to
> > detect and report integer overflow. Many languages detect overflow and
> > silently convert fixnums to bignums when it occurs. IIRC, Java has clear
> > specifications about the size of data types and the range of values they
> > can represent. So, actually, you can get predictable overflow, detect
> > overflow, and have well-defined behavior in case it occurs.
> >
>
> but defining/handling these cases is often more expensive than not...

True. But then, it can also be that your program produces incorrect
results if you don't detect and handle integer overflow. Take your pick:
a program that runs incredibly fast, but produces incorrect results, or
a program that runs somewhat slower, but produces correct ones.

> my problems are:
> int in my language does not increase its size (it is, whatever will fit in a
> fixnum);
> long, however, will upgrade to a larger size (a 64 bit heap integer), and
> then possibly to bignum.

Well, then that's your specification, and your users will have to deal
with it. Or use a different language, of course.

> int+int is defined to return int, but there is no proof it wont overflow.
> long, however, is more expensive than int, and thus to be avoided.

Depends. If you want correct results, and you don't know that your
values will fit in an int (whose range you don't know), you'd better use
long.

> would be nice if my ints were the same size as C, but they are not, so I
> leave the rest of the definition generally undefined (in practice, they will
> overflow, but I don't define this exactly...).

It's ok to leave things undefined sometimes. Lots of people won't care
that their ints can overflow, and many won't care if ints are 29-bits,
31-bits, or 48-bits, either. Alternatively, since you know your ints are
29-bits, you could include that in the spec, and leave only the result
of an operation that causes integer overflow undefined. Or you could
actually detect and handle it; really, detecting integer overflow
shouldn't be all that expensive, and it _should_ occur rarely enough
that the cost of handling it doesn't have a huge impact on performance.

Regards,

Bob

---
> Those who do not study history are doomed to repeat it

Yes, and those who do study history are doomed to watch in frustration
as it is unwittingly repeated by those who do not :-)

-- jonadab on Slashdot


cr88192

unread,
Aug 19, 2006, 7:45:24 AM8/19/06
to

"Robbert Haarman" <comp.la...@inglorion.net> wrote in message
news:2006081909...@morgenes.shire.sytes.net...
yes, ok.


>> >> sadly as it is, there is no real way to verify in many cases if
>> >> 'int+int'
>> >> will overflow, leaving the (imo crude) "overflow behavior is
>> >> undefined"
>> >> semantics...
>> >
>> > It depends. All CPUs I've written assembly code for had the ability to
>> > detect and report integer overflow. Many languages detect overflow and
>> > silently convert fixnums to bignums when it occurs. IIRC, Java has
>> > clear
>> > specifications about the size of data types and the range of values
>> > they
>> > can represent. So, actually, you can get predictable overflow, detect
>> > overflow, and have well-defined behavior in case it occurs.
>> >
>>
>> but defining/handling these cases is often more expensive than not...
>
> True. But then, it can also be that your program produces incorrect
> results if you don't detect and handle integer overflow. Take your pick:
> a program that runs incredibly fast, but produces incorrect results, or
> a program that runs somewhat slower, but produces correct ones.
>

well, another point is that, declaring a type as 'int' basically means "this
value will fit in an integer".

types like long, or variant (which may both still use fixnums as the general
representation), will in fact detect this overflow and promote the type
automatically.

the big thing is, declaring it 'int' also means declaring it fixnum, and
thus one is bound by the size of fixnum.

more or less, nearly the sole purpose of 'int' is speed (by ommiting futher
typechecks).
the fact is, the number will overflow, and the vm wont care. it is just lame
that it is 29 bits and not 32, which means that it does not match up exactly
with C's int.


>> my problems are:
>> int in my language does not increase its size (it is, whatever will fit
>> in a
>> fixnum);
>> long, however, will upgrade to a larger size (a 64 bit heap integer), and
>> then possibly to bignum.
>
> Well, then that's your specification, and your users will have to deal
> with it. Or use a different language, of course.
>

variant is the other option (the default type), which will convert freely as
needed...
I just need fixed rules for the sake of the inferencer.

I had considered other types (eg: byte, sbyte, short, ushort, and uint),
which would be like int but implicitly mask or sign extend. I didn't fully
implement them though (in bytecode such types would neccisarily be
slower...).

>> int+int is defined to return int, but there is no proof it wont overflow.
>> long, however, is more expensive than int, and thus to be avoided.
>
> Depends. If you want correct results, and you don't know that your
> values will fit in an int (whose range you don't know), you'd better use
> long.
>

yes, or variant...

int is intended for the really common case of loops and similar, where it is
known the value wont be all that large. also, being a long time C coder,
such restrictions are nothing major (it is just sad that, since I don't know
the size, overflow can't be utilized the same way it is often used in C...).

>> would be nice if my ints were the same size as C, but they are not, so I
>> leave the rest of the definition generally undefined (in practice, they
>> will
>> overflow, but I don't define this exactly...).
>
> It's ok to leave things undefined sometimes. Lots of people won't care
> that their ints can overflow, and many won't care if ints are 29-bits,
> 31-bits, or 48-bits, either. Alternatively, since you know your ints are
> 29-bits, you could include that in the spec, and leave only the result
> of an operation that causes integer overflow undefined. Or you could
> actually detect and handle it; really, detecting integer overflow
> shouldn't be all that expensive, and it _should_ occur rarely enough
> that the cost of handling it doesn't have a huge impact on performance.
>

yes, I had considered defining it.
then again, I had also considered merging 2 types and giving myself 30 bit
fixnums instead...

I have also considered standardizing on a 32 bit tagged value type, even for
64 bit archs, under the thought that in the 64 bit case (or maybe just
eventually), they wont encode an address but an index into the heap.

this would actually make some operations (eg: reference counting) a little
cheaper (albeit getting the pointer to an object on-heap would be slightly
more expensive).

it is a cost difference along the lines of replacing: (a&(~7)) with:
(arr[a>>19]+((a>>2)&0x1FFFE)).

however, on the side of ref counting (done eaqualy as much or more), it will
save several checks and possibly a loop...

Curtis W

unread,
Aug 19, 2006, 11:23:39 AM8/19/06
to
> > > Ok, thanks for the clarification. It sounds like that would be
> > > considered soft typing, which is another matter entirely. I tend to
> > > just lump that in with static typing, since it still goes against the
> > > theory behind dynamic typing, just to a lesser degree.
> > >
>
> I would say soft typing is closer to dynamic typing, because it accepts
> programs with possible type errors, which is the essential
> characteristic of dynamic typing, and conflicts with static typing,
> where such programs would have to be rejected. There's an argument for
> considering it another place in a spectrum (as cr does), though.
Well, yes, it is closer to dynamic typing than it is static, the
difference being that soft typing has errors at compile time. In order
to do this, though, it has to sacrifice flexibility, because it's
working off the assumption that a known error at compile time is a bad
thing to postpone. Most of the time this works out okay, but you start
to get into trouble when the programmer actually wants the error to
happen at runtime. If you factor in my theory that warnings are just as
good as errors, you can see why I believe that warnings+flexibility
(dynamic typing) is better than errors+inflexibility (soft typing).

Curtis W

unread,
Aug 19, 2006, 11:26:23 AM8/19/06
to
> # Static typing
> $ static-compiler program.source -o program
> Error: add(string, int) not defined
> $ ./program
> no such file or directory: ./program
>
> # Dynamic typing
> $ dynamic-compiler program.source -o program
> $ ./program
> Error: add(string, int) not defined
>
> # Soft typing
> $ soft-compiler program.source -o program
> Warning: add(string, int) not defined
> $ ./program
> Error: add(string, int) not defined
Actually, that last one is actually still dynamic typing. The soft
typing version would identical to the statically typed one in this case.

cr88192

unread,
Aug 19, 2006, 5:12:38 PM8/19/06
to

"Curtis W" <cwar...@gmail.com> wrote in message
news:1156001019....@b28g2000cwb.googlegroups.com...

I am not entirely sure I see your point here.

if the developer declares the types, it can be assumed they want the error
to occure at compile time (or they only want a function to be called with
certain types, ...).

otherwise, these languages tend to provide dynamic types as well (in my lang
I called this type 'variant', or 'var'). in this case, type errors are left
to be resolved at runtime.

likewise, all this also provides a way to improve performance by forcing
values to specific types, thus limiting the damage that can be caused due to
weaknesses in the inferencer (actually, at times I wonder if it does enough
to deserve this description, then again, it may do more later...).

there may also be semantic relevance here as well.

or such...


Curtis W

unread,
Aug 19, 2006, 8:14:11 PM8/19/06
to
> I am not entirely sure I see your point here.
>
> if the developer declares the types, it can be assumed they want the error
> to occure at compile time (or they only want a function to be called with
> certain types, ...).
That's what most people generally assume, but it leaves the programmer
in the dark if he actually _wants_ the error to occur at runtime (e.g.
via an exception). This doesn't even necessarily involve type errors;
consider this python example:

try:
import pygtk
except ImportError:
print "Error: couldn't find pygtk, running without GUI"

In this case it's obvious that flagging the absence of 'pygtk' at
compile time is not wanted. In trivial cases like this the compiler
could theoretically infer it, but anything more complex and you start
to bump up against the halting problem.

> otherwise, these languages tend to provide dynamic types as well (in my lang
> I called this type 'variant', or 'var'). in this case, type errors are left
> to be resolved at runtime.

If your 'var' type is similar to Boo's "duck" type, then really you're
just providing a back door to dynamic typing from a statically typed
language; it doesn't somehow make your language dynamically typed,
rather it just makes it less sound from a static typing supporter's
view.

> likewise, all this also provides a way to improve performance by forcing
> values to specific types, thus limiting the damage that can be caused due to
> weaknesses in the inferencer (actually, at times I wonder if it does enough
> to deserve this description, then again, it may do more later...).

I'm not saying that you couldn't allow the programmer to force a
variable to be a specific type at compile time for performance reasons,
so long as it isn't done by default it's perfectly fine.

Jon Harrop

unread,
Aug 19, 2006, 9:14:18 PM8/19/06
to
Curtis W wrote:
> Aside from brevity,

Given the brevity of ML, I see no evidence of dynamic typing => brevity.

--
Dr Jon D Harrop, Flying Frog Consultancy
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists

Jon Harrop

unread,
Aug 19, 2006, 9:16:55 PM8/19/06
to
Stefan Ram wrote:
> Robbert Haarman <comp.la...@inglorion.net> writes:
>>type annotations. This leads to unnecessary verbosity.
>
> One also might regard this as documentation.
>
> Without static types:
>
> bind( first, second ){ return new Bind( first, second ).composition(); }
>
> With static types:
>
> Operation<IntValue,MemoryState> bind
> ( Operation<IntValue,MemoryState> first,
> ParameterizedOperation<IntValue,MemoryState,IntValue> second )
> { return new Bind<IntValue,MemoryState,IntValue>
> ( first, second ).composition(); }
>
> Which one is more readable?

This has nothing to do with static typing. You can annotate types in
dynamically typed languages and statically typed languages which have type
inference.

Curtis W

unread,
Aug 19, 2006, 10:15:50 PM8/19/06
to
I don't have much knowledge of ML, although the fact that it doesn't
have an object system (as far as I know) is reason enough for lack of
brevity. I'm not sure how much this applies to ML, but OCaml has
several areas where dynamic typing is more concise:

python:

x = eval(get_input())
print x*2

OCaml:

let x = eval (get_input ()) in
match x with
`Int x -> print x*2;;


The key thing to note is the pattern matching required. If OCaml wasn't
so lax in regard to pattern matching it would be even longer to handle
the general case, something done automatically in the python version.

Another area where OCaml is more verbose is its structural subtyping.
How does it deal with the case where certain methods are only used in
certain, possibly random, cases? It seems like one would have to
manually type functions like that, which is added verbosity not
required in the dynamic version. Of course, the dynamic version would
require you to type it if you want accurate warnings, but those are
strictly optional.

cr88192

unread,
Aug 19, 2006, 11:32:43 PM8/19/06
to

"Curtis W" <cwar...@gmail.com> wrote in message
news:1156032851.5...@h48g2000cwc.googlegroups.com...

>> I am not entirely sure I see your point here.
>>
>> if the developer declares the types, it can be assumed they want the
>> error
>> to occure at compile time (or they only want a function to be called with
>> certain types, ...).
> That's what most people generally assume, but it leaves the programmer
> in the dark if he actually _wants_ the error to occur at runtime (e.g.
> via an exception). This doesn't even necessarily involve type errors;
> consider this python example:
>
> try:
> import pygtk
> except ImportError:
> print "Error: couldn't find pygtk, running without GUI"
>
> In this case it's obvious that flagging the absence of 'pygtk' at
> compile time is not wanted. In trivial cases like this the compiler
> could theoretically infer it, but anything more complex and you start
> to bump up against the halting problem.
>

the above could be done at runtime (ok, example uses non-implemented
features):

int i;
var v;

v=read_eval(); //read_eval, doesn't actually exist, but gives the idea

try i=v catch(TypeError)
println(typename(v), " is not int");

nor do exceptions, or 'typename', presently exist...
I guess I implement things as I need them, but haven't needed them yet.
read_eval and typename would be easy, however exceptions are a little more
work (currently, on error the vm will print a message and die...).


>> otherwise, these languages tend to provide dynamic types as well (in my
>> lang
>> I called this type 'variant', or 'var'). in this case, type errors are
>> left
>> to be resolved at runtime.
> If your 'var' type is similar to Boo's "duck" type, then really you're
> just providing a back door to dynamic typing from a statically typed
> language; it doesn't somehow make your language dynamically typed,
> rather it just makes it less sound from a static typing supporter's
> view.
>

this works imo. it is a hybrid (imo, a lot like VB).

the lang is actually intended to be a little closer to statically typed, but
offers a lot of traditionally dynamic features (lexical closures,
hetrogeneous lists, ...).

the thing is, however, that in most places tagged values are used
(type-specific cases are largely handled by special opcodes that work with
the values directly, rather than expecting all cases to be handled by all
types...).


>> likewise, all this also provides a way to improve performance by forcing
>> values to specific types, thus limiting the damage that can be caused due
>> to
>> weaknesses in the inferencer (actually, at times I wonder if it does
>> enough
>> to deserve this description, then again, it may do more later...).
> I'm not saying that you couldn't allow the programmer to force a
> variable to be a specific type at compile time for performance reasons,
> so long as it isn't done by default it's perfectly fine.
>

yeah, the default type is actually variant (which is also the catch-all
type).

most purely static languages, when faced with more complicated issues, end
up using often complicated and ugly language features to deal with the
problem.

having a fully generic type, however, solves a lot of these problems,
largely eliminating the need for such features...

eg: my lang does not have a complicated typesystem, union-types, templates,
... as I don't really feel they are needed...


or such...


George Neuner

unread,
Aug 20, 2006, 2:24:34 AM8/20/06
to
On 19 Aug 2006 08:23:39 -0700, "Curtis W" <cwar...@gmail.com> wrote:

>>>> George Neuner wrote: some stuff about Dylan

>>> Curtis W. wrote:
>>>
>>> Ok, thanks for the clarification. It sounds like that would be
>>> considered soft typing, which is another matter entirely. I tend to
>>> just lump that in with static typing, since it still goes against the
>>> theory behind dynamic typing, just to a lesser degree.
>

>> Robbert Haarman wrote:
>>
>> I would say soft typing is closer to dynamic typing, because it accepts
>> programs with possible type errors, which is the essential
>> characteristic of dynamic typing, and conflicts with static typing,
>> where such programs would have to be rejected. There's an argument for
>> considering it another place in a spectrum (as cr does), though.
>
>Well, yes, it is closer to dynamic typing than it is static, the
>difference being that soft typing has errors at compile time. In order
>to do this, though, it has to sacrifice flexibility, because it's
>working off the assumption that a known error at compile time is a bad
>thing to postpone. Most of the time this works out okay, but you start
>to get into trouble when the programmer actually wants the error to
>happen at runtime. If you factor in my theory that warnings are just as
>good as errors, you can see why I believe that warnings+flexibility
>(dynamic typing) is better than errors+inflexibility (soft typing).

Please attribute other posters. It's hard to follow a conversation
when you don't know who said what.


I don't see why you think soft typing is less flexible than dynamic
typing ... wherever you leave the types unspecified the program should
behave as if is dynamically typed. If it doesn't, the language isn't
really using soft typing IMO.

My only experience with this kind of type system is Dylan. In Dylan,
leaving either side of the type equation unspecified results in
runtime type checking. You only get a compile time error when the
types involved are completely specified, the types don't match and the
source type is not coercible into the destination type.

Curtis W

unread,
Aug 20, 2006, 11:45:15 AM8/20/06
to
Oh, sorry. I usually just use the tree view on the left side of the
page, but I guess not everybody uses google groups.

> I don't see why you think soft typing is less flexible than dynamic
> typing ... wherever you leave the types unspecified the program should
> behave as if is dynamically typed. If it doesn't, the language isn't
> really using soft typing IMO.

Well, no. The kind of soft typing I'm talking about is where it tries
to catch as many errors at compile time without being annoying. This
generally means inferring the types of arguments to a function and
checking it against the values passed in, possibly causing a compile
time error.

> My only experience with this kind of type system is Dylan. In Dylan,
> leaving either side of the type equation unspecified results in
> runtime type checking. You only get a compile time error when the
> types involved are completely specified, the types don't match and the
> source type is not coercible into the destination type.

That's a bit of an odd type system--one might even call it dynamically
typed, considering that, by default, everything acts like a normal
dynamic language. The only problem I see with making type annotations
checked at compile time is that, if you only want a warning, you can't
have the benefits of any type checking, which would be especially
crippling in a dependantly typed language.

Brendan Guild

unread,
Aug 20, 2006, 4:52:50 PM8/20/06
to
Curtis W wrote in
news:1155922778.9...@75g2000cwc.googlegroups.com:

> Robbert Haarman wrote:
>> On Wed, Aug 16, 2006 at 06:42:47AM -0700, Curtis W wrote:
>> > Having an entry in a format string _is_ a commonality.
>>
>> Not in the operations that are available on the values you put in
>> the list. That format string also doesn't affect what types of
>> values I can store in the list, neither under static, nor under
>> dynamic typing (it's possible to devise mechanisms by which
>> format strings do have that property (e.g. sbcl checks arguments
>> against format strings), but assume that this is a format string
>> that I made up out of thin air and that doesn't have any
>> significance to the type checker).
> Yes, I know, but each element requires an entry in the format
> string for it to work. Since this is required of all entries in
> the list no matter what type they are, it can be seen as a
> commonality, so it's not a heterogenous list.

That's not exactly true. In the actual code provided, it was possible
to have entries in the list that didn't have corresponding elements
in the format string.

Also, one could do something very similar without any format string.
For example,

foo = ['no format', 42, 3.5, 'dog']
n = 0
while n < foo.length
case n % 3
when 0
foo[n + 1] = foo[n + 1].reverse
when 1
foo[n + 1] = foo[n + 1] / 2
end
n = n + 1
end

The obvious thing to point out here is that the regular pattern of:
string, number, something, string, number, something, etc. could be
called a commonality between the elements, but what this is meant to
illustrate is that the commonality may need to be computed.

Now imagine a list whose 'commonality' can be computed with no less
than a full Turing machine. That is, we can determine whether we
should divide by 2 or 'reverse' by running a some Turing machine or
the equivalent Ruby code. This works because Ruby is Turing complete,
but that's where the problem lies for statically typed languages: The
type system of a statically typed language is not Turing complete.
This means that we have achieved a level of heterogeneity that is
forbidden by statically typed languages.

>> > If you don't have one for one of the entries, it'll fail.
>>
>> It won't _necessarily_ fail, and that's why it's interesting:
>> under static typing, it will be rejected because it's not proven
>> that the types are correct, but under dynamic typing it will run,
>> as long as the types actually are correct (in both cases,
>> correct. w.r.t. the operations performed on the values).
> Let's take an example. Let's say the user enters the following for
> 'foo':
>
> ['iis', '1', '2', 'foo', 'bar']
>
> _That_ is a heterogenous list, because there are no commonalities
> between elements--the last one doesn't have an entry in the format
> string. Are you telling me that won't produce an error at runtime
> when you try and apply the algorithm to it? If it doesn't, I'd
> like to know what language you're using so I can stay far away
> from it.

The language is Ruby. Let us take another look at that algorithm:

Robbert Haarman wrote:
> Alright, but in typical dynamically typed languages, you can make
> heterogenous lists, and use more than just the operations defined
> on the common base type (if any) on the elements. For example, in
> Ruby, it's perfectly fine to say:
>
> foo = ['is', 42, 'the answer']
> n = 0
> while n < foo[0].length
> case foo[0][n].chr
> when 'i'
> foo[n + 1] = foo[n + 1] / 2
> when 's'
> foo[n + 1] = foo[n + 1].reverse
> end
> n = n + 1
> end
> puts foo[1]
> puts foo[2]

Now if we replace the value of foo with


['iis', '1', '2', 'foo', 'bar']

It looks like no error is produced! The resulting foo will just be
['iis', 0.5, 1, 'oof', 'bar']
as expected.

Curtis W wrote:
> The property of turing completeness that's applicable here is that
> any turing complete language can implement any other turing
> complete language. For example, the perl interpreter is written in
> C, so it is possible to add an integer to a string from C, even if
> it means implementing a perl interpreter (it doesn't). You might
> make the case that it's not nearly as easy in C as it is in perl,
> but then this isn't about easy of use, but rather whether it's
> possible.

Languages deliberately introduce restrictions on what can be done,
especially in statically typed languages. You cannot assign the
address of a double to a pointer to an int in C (without a cast),
that is simply forbidden. In a dynamically typed language it would be
allowed.

Simulating a dynamically typed language that allows such assignments
and then making the assignment in that language is not the same as
making that assignment in C.

Statically typed languages do not allow heterorgeneous lists in the
same way that dynamically typed languages do. That is simply a choice
that they make. It does not mean that statically typed languages are
not Turing complete, since you can indeed make an interpreter for a
dynamically typed language, but that does not change the fact of the
matter about heterogeneous lists.

Curtis W

unread,
Aug 20, 2006, 5:55:13 PM8/20/06
to
Brendan Guild wrote:
> Curtis W wrote in
> news:1155922778.9...@75g2000cwc.googlegroups.com:
>
> > Robbert Haarman wrote:
> >> On Wed, Aug 16, 2006 at 06:42:47AM -0700, Curtis W wrote:
> >> > Having an entry in a format string _is_ a commonality.
> >>
> >> Not in the operations that are available on the values you put in
> >> the list. That format string also doesn't affect what types of
> >> values I can store in the list, neither under static, nor under
> >> dynamic typing (it's possible to devise mechanisms by which
> >> format strings do have that property (e.g. sbcl checks arguments
> >> against format strings), but assume that this is a format string
> >> that I made up out of thin air and that doesn't have any
> >> significance to the type checker).
> > Yes, I know, but each element requires an entry in the format
> > string for it to work. Since this is required of all entries in
> > the list no matter what type they are, it can be seen as a
> > commonality, so it's not a heterogenous list.
>
> That's not exactly true. In the actual code provided, it was possible
> to have entries in the list that didn't have corresponding elements
> in the format string.
Yes, that's true; I hadn't noticed that. Even still, it doesn't really
make a difference--why even put the element in the list if you're not
going to use it? Essentially what you're doing in that instance is
simply working on the part of the list that isn't heterogenous. Working
with pi to the 10th digit doesn't somehow make it possible to use
irrational numbers in calculations, for example.

> The obvious thing to point out here is that the regular pattern of:
> string, number, something, string, number, something, etc. could be
> called a commonality between the elements, but what this is meant to
> illustrate is that the commonality may need to be computed.

Yes, it's an implicit commonality.

> Now imagine a list whose 'commonality' can be computed with no less
> than a full Turing machine. That is, we can determine whether we
> should divide by 2 or 'reverse' by running a some Turing machine or
> the equivalent Ruby code. This works because Ruby is Turing complete,
> but that's where the problem lies for statically typed languages: The
> type system of a statically typed language is not Turing complete.

They can be. Most (all?) dependently typed languages have turing
complete type systems.

> This means that we have achieved a level of heterogeneity that is
> forbidden by statically typed languages.

It's not "forbidden." It's still completely possible to do, you just
can't type check it at compile time, which is still only possible if
the pattern is known by then. Of course, none of that applies for
dependently typed languages.

> Robbert Haarman wrote:
> > Alright, but in typical dynamically typed languages, you can make
> > heterogenous lists, and use more than just the operations defined
> > on the common base type (if any) on the elements. For example, in
> > Ruby, it's perfectly fine to say:
> >
> > foo = ['is', 42, 'the answer']
> > n = 0
> > while n < foo[0].length
> > case foo[0][n].chr
> > when 'i'
> > foo[n + 1] = foo[n + 1] / 2
> > when 's'
> > foo[n + 1] = foo[n + 1].reverse
> > end
> > n = n + 1
> > end
> > puts foo[1]
> > puts foo[2]
>
> Now if we replace the value of foo with
> ['iis', '1', '2', 'foo', 'bar']
> It looks like no error is produced! The resulting foo will just be
> ['iis', 0.5, 1, 'oof', 'bar']
> as expected.

Assuming there aren't any commonalities built in from the language
(there are), you can't do anything meaningful on the last element
anyway*, so its presence doesn't matter.

* I suspect you're going to try to come back with something like this:
foo[4].reverse

In this situation, 'foo' can be seen as two separate lists shoved
together--the first one is described by the format string, the second
is a list consisting of a string.

> Curtis W wrote:
> > The property of turing completeness that's applicable here is that
> > any turing complete language can implement any other turing
> > complete language. For example, the perl interpreter is written in
> > C, so it is possible to add an integer to a string from C, even if
> > it means implementing a perl interpreter (it doesn't). You might
> > make the case that it's not nearly as easy in C as it is in perl,
> > but then this isn't about easy of use, but rather whether it's
> > possible.
>
> Languages deliberately introduce restrictions on what can be done,
> especially in statically typed languages. You cannot assign the
> address of a double to a pointer to an int in C (without a cast),
> that is simply forbidden. In a dynamically typed language it would be
> allowed.

Hmm, so you're comparing C with the entirety of dynamic languages?
Maybe I should compare statically typed languages and BASIC? Here's a
hint: you can do that in languages that support union types.

> Simulating a dynamically typed language that allows such assignments
> and then making the assignment in that language is not the same as
> making that assignment in C.

Well, yes it is. It's true that the type system won't be able to check
it, but it's certainly possible to do.

Curtis W

unread,
Aug 20, 2006, 6:03:03 PM8/20/06
to
Brendan Guild wrote:
> Curtis W wrote in
> news:1155922778.9...@75g2000cwc.googlegroups.com:
>
> > Robbert Haarman wrote:
> >> On Wed, Aug 16, 2006 at 06:42:47AM -0700, Curtis W wrote:
> >> > Having an entry in a format string _is_ a commonality.
> >>
> >> Not in the operations that are available on the values you put in
> >> the list. That format string also doesn't affect what types of
> >> values I can store in the list, neither under static, nor under
> >> dynamic typing (it's possible to devise mechanisms by which
> >> format strings do have that property (e.g. sbcl checks arguments
> >> against format strings), but assume that this is a format string
> >> that I made up out of thin air and that doesn't have any
> >> significance to the type checker).
> > Yes, I know, but each element requires an entry in the format
> > string for it to work. Since this is required of all entries in
> > the list no matter what type they are, it can be seen as a
> > commonality, so it's not a heterogenous list.
>
> That's not exactly true. In the actual code provided, it was possible
> to have entries in the list that didn't have corresponding elements
> in the format string.
Oh, I hadn't noticed that. Even still, you won't be able to do anything
meaningful on the other elements because you don't know what they can
do, which supports my claim that truly heterogenous lists are
impractical.

> Now imagine a list whose 'commonality' can be computed with no less
> than a full Turing machine. That is, we can determine whether we
> should divide by 2 or 'reverse' by running a some Turing machine or
> the equivalent Ruby code. This works because Ruby is Turing complete,
> but that's where the problem lies for statically typed languages: The
> type system of a statically typed language is not Turing complete.

It can be. Dependently typed languages have a turing complete type
system, for example.

> This means that we have achieved a level of heterogeneity that is
> forbidden by statically typed languages.

Only for the weaker ones.

> Robbert Haarman wrote:
> > Alright, but in typical dynamically typed languages, you can make
> > heterogenous lists, and use more than just the operations defined
> > on the common base type (if any) on the elements. For example, in
> > Ruby, it's perfectly fine to say:
> >
> > foo = ['is', 42, 'the answer']
> > n = 0
> > while n < foo[0].length
> > case foo[0][n].chr
> > when 'i'
> > foo[n + 1] = foo[n + 1] / 2
> > when 's'
> > foo[n + 1] = foo[n + 1].reverse
> > end
> > n = n + 1
> > end
> > puts foo[1]
> > puts foo[2]
>
> Now if we replace the value of foo with
> ['iis', '1', '2', 'foo', 'bar']
> It looks like no error is produced! The resulting foo will just be
> ['iis', 0.5, 1, 'oof', 'bar']
> as expected.

Except you can't even operate on the elements which aren't in the
format string. You could assume that every element not in the format
string is a string, but then you're basically just splitting 'foo' up
into two homogenous lists.

> Curtis W wrote:
> > The property of turing completeness that's applicable here is that
> > any turing complete language can implement any other turing
> > complete language. For example, the perl interpreter is written in
> > C, so it is possible to add an integer to a string from C, even if
> > it means implementing a perl interpreter (it doesn't). You might
> > make the case that it's not nearly as easy in C as it is in perl,
> > but then this isn't about easy of use, but rather whether it's
> > possible.
>
> Languages deliberately introduce restrictions on what can be done,
> especially in statically typed languages. You cannot assign the
> address of a double to a pointer to an int in C (without a cast),
> that is simply forbidden. In a dynamically typed language it would be
> allowed.

Not in C you can't, but you can in any language with union types, e.g.
haskell or OCaml.

> Simulating a dynamically typed language that allows such assignments
> and then making the assignment in that language is not the same as
> making that assignment in C.

No. It is true that the C compiler won't be able to type check it, but
it's certainly still possible.

Brendan Guild

unread,
Aug 20, 2006, 8:38:16 PM8/20/06
to
Curtis W wrote in
news:1156111383....@m73g2000cwd.googlegroups.com:

> Brendan Guild wrote:
>> Now imagine a list whose 'commonality' can be computed with no
>> less than a full Turing machine. That is, we can determine
>> whether we should divide by 2 or 'reverse' by running a some
>> Turing machine or the equivalent Ruby code. This works because
>> Ruby is Turing complete, but that's where the problem lies for
>> statically typed languages: The type system of a statically typed
>> language is not Turing complete.
> It can be. Dependently typed languages have a turing complete type
> system, for example.
>
>> This means that we have achieved a level of heterogeneity that is
>> forbidden by statically typed languages.
> Only for the weaker ones.

Of course you are correct that a type system can be Turing complete,
though in practice it is not something I have seen. On the other
hand, heterogeneous lists have more power than merely that; they can
do things which even a Turing complete static type system cannot
allow.

It is as easy as this: take the format string from the input to the
program. Now a dynamically typed language can use a truely
heterogeneous list to store and use values as described by the format
string, but a statically typed language can never create a list with
such power, simply because the necessary information does not exist
early enough.



>> Languages deliberately introduce restrictions on what can be
>> done, especially in statically typed languages. You cannot assign
>> the address of a double to a pointer to an int in C (without a
>> cast), that is simply forbidden. In a dynamically typed language
>> it would be allowed.
> Not in C you can't, but you can in any language with union types,
> e.g. haskell or OCaml.

You can only do it if the union types are used. Every statically
typed language has incompatable types; it just varies from language
to language. The specific example is not important.

>> Simulating a dynamically typed language that allows such
>> assignments and then making the assignment in that language is
>> not the same as making that assignment in C.
> No. It is true that the C compiler won't be able to type check it,
> but it's certainly still possible.

There are two meanings of "Language A can do B" that are distinct in
this case. In the case of Turing machines and Turing completeness, a
language can do B if it can compute the function that B represents.
Turing complete languages can do any B that a Turing machine can.

When we say that language A can do B in the sense of language
properties, we are talking about the the operations that are
considered legal in the language definition. For example, an
assignment:
x = y
can only be done in language A if x and y have compatible types in
language A. Even if you are able to find a way to produce the same
effect with more statements, it does not change the fact that x and y
are incompatible and the above assignment is illegal.

In statically typed languages heterogeneous lists are illegal. This
is a statement about language properties and it is completely
orthogonal to the property of being Turing complete.

Looking at it another way: Being able to interpret language X in
language Y does not give language Y all the properties of language X.
If that were the case, then all Turing complete languages would be
the same.

Curtis W

unread,
Aug 20, 2006, 8:55:22 PM8/20/06
to
Ack. I didn't think the first one got through--I spent an hour or so
typing it up and when I hit "submit" firefox crashed, along with my
entire X session.

Curtis W

unread,
Aug 20, 2006, 9:15:06 PM8/20/06
to
Brendan Guild wrote:
> It is as easy as this: take the format string from the input to the
> program. Now a dynamically typed language can use a truely
> heterogeneous list to store and use values as described by the format
> string, but a statically typed language can never create a list with
> such power, simply because the necessary information does not exist
> early enough.
That's where an 'any' type would come in.

> >> Simulating a dynamically typed language that allows such
> >> assignments and then making the assignment in that language is
> >> not the same as making that assignment in C.
> > No. It is true that the C compiler won't be able to type check it,
> > but it's certainly still possible.
>
> There are two meanings of "Language A can do B" that are distinct in
> this case. In the case of Turing machines and Turing completeness, a
> language can do B if it can compute the function that B represents.
> Turing complete languages can do any B that a Turing machine can.
>
> When we say that language A can do B in the sense of language
> properties, we are talking about the the operations that are
> considered legal in the language definition.

I suggest you use clearer terminology in the future--I don't know how I
was supposed to know you redefined the word "do."

> In statically typed languages heterogeneous lists are illegal. This
> is a statement about language properties and it is completely
> orthogonal to the property of being Turing complete.

Here, let me rephrase that for you:

"In statically typed languages heterogenous lists require more effort
to use compared to dynamically typed languages."

In this case, I agree. I was never arguing that, so I have no problem
admitting that you're right on this point.

Jon Harrop

unread,
Aug 20, 2006, 10:13:03 PM8/20/06
to
Curtis W wrote:
> I don't have much knowledge of ML, although the fact that it doesn't
> have an object system (as far as I know)

OCaml is an ML and it has an object system.

> is reason enough for lack of brevity.

OOP is verbose, IMHO.

> I'm not sure how much this applies to ML, but OCaml has
> several areas where dynamic typing is more concise:
>
> python:
>
> x = eval(get_input())
> print x*2
>
> OCaml:
>
> let x = eval (get_input ()) in
> match x with
> `Int x -> print x*2;;

The way you have written this particular example, yes. Overall, OCaml is
typically at least as concise as Python.

> The key thing to note is the pattern matching required.

There are many ways to do it without pattern matching on the outside, e.g.
put it in the "print" function, use OOP, typify the functions.

> If OCaml wasn't
> so lax in regard to pattern matching it would be even longer to handle
> the general case, something done automatically in the python version.

Only if by "the general case" you mean anything that happens to be typeable
in Python.

> Another area where OCaml is more verbose is its structural subtyping.
> How does it deal with the case where certain methods are only used in
> certain, possibly random, cases? It seems like one would have to
> manually type functions like that, which is added verbosity not
> required in the dynamic version. Of course, the dynamic version would
> require you to type it if you want accurate warnings, but those are
> strictly optional.

I thought structural subtyping could be entirely implicit in OCaml but I
won't speculate on OOP in OCaml. Suffice to say, OOP is rarely used in
OCaml because it provides better alternatives for most common cases.

Jon Harrop

unread,
Aug 20, 2006, 10:21:42 PM8/20/06
to
Brendan Guild wrote:
> Of course you are correct that a type system can be Turing complete,
> though in practice it is not something I have seen.

C++?

> On the other
> hand, heterogeneous lists have more power than merely that; they can
> do things which even a Turing complete static type system cannot
> allow.

In as much as that is true, it is a tautology.

> In statically typed languages heterogeneous lists are illegal.

Again, this statement is so limited in applicability that it is useless.

You can implement dynamic languages in static languages, so you're not
losing anything. At worst, you have simply made some things more difficult.
It is more difficult to create a list of values where each value is of a
different type. However, that data structure is useless in practice so
people using statically typed languages simply don't care.

Curtis W

unread,
Aug 20, 2006, 10:38:13 PM8/20/06
to
Jon Harrop wrote:
> Curtis W wrote:
> > I don't have much knowledge of ML, although the fact that it doesn't
> > have an object system (as far as I know)
>
> OCaml is an ML and it has an object system.
>
> > is reason enough for lack of brevity.
>
> OOP is verbose, IMHO.
Classes (or their equivalent) are more concise when you compare them to
an equally flexible, non-class-based solution.

> > I'm not sure how much this applies to ML, but OCaml has
> > several areas where dynamic typing is more concise:
> >
> > python:
> >
> > x = eval(get_input())
> > print x*2
> >
> > OCaml:
> >
> > let x = eval (get_input ()) in
> > match x with
> > `Int x -> print x*2;;
>
> The way you have written this particular example, yes. Overall, OCaml is
> typically at least as concise as Python.

So then it should be obvious that OCaml is more verbose as a language
than python.

> > The key thing to note is the pattern matching required.
>
> There are many ways to do it without pattern matching on the outside, e.g.
> put it in the "print" function, use OOP, typify the functions.

Hiding it in the print function doesn't get rid of it--somebody still
has to type it. OOP in OCaml can also be rather verbose, e.g. in the
case when OCaml can't correctly infer the interface for an argument.

> > If OCaml wasn't
> > so lax in regard to pattern matching it would be even longer to handle
> > the general case, something done automatically in the python version.
>
> Only if by "the general case" you mean anything that happens to be typeable
> in Python.

By "the general case" I'm talking about explicitly handling the error:

let x = eval (get_input ()) in
match x with
`Int x -> print x*2

| _ -> print "error that I don't care about!";;

> > Another area where OCaml is more verbose is its structural subtyping.
> > How does it deal with the case where certain methods are only used in
> > certain, possibly random, cases? It seems like one would have to
> > manually type functions like that, which is added verbosity not
> > required in the dynamic version. Of course, the dynamic version would
> > require you to type it if you want accurate warnings, but those are
> > strictly optional.
>
> I thought structural subtyping could be entirely implicit in OCaml but I
> won't speculate on OOP in OCaml. Suffice to say, OOP is rarely used in
> OCaml because it provides better alternatives for most common cases.

Hehe. I wonder if you meant to say "doesn't provide." In any event,
it's not surprising that OOP isn't often used in OCaml, based on the
community's preference for inflexibility.

Brendan Guild

unread,
Aug 20, 2006, 11:03:36 PM8/20/06
to
Curtis W wrote in
news:1156122906.7...@p79g2000cwp.googlegroups.com:

> Brendan Guild wrote:
>> It is as easy as this: take the format string from the input to
>> the program. Now a dynamically typed language can use a truely
>> heterogeneous list to store and use values as described by the
>> format string, but a statically typed language can never create a
>> list with such power, simply because the necessary information
>> does not exist early enough.
> That's where an 'any' type would come in.

Except that in a statically typed language, you would only be allowed
to preform operations that can apply to any type, which is likely to
be a uselessly small number of operations.

I am talking about a set of types which share no commonality except
for that which they are given at runtime. I would call that 'truly
heterogeneous'; it is certainly heterogeneous enough to be impossible
to handle statically.

Another way in which a dynamically typed language can work with
heterogeneous lists is that it can allow type errors to occur and be
thrown as exceptions, then catch the exception and continue
processing the list. That sort of algorithm can apply to lists whose
elements have any types at all, with no restrictions. Surely that is
truly heterogeneous.

>> There are two meanings of "Language A can do B" that are distinct
>> in this case. In the case of Turing machines and Turing
>> completeness, a language can do B if it can compute the function
>> that B represents. Turing complete languages can do any B that a
>> Turing machine can.
>>
>> When we say that language A can do B in the sense of language

>> properties, we are talking about the operations that are


>> considered legal in the language definition.
> I suggest you use clearer terminology in the future--I don't know
> how I was supposed to know you redefined the word "do."

It seemed to be already redefined when I got here. I was just trying
to point out the two meanings of the word so that they could be used
deliberately, in case that unintentional usage was causing confusion.

Let us look back at where this started:
Curtis W previously wrote:
> Robbert Haarman wrote:
>> In a statically typed language, you would be limited to those
>> operations that are supported by all elements - which, for a truly
>> heterogenous list, would be none, and thus, indeed, the list would
>> be useless.
>
> No. If that were true, you'd be saying statically typed languages
> aren't turing complete. Statically typed languages are able to do
> anything dynamic languages can, so I'm not sure where you're
> getting this from.

Here it looks like you are twisting the meaning of 'do' around. The
only inference you can make about what a language can 'do' from the
fact that it is Turing complete is that it can represent a program to
compute any function that a Turing machine can compute.

When Robbert Haarman said that certain operations are not allowed in
a statically typed language, that was a completely separate issue
from what the language can 'do'. In any language, certain programs
are legal and other are illegal. Haarman was making a statement about
the class of legal programs, not the class of possible input/output
relations.

Curtis W wrote:


> Brendan Guild wrote:
>> In statically typed languages heterogeneous lists are illegal.
>> This is a statement about language properties and it is
>> completely orthogonal to the property of being Turing complete.
> Here, let me rephrase that for you:
>
> "In statically typed languages heterogenous lists require more
> effort to use compared to dynamically typed languages."

It is poor practice to change the meaning of a statement when you
rephrase it. Requiring effort and being illegal are very different
problems.

> In this case, I agree. I was never arguing that, so I have no
> problem admitting that you're right on this point.

I am surprised that you did not agree with my actual statement, since
you were saying that heterogeneous lists do not exist in any
language.

Jon Harrop

unread,
Aug 20, 2006, 11:01:22 PM8/20/06
to
Curtis W wrote:
> Classes (or their equivalent) are more concise when you compare them to
> an equally flexible, non-class-based solution.

Try converting something like this mini-interpreter into OOP:

http://www.ffconsultancy.com/free/ocaml/interpreter.html

You'll find that classes (or their equivalent) are needlessly verbose.

>> The way you have written this particular example, yes. Overall, OCaml is
>> typically at least as concise as Python.
>
> So then it should be obvious that OCaml is more verbose as a language
> than python.

That doesn't make sense.

>> > The key thing to note is the pattern matching required.
>>
>> There are many ways to do it without pattern matching on the outside,
>> e.g. put it in the "print" function, use OOP, typify the functions.
>
> Hiding it in the print function doesn't get rid of it--somebody still
> has to type it.

In general, that is no different in static or dynamic languages. You can
argue that it is different in this case because Python happens to provide a
boxed int type and a print function that works on it. If "eval" returned
anything more interesting then you would have to write your print function
in both languages.

> OOP in OCaml can also be rather verbose, e.g. in the
> case when OCaml can't correctly infer the interface for an argument.

If we're discussing the verbosity of languages then the differences between
OOP in OCaml and Python are unimportant.

>> Only if by "the general case" you mean anything that happens to be
>> typeable in Python.
>
> By "the general case" I'm talking about explicitly handling the error:
>
> let x = eval (get_input ()) in
> match x with
> `Int x -> print x*2
> | _ -> print "error that I don't care about!";;

You should care about your errors. For example, write a function to unbox an
int and use that:

let int = function `Int n -> n | _ -> invalid_arg "int"

print_int(int(eval(get_input())) * 2)

>> I thought structural subtyping could be entirely implicit in OCaml but I
>> won't speculate on OOP in OCaml. Suffice to say, OOP is rarely used in
>> OCaml because it provides better alternatives for most common cases.
>
> Hehe. I wonder if you meant to say "doesn't provide." In any event,
> it's not surprising that OOP isn't often used in OCaml, based on the
> community's preference for inflexibility.

Again, there is no evidence for any of that. You can try to retreat into a
debate about "flexibility", whatever you think that is today, but that
doesn't make OCaml more verbose.

Brendan Guild

unread,
Aug 20, 2006, 11:24:16 PM8/20/06
to
Jon Harrop wrote in
news:44e918ae$0$3594$ed2e...@ptn-nntp-reader04.plus.net:

> Brendan Guild wrote:
>> Of course you are correct that a type system can be Turing
>> complete, though in practice it is not something I have seen.
>
> C++?

That is rather embarrassing! I did know that C++ templates were
Turing complete, but I had forgotten. It certainly does not seem as
if it should be Turing complete at first glance. Let us just forget I
mentioned that.

>> On the other hand, heterogeneous lists have more power than merely
>> that; they can do things which even a Turing complete static type
>> system cannot allow.
>
> In as much as that is true, it is a tautology.

I might have called it a tautology until it became controversial. At
least I know of one person who does not believe that it is true. It
has been claimed that the full power of heterogeneous lists is
available in static type systems. As counter-intuitive as that may
seem, it is at least something to discuss.

> You can implement dynamic languages in static languages, so you're
> not losing anything. At worst, you have simply made some things
> more difficult. It is more difficult to create a list of values
> where each value is of a different type. However, that data
> structure is useless in practice so people using statically typed
> languages simply don't care.

People often do not miss what their language does not provide because
they are so used to working with that language. I so much prefer
statically typed languages that I cannot think of a good use for
heterogeneous lists, but I am sure that someone who works extensively
with dynamically typed languages could easily illustrate one.

Also, when you say that we are not losing anything, you mean only in
the sense that statically typed languages are Turing complete, which
no one doubts. Losing programmer time and effort, increasing
debugging time, increasing complexity of design, reducing readability
and maintainability: while these are theoretically 'nothing', I think
they are actually quite important!

Curtis W

unread,
Aug 20, 2006, 11:57:11 PM8/20/06
to
Brendan Guild wrote:
> Curtis W wrote in
> news:1156122906.7...@p79g2000cwp.googlegroups.com:
>
> > Brendan Guild wrote:
> >> It is as easy as this: take the format string from the input to
> >> the program. Now a dynamically typed language can use a truely
> >> heterogeneous list to store and use values as described by the
> >> format string, but a statically typed language can never create a
> >> list with such power, simply because the necessary information
> >> does not exist early enough.
> > That's where an 'any' type would come in.
>
> Except that in a statically typed language, you would only be allowed
> to preform operations that can apply to any type, which is likely to
> be a uselessly small number of operations.
What makes you think that? It's perfectly possible to downcast in a
type-safe manner. See: OCaml.

> Another way in which a dynamically typed language can work with
> heterogeneous lists is that it can allow type errors to occur and be
> thrown as exceptions, then catch the exception and continue
> processing the list. That sort of algorithm can apply to lists whose
> elements have any types at all, with no restrictions. Surely that is
> truly heterogeneous.

Exceptions being thrown is a commonality.

> >> There are two meanings of "Language A can do B" that are distinct
> >> in this case. In the case of Turing machines and Turing
> >> completeness, a language can do B if it can compute the function
> >> that B represents. Turing complete languages can do any B that a
> >> Turing machine can.
> >>
> >> When we say that language A can do B in the sense of language
> >> properties, we are talking about the operations that are
> >> considered legal in the language definition.
> > I suggest you use clearer terminology in the future--I don't know
> > how I was supposed to know you redefined the word "do."
>
> It seemed to be already redefined when I got here. I was just trying
> to point out the two meanings of the word so that they could be used
> deliberately, in case that unintentional usage was causing confusion.

I've always used the normal meaning of the word and I've assumed
everybody else has, too.

> Let us look back at where this started:
> Curtis W previously wrote:
> > Robbert Haarman wrote:
> >> In a statically typed language, you would be limited to those
> >> operations that are supported by all elements - which, for a truly
> >> heterogenous list, would be none, and thus, indeed, the list would
> >> be useless.
> >
> > No. If that were true, you'd be saying statically typed languages
> > aren't turing complete. Statically typed languages are able to do
> > anything dynamic languages can, so I'm not sure where you're
> > getting this from.
>
> Here it looks like you are twisting the meaning of 'do' around. The
> only inference you can make about what a language can 'do' from the
> fact that it is Turing complete is that it can represent a program to
> compute any function that a Turing machine can compute.

No, I'm not. Any program written in any programming language can do
anything any other program can do.

> Curtis W wrote:
> > Brendan Guild wrote:
> >> In statically typed languages heterogeneous lists are illegal.
> >> This is a statement about language properties and it is
> >> completely orthogonal to the property of being Turing complete.
> > Here, let me rephrase that for you:
> >
> > "In statically typed languages heterogenous lists require more
> > effort to use compared to dynamically typed languages."
>
> It is poor practice to change the meaning of a statement when you
> rephrase it. Requiring effort and being illegal are very different
> problems.

What do you gain by comparing two languages on such a superficial
level? So one language doesn't do something exactly the same as
another, that's _why_ they're different.

> > In this case, I agree. I was never arguing that, so I have no
> > problem admitting that you're right on this point.
>
> I am surprised that you did not agree with my actual statement, since
> you were saying that heterogeneous lists do not exist in any
> language.

Generally when people say "heterogenous lists" I assume they mean
easily-extensible homogenous lists. If I'm talking about truly
heterogenous lists, I say "truly heterogenous lists" ;-)

Curtis W

unread,
Aug 21, 2006, 12:11:52 AM8/21/06
to
Jon Harrop wrote:
> Curtis W wrote:
> > Classes (or their equivalent) are more concise when you compare them to
> > an equally flexible, non-class-based solution.
>
> Try converting something like this mini-interpreter into OOP:
>
> http://www.ffconsultancy.com/free/ocaml/interpreter.html
>
> You'll find that classes (or their equivalent) are needlessly verbose.
I'm sure they would be, assuming you're alluding to the compactness of
pattern matching. What you fail to realize, however, is that in a
completely class-based system you're going to have a lot of member
functions (a vanilla python class starts out with 15) which otherwise
would have to be passed around manually.

> >> The way you have written this particular example, yes. Overall, OCaml is
> >> typically at least as concise as Python.
> >
> > So then it should be obvious that OCaml is more verbose as a language
> > than python.
>
> That doesn't make sense.

in most cases python verbosity = OCaml verbosity
in some cases python verbosity < OCaml verbosity
total OCaml verbosity = python verbosity + added verbosity
python verbosity < OCaml verbosity

> >> > The key thing to note is the pattern matching required.
> >>
> >> There are many ways to do it without pattern matching on the outside,
> >> e.g. put it in the "print" function, use OOP, typify the functions.
> >
> > Hiding it in the print function doesn't get rid of it--somebody still
> > has to type it.
>
> In general, that is no different in static or dynamic languages. You can
> argue that it is different in this case because Python happens to provide a
> boxed int type and a print function that works on it. If "eval" returned
> anything more interesting then you would have to write your print function
> in both languages.

Overall work is what matters, not necessarily what's visible to the
programmer. After all, if you're going to go to such great lengths to
emulate it, why not just use it?

> >> Only if by "the general case" you mean anything that happens to be
> >> typeable in Python.
> >
> > By "the general case" I'm talking about explicitly handling the error:
> >
> > let x = eval (get_input ()) in
> > match x with
> > `Int x -> print x*2
> > | _ -> print "error that I don't care about!";;
>
> You should care about your errors. For example, write a function to unbox an
> int and use that:
>
> let int = function `Int n -> n | _ -> invalid_arg "int"
>
> print_int(int(eval(get_input())) * 2)
>

I don't like forcing methodologies on other people. Most of the time, I
don't care about errors. Unhandled exceptions are generally fine, but
that still leaves the door open for people who do want to handle them.

> >> I thought structural subtyping could be entirely implicit in OCaml but I
> >> won't speculate on OOP in OCaml. Suffice to say, OOP is rarely used in
> >> OCaml because it provides better alternatives for most common cases.
> >
> > Hehe. I wonder if you meant to say "doesn't provide." In any event,
> > it's not surprising that OOP isn't often used in OCaml, based on the
> > community's preference for inflexibility.
>
> Again, there is no evidence for any of that. You can try to retreat into a
> debate about "flexibility", whatever you think that is today, but that
> doesn't make OCaml more verbose.

Not directly. OCaml becomes verbose when the programmer needs
flexibility, since it defaults to inflexiblility and speed/typeability.

Robbert Haarman

unread,
Aug 21, 2006, 2:45:29 AM8/21/06
to
On Mon, Aug 21, 2006 at 03:21:42AM +0100, Jon Harrop wrote:
> Brendan Guild wrote:
>
> > In statically typed languages heterogeneous lists are illegal.
>
> Again, this statement is so limited in applicability that it is useless.

Note that I brought up heterogenous lists just as one example of
something that is legal under dynamic typing, but not static typing.
There are certainly other examples.

> You can implement dynamic languages in static languages, so you're not
> losing anything.

We can as well stop developing Ocaml. You can implement it in x86
assembly, so you're not really losing anything.

> At worst, you have simply made some things more difficult.

Well, that's the point, really. Of course, you can implement a program
that produces the same outputs from the same inputs, given a program in
a dynamically typed language that uses heterogenous lists, or any other
construct not allowed under static typing. That's what it means for both
languages to be Turing complete. The point is that the dynamic typing
allows things that static typing disallows (by definition!), and thus,
all else being equal, dynamic typing is more expressive.

Regards,

Bob

---
#include <stdio.h>
#define SIX 1 + 5
#define NINE 8 + 1
int main(int argc, char **argv) {
return printf("When you multiply SIX by NINE, you get %d\n",
SIX * NINE);
}


Robbert Haarman

unread,
Aug 21, 2006, 3:06:01 AM8/21/06
to
On Sun, Aug 20, 2006 at 06:15:06PM -0700, Curtis W wrote:
> Brendan Guild wrote:
> > It is as easy as this: take the format string from the input to the
> > program. Now a dynamically typed language can use a truely
> > heterogeneous list to store and use values as described by the format
> > string, but a statically typed language can never create a list with
> > such power, simply because the necessary information does not exist
> > early enough.
> That's where an 'any' type would come in.

As Brendan pointed out, such an any type would allow only operations
that can be performed on any value to be performed on the elements of
that list, regardless of their run time types. Indeed, as you pointed
out, one of these operations may be casting it to another, more useful,
type...but that doesn't counter the argument that heterogenous lists
aren't allowed under static typing.

The fact that, under dynamic typing, the values in the list can be used
with type-specific operations without requiring a cast shows that
they've retained their own types (rather than having been coerced into a
common supertype), and thus that the list may be heterogenous. At least,
that's how I see it; clearly, you don't share that view - but I think
it's a matter of definitions...there is definitely something more
heterogenous about a list containing integers and strings than a list
containing only anys.

Also, as far as I can see, when you're casting these values, one of two
things happens: either the cast is checked at run time (dynamic
typing!), or it is not checked at all (loss of type safety). Either way,
you lose static typing.

> > >> Simulating a dynamically typed language that allows such
> > >> assignments and then making the assignment in that language is
> > >> not the same as making that assignment in C.
> > > No. It is true that the C compiler won't be able to type check it,
> > > but it's certainly still possible.
> >
> > There are two meanings of "Language A can do B" that are distinct in
> > this case. In the case of Turing machines and Turing completeness, a
> > language can do B if it can compute the function that B represents.
> > Turing complete languages can do any B that a Turing machine can.
> >
> > When we say that language A can do B in the sense of language
> > properties, we are talking about the the operations that are
> > considered legal in the language definition.
> I suggest you use clearer terminology in the future--I don't know how I
> was supposed to know you redefined the word "do."

It certainly wasn't Brendan who redefined the word "do". In fact, I'm
very grateful he brought this up, because now I clearly see what has
been happening. You have been using "do" as in, "given a program in
language A, you can write a program that produces the same outputs from
the same inputs" (assuming both languages are Turing complete). I was
using "do" w.r.t. specific language features, e.g. you can put elements
of disjoint types in a single list in dynamically typed languages, or
you can add an integer to a float in C.

To me, the "you can implement an equivalent program" argument is
irrelevant...the point is that dynamic typing allows certain specific
expressions that static typing rejects.

> > In statically typed languages heterogeneous lists are illegal. This
> > is a statement about language properties and it is completely
> > orthogonal to the property of being Turing complete.
> Here, let me rephrase that for you:
>
> "In statically typed languages heterogenous lists require more effort
> to use compared to dynamically typed languages."
>
> In this case, I agree. I was never arguing that, so I have no problem
> admitting that you're right on this point.

The problem is, you and I haven't been able to agree on what
heterogenous lists are. With my definition (elements may have any type,
without this putting any restrictions on the operations that may
subsequently be applied to elements), static typing doesn't allow
heterogenous lists at all. Not even with more effort. It just isn't
compatible with static typing (except perhaps in corner cases, where the
types of all elements can be determined statically).

Regards,

Bob

---
In theory there is no difference between theory and practice, but in practice
there is.

Jon Harrop

unread,
Aug 21, 2006, 6:00:38 AM8/21/06
to
Curtis W wrote:
> Jon Harrop wrote:
>> Curtis W wrote:
>> > Classes (or their equivalent) are more concise when you compare them to
>> > an equally flexible, non-class-based solution.
>>
>> Try converting something like this mini-interpreter into OOP:
>>
>> http://www.ffconsultancy.com/free/ocaml/interpreter.html
>>
>> You'll find that classes (or their equivalent) are needlessly verbose.
>
> I'm sure they would be, assuming you're alluding to the compactness of
> pattern matching. What you fail to realize, however, is that in a
> completely class-based system you're going to have a lot of member
> functions (a vanilla python class starts out with 15) which otherwise
> would have to be passed around manually.

We really need to ossify this with examples. Try converting the interpreter
from that page into Python and I think you'll find it is a lot more verbose
than the OCaml. I am sure there are cases where OOP can save you some space
but they are few and far between and can also be implemented in OCaml.

>> >> The way you have written this particular example, yes. Overall, OCaml
>> >> is typically at least as concise as Python.
>> >
>> > So then it should be obvious that OCaml is more verbose as a language
>> > than python.
>>
>> That doesn't make sense.
>
> in most cases python verbosity = OCaml verbosity

I said "at least as concise", so:

in most cases python verbosity >= OCaml verbosity

>> In general, that is no different in static or dynamic languages. You can


>> argue that it is different in this case because Python happens to provide
>> a boxed int type and a print function that works on it. If "eval"
>> returned anything more interesting then you would have to write your
>> print function in both languages.
>
> Overall work is what matters, not necessarily what's visible to the
> programmer. After all, if you're going to go to such great lengths to
> emulate it, why not just use it?

Because it costs you static typing everywhere else, greatly increasing the
amount of work required to write everything apart from your heterogeneous
list. Moreover, I've never needed a heterogeneous list.

>> print_int(int(eval(get_input())) * 2)
>
> I don't like forcing methodologies on other people.

Like dynamic typing?

> Most of the time, I
> don't care about errors. Unhandled exceptions are generally fine, but
> that still leaves the door open for people who do want to handle them.

People who want to handle exceptions can use an exception handler.

>> Again, there is no evidence for any of that. You can try to retreat into
>> a debate about "flexibility", whatever you think that is today, but that
>> doesn't make OCaml more verbose.
>
> Not directly. OCaml becomes verbose when the programmer needs
> flexibility, since it defaults to inflexiblility and speed/typeability.

That would be the retreat. Real programs are usually more concise in OCaml
AFAIK.

Jon Harrop

unread,
Aug 21, 2006, 6:04:58 AM8/21/06
to
Brendan Guild wrote:
> Also, when you say that we are not losing anything, you mean only in
> the sense that statically typed languages are Turing complete, which
> no one doubts. Losing programmer time and effort, increasing
> debugging time, increasing complexity of design, reducing readability
> and maintainability: while these are theoretically 'nothing', I think
> they are actually quite important!

Indeed, they are pivotal and I disagree with all of them. IMHO, static
typing leads to faster development, equal readability and better
maintainability.

Jon Harrop

unread,
Aug 21, 2006, 6:13:21 AM8/21/06
to
Brendan Guild wrote:
> Except that in a statically typed language, you would only be allowed
> to preform operations that can apply to any type, which is likely to
> be a uselessly small number of operations.

If your list elements are objects then you could apply any methods that they
have in common.

> I am talking about a set of types which share no commonality except
> for that which they are given at runtime. I would call that 'truly
> heterogeneous'; it is certainly heterogeneous enough to be impossible
> to handle statically.

Can you give any examples where such a "truly heterogeneous" list might be
useful?

> Another way in which a dynamically typed language can work with
> heterogeneous lists is that it can allow type errors to occur and be
> thrown as exceptions, then catch the exception and continue
> processing the list.

You can do that in OCaml.

Robbert Haarman

unread,
Aug 21, 2006, 7:02:01 AM8/21/06
to
On Mon, Aug 21, 2006 at 11:13:21AM +0100, Jon Harrop wrote:
> Brendan Guild wrote:
> > Except that in a statically typed language, you would only be allowed
> > to preform operations that can apply to any type, which is likely to
> > be a uselessly small number of operations.
>
> If your list elements are objects then you could apply any methods that they
> have in common.

Yes, and the point is that, under dynamic typing, you're _not_
restricted to only operations that they have in common.

> > I am talking about a set of types which share no commonality except
> > for that which they are given at runtime. I would call that 'truly
> > heterogeneous'; it is certainly heterogeneous enough to be impossible
> > to handle statically.
>
> Can you give any examples where such a "truly heterogeneous" list might be
> useful?

That's besides the point; the point was to provide an example of how
static typing rejects programs that would be valid under dynamic typing.

The only reason I brought up heterogenous lists was as an illustration
of how static typing restricts you in the programs you can write. It was
never my intention to suggest that this makes dynamic typing better, or
that this is a real problem for statically typed languages. Maybe this
restriction is actually a Good Thing.

Regards,

Bob

---
A policeman pulls Werner Heisenberg over on the Autobahn for speeding.

Policeman: Sir, do you know how fast you were going?
Heisenberg: No, but I know exactly where I am.


Curtis W

unread,
Aug 21, 2006, 12:25:15 PM8/21/06
to
Robbert Haarman wrote:
> On Sun, Aug 20, 2006 at 06:15:06PM -0700, Curtis W wrote:
> > Brendan Guild wrote:
> > > It is as easy as this: take the format string from the input to the
> > > program. Now a dynamically typed language can use a truely
> > > heterogeneous list to store and use values as described by the format
> > > string, but a statically typed language can never create a list with
> > > such power, simply because the necessary information does not exist
> > > early enough.
> > That's where an 'any' type would come in.
>
> As Brendan pointed out, such an any type would allow only operations
> that can be performed on any value to be performed on the elements of
> that list, regardless of their run time types. Indeed, as you pointed
> out, one of these operations may be casting it to another, more useful,
> type...but that doesn't counter the argument that heterogenous lists
> aren't allowed under static typing.
Actually, truly heterogenous lists are, and just like in dynamic
typing, they're completely useless since you can't actually do anything
to the elements. If you're talking about partially heterogenous lists,
then those also are allowed, just that you can't do as much with them
directly as in dynamic languages. While this conclusion is true, I
still don't like the use of the word "allowed"--would you say a horse
can't move compared to a car because it doesn't have wheels? After all,
it can be assumed that both horses and cars can move just as the other
can, so we can just ignore the implication and assume that the
statement reflects the fact that horses and cars move in a different
way.

> The fact that, under dynamic typing, the values in the list can be used
> with type-specific operations without requiring a cast shows that
> they've retained their own types (rather than having been coerced into a
> common supertype), and thus that the list may be heterogenous. At least,
> that's how I see it; clearly, you don't share that view - but I think
> it's a matter of definitions...there is definitely something more
> heterogenous about a list containing integers and strings than a list
> containing only anys.

Actually, most dynamically typed languages have lists which handle
values of 'any' type, so in reality the difference is that in
dynamically typed languages no casting or coercion is required to
access subclasses.

> Also, as far as I can see, when you're casting these values, one of two
> things happens: either the cast is checked at run time (dynamic
> typing!), or it is not checked at all (loss of type safety). Either way,
> you lose static typing.

Casting can be checked at runtime and still be considered static, since
the programmer has to manually tell the compiler to do it.

Yes, although again, the wording of this is somewhat deceptive. The
fact that it's "rejected" isn't the important part; rather, the fact
that it takes more effort to get an equivalent effect is what really
matters.

Curtis W

unread,
Aug 21, 2006, 12:40:27 PM8/21/06
to
Jon Harrop wrote:
> Curtis W wrote:
> > Jon Harrop wrote:
> >> Curtis W wrote:
> >> > Classes (or their equivalent) are more concise when you compare them to
> >> > an equally flexible, non-class-based solution.
> >>
> >> Try converting something like this mini-interpreter into OOP:
> >>
> >> http://www.ffconsultancy.com/free/ocaml/interpreter.html
> >>
> >> You'll find that classes (or their equivalent) are needlessly verbose.
> >
> > I'm sure they would be, assuming you're alluding to the compactness of
> > pattern matching. What you fail to realize, however, is that in a
> > completely class-based system you're going to have a lot of member
> > functions (a vanilla python class starts out with 15) which otherwise
> > would have to be passed around manually.
>
> We really need to ossify this with examples. Try converting the interpreter
> from that page into Python and I think you'll find it is a lot more verbose
> than the OCaml. I am sure there are cases where OOP can save you some space
> but they are few and far between and can also be implemented in OCaml.
Do you know how verbose passing around 15 functions and the data they
operate on can get? That is the only way to get the same amount of
flexibility without using classes, so don't try and argue that you
don't need to include some of them (what happens if you need it
later?).

> >> >> The way you have written this particular example, yes. Overall, OCaml
> >> >> is typically at least as concise as Python.
> >> >
> >> > So then it should be obvious that OCaml is more verbose as a language
> >> > than python.
> >>
> >> That doesn't make sense.
> >
> > in most cases python verbosity = OCaml verbosity
>
> I said "at least as concise", so:
>
> in most cases python verbosity >= OCaml verbosity

Possibly, but only if you fail to code the equivalent amount of
flexibility into the OCaml version.

> >> In general, that is no different in static or dynamic languages. You can
> >> argue that it is different in this case because Python happens to provide
> >> a boxed int type and a print function that works on it. If "eval"
> >> returned anything more interesting then you would have to write your
> >> print function in both languages.
> >
> > Overall work is what matters, not necessarily what's visible to the
> > programmer. After all, if you're going to go to such great lengths to
> > emulate it, why not just use it?
>
> Because it costs you static typing everywhere else, greatly increasing the
> amount of work required to write everything apart from your heterogeneous
> list.

> Moreover, I've never needed a heterogeneous list.

Neither have I. (yes, I'm talking about "actual" heterogenous lists,
not the theoretical ones which aren't useful)

> >> print_int(int(eval(get_input())) * 2)
> >
> > I don't like forcing methodologies on other people.
>
> Like dynamic typing?

No, like error handling. There's a reason so many people despise
checked exceptions (and static typing, for that matter).

> > Most of the time, I
> > don't care about errors. Unhandled exceptions are generally fine, but
> > that still leaves the door open for people who do want to handle them.
>
> People who want to handle exceptions can use an exception handler.

If only type errors happened at runtime. Oh wait, they do in dynamic
languages!

> >> Again, there is no evidence for any of that. You can try to retreat into
> >> a debate about "flexibility", whatever you think that is today, but that
> >> doesn't make OCaml more verbose.
> >
> > Not directly. OCaml becomes verbose when the programmer needs
> > flexibility, since it defaults to inflexiblility and speed/typeability.
>
> That would be the retreat. Real programs are usually more concise in OCaml
> AFAIK.

When I can do this in OCaml I'll retract my statement:

let rec factorial = function
1 -> 1
| x -> x * (factorial x-1);;

factorial 4.0;;

or even better:

4.0#factorial();;

Brendan Guild

unread,
Aug 21, 2006, 3:17:01 PM8/21/06
to
Curtis W wrote in
news:1156177515.4...@74g2000cwt.googlegroups.com:
> Robbert Haarman wrote:
>> As Brendan pointed out, such an any type would allow only
>> operations that can be performed on any value to be performed on
>> the elements of that list, regardless of their run time types.
>> Indeed, as you pointed out, one of these operations may be
>> casting it to another, more useful, type...but that doesn't
>> counter the argument that heterogenous lists aren't allowed under
>> static typing.
>
> Actually, truly heterogenous lists are, and just like in dynamic
> typing, they're completely useless since you can't actually do
> anything to the elements. If you're talking about partially
> heterogenous lists, then those also are allowed, just that you
> can't do as much with them directly as in dynamic languages.

This is a strangely static-centric point of view for someone in favor
of dynamic typing. Naturally, Haarman was talking about truly
heterogeneous lists, but they are only completely useless in static
typing languages.

> While this conclusion is true, I still don't like the use of the
> word "allowed"--would you say a horse can't move compared to a car
> because it doesn't have wheels? After all, it can be assumed that
> both horses and cars can move just as the other can, so we can
> just ignore the implication and assume that the statement reflects
> the fact that horses and cars move in a different way.

"Allowed" is a perfect word for it. Every language in the world has
things which are allowed and things which are forbidden. C++, OCaml,
Ruby, English, etc. Sometimes people even talk about a language as if
it were exactly the set of programs that can be written in it. In
other words, every language has programs which cannot be written,
despite being Turing complete. Finally, some languages have lists
that can hold anything in any element, and some simply do not.

If you consider this to be a problem, there are always ways to get
around it; we know that from the fact that the language is Turing
complete, but let us not pretend that the problem does not exist.



> Actually, most dynamically typed languages have lists which handle
> values of 'any' type, so in reality the difference is that in
> dynamically typed languages no casting or coercion is required to
> access subclasses.

That is an important difference. In a very statically typed language,
there should not be casting. I've read that OCaml allows type-safe
downcasting, but to me it looks like in OCaml there are no downcasts
allowed or required for the usual uses for that operation.

Any static typing language, even if it allows casting, is still more
restrictive than a dynamic typing language. In order to cast you need
two things: there must exist a type that describes the set of values
that you want to operate on, and you must know the name of that type
in advance.

OCaml is interesting because every set of operations has its own
object type, so there is no restriction in that sense, but OCaml does
not allow casting because the combination of the two would be
extremely unsafe.

Even if you go through the effort of setting up a class hierarchy to
allow exactly the casts that you need for the list, you still don't
have a truly heterogeneous list of the sort that a dynamic typing
language has.

> Casting can be checked at runtime and still be considered static,
> since the programmer has to manually tell the compiler to do it.

That is the key. It is static because the programmer has to manually
tell the compiler to do it and it ruins truly heterogeneous lists for
exactly the same reason.

First, casting gives your code an explicit, finite list of all the
types it can handle, which is in no way required in a dynamic typing
language.

Second, casting is an operation or a set of operations. It has been
pointed out in many ways all the subtle things which are actually
commonalities between elements of a list that sneak up and destroy
what seem to be heterogeneous lists. After all that, I have no doubt
that it can be widely agreed that sharing a set of operations is a
commonality. When those operations are casts, the commonality does
not exist in dynamic typing languages.

>> To me, the "you can implement an equivalent program" argument is
>> irrelevant...the point is that dynamic typing allows certain
>> specific expressions that static typing rejects.
> Yes, although again, the wording of this is somewhat deceptive.
> The fact that it's "rejected" isn't the important part; rather,
> the fact that it takes more effort to get an equivalent effect is
> what really matters.

That is why you cannot dismiss heterogeneous lists from the debate
between static and dynamic typing. The fact that one requires more
effort to achieve the same effect can be very important.

Jon Harrop

unread,
Aug 21, 2006, 4:18:57 PM8/21/06
to
Curtis W wrote:
> Jon Harrop wrote:
>> We really need to ossify this with examples. Try converting the
>> interpreter from that page into Python and I think you'll find it is a
>> lot more verbose than the OCaml. I am sure there are cases where OOP can
>> save you some space but they are few and far between and can also be
>> implemented in OCaml.
>
> Do you know how verbose passing around 15 functions and the data they
> operate on can get? That is the only way to get the same amount of
> flexibility without using classes, so don't try and argue that you
> don't need to include some of them (what happens if you need it
> later?).

That is not true. OOP simply gives a different (and typically less useful)
kind of flexibility. Specifically, OOP groups by type whereas variants
group by function. If you're adding new types then OOP is arguably better
because the source code changes are localised. If you're adding functions
(which is more common) then variants are better.

On the other hand, pattern matching over variants provides functionality not
exposed by OOP. For example, parallel pattern matching, variable binding,
structure matching, or-patterns, guarded patterns and so forth.

>> I said "at least as concise", so:
>>
>> in most cases python verbosity >= OCaml verbosity
>
> Possibly, but only if you fail to code the equivalent amount of
> flexibility into the OCaml version.

Again, your retreat into a subjective notion of "inflexible" is unsupported
and evades the issue anyway.

>> >> print_int(int(eval(get_input())) * 2)
>> >
>> > I don't like forcing methodologies on other people.
>>
>> Like dynamic typing?
>
> No, like error handling. There's a reason so many people despise
> checked exceptions (and static typing, for that matter).

OCaml doesn't require checked exceptions.

>> > Most of the time, I
>> > don't care about errors. Unhandled exceptions are generally fine, but
>> > that still leaves the door open for people who do want to handle them.
>>
>> People who want to handle exceptions can use an exception handler.
>
> If only type errors happened at runtime. Oh wait, they do in dynamic
> languages!

Static typing is about proving that run-time exceptions cannot occur.

>> > Not directly. OCaml becomes verbose when the programmer needs
>> > flexibility, since it defaults to inflexiblility and speed/typeability.
>>
>> That would be the retreat. Real programs are usually more concise in
>> OCaml AFAIK.
>
> When I can do this in OCaml I'll retract my statement:
>
> let rec factorial = function
> 1 -> 1
> | x -> x * (factorial x-1);;
>
> factorial 4.0;;

If you want to pretend that int and float are interchangeable then I'd
rather we used different languages...

> or even better:
>
> 4.0#factorial();;

How on Earth is that better than "factorial 4" or "4!"?

Jon Harrop

unread,
Aug 21, 2006, 4:42:48 PM8/21/06
to
Robbert Haarman wrote:
> On Mon, Aug 21, 2006 at 11:13:21AM +0100, Jon Harrop wrote:
>> Brendan Guild wrote:
>> > Except that in a statically typed language, you would only be allowed
>> > to preform operations that can apply to any type, which is likely to
>> > be a uselessly small number of operations.
>>
>> If your list elements are objects then you could apply any methods that
>> they have in common.
>
> Yes, and the point is that, under dynamic typing, you're _not_
> restricted to only operations that they have in common.

Sure. What is the point in collecting values if they have nothing relevant
in common?

>> > I am talking about a set of types which share no commonality except
>> > for that which they are given at runtime. I would call that 'truly
>> > heterogeneous'; it is certainly heterogeneous enough to be impossible
>> > to handle statically.
>>
>> Can you give any examples where such a "truly heterogeneous" list might
>> be useful?
>
> That's besides the point; the point was to provide an example of how
> static typing rejects programs that would be valid under dynamic typing.

My problem with your example is that it implies that types in static
languages and types in dynamic languages are equivalent. In practice, you
can easily implement a dynamic type system in a language like OCaml. So the
difference is only that you must box your values in the statically typed
language.

> The only reason I brought up heterogenous lists was as an illustration
> of how static typing restricts you in the programs you can write. It was
> never my intention to suggest that this makes dynamic typing better, or
> that this is a real problem for statically typed languages. Maybe this
> restriction is actually a Good Thing.

I don't think it is a good thing. I think it is unimportant.

Dynamic typing can be better under certain circumstances though. For
example, when type information is not available statically in most of the
program (e.g. XML-RPC bindings) or when you're dealing with run-time
generated code.

Jon Harrop

unread,
Aug 21, 2006, 5:03:01 PM8/21/06
to
Brendan Guild wrote:
> Curtis W wrote in
>> Actually, truly heterogenous lists are, and just like in dynamic
>> typing, they're completely useless since you can't actually do
>> anything to the elements. If you're talking about partially
>> heterogenous lists, then those also are allowed, just that you
>> can't do as much with them directly as in dynamic languages.
>
> This is a strangely static-centric point of view for someone in favor
> of dynamic typing. Naturally, Haarman was talking about truly
> heterogeneous lists, but they are only completely useless in static
> typing languages.

Having them as the only available construct in most dynamically typed
languages does not make them useful, it makes them the only option.

>> While this conclusion is true, I still don't like the use of the
>> word "allowed"--would you say a horse can't move compared to a car
>> because it doesn't have wheels? After all, it can be assumed that
>> both horses and cars can move just as the other can, so we can
>> just ignore the implication and assume that the statement reflects
>> the fact that horses and cars move in a different way.
>
> "Allowed" is a perfect word for it. Every language in the world has
> things which are allowed and things which are forbidden. C++, OCaml,
> Ruby, English, etc. Sometimes people even talk about a language as if
> it were exactly the set of programs that can be written in it. In
> other words, every language has programs which cannot be written,
> despite being Turing complete. Finally, some languages have lists
> that can hold anything in any element, and some simply do not.

No. Such lists can hold any value from the dynamic type system.

> If you consider this to be a problem, there are always ways to get
> around it; we know that from the fact that the language is Turing
> complete, but let us not pretend that the problem does not exist.

The problem does not exist.

> Any static typing language, even if it allows casting, is still more
> restrictive than a dynamic typing language. In order to cast you need
> two things: there must exist a type that describes the set of values
> that you want to operate on, and you must know the name of that type
> in advance.

No. The type may be inferred and anonymous.

> Even if you go through the effort of setting up a class hierarchy to
> allow exactly the casts that you need for the list, you still don't
> have a truly heterogeneous list of the sort that a dynamic typing
> language has.

This debate is only going places if anyone can provide a real example of
code that leverages these mysterious "truly heterogeneous lists". So far,
it seems they are both purely theoretical and purely useless.

> First, casting gives your code an explicit, finite list of all the
> types it can handle, which is in no way required in a dynamic typing
> language.

One of those types could be "any", in which case this difference between
static and dynamic typing vanishes.

>> Yes, although again, the wording of this is somewhat deceptive.
>> The fact that it's "rejected" isn't the important part; rather,
>> the fact that it takes more effort to get an equivalent effect is
>> what really matters.
>
> That is why you cannot dismiss heterogeneous lists from the debate
> between static and dynamic typing. The fact that one requires more
> effort to achieve the same effect can be very important.

You might be able to substantiate "requires more code" but you cannot
substantiate "requires more effort" without taking into account the change
in development speed due to static typing.

Curtis W

unread,
Aug 21, 2006, 5:42:41 PM8/21/06
to
Jon Harrop wrote:
> Curtis W wrote:
> > Jon Harrop wrote:
> >> We really need to ossify this with examples. Try converting the
> >> interpreter from that page into Python and I think you'll find it is a
> >> lot more verbose than the OCaml. I am sure there are cases where OOP can
> >> save you some space but they are few and far between and can also be
> >> implemented in OCaml.
> >
> > Do you know how verbose passing around 15 functions and the data they
> > operate on can get? That is the only way to get the same amount of
> > flexibility without using classes, so don't try and argue that you
> > don't need to include some of them (what happens if you need it
> > later?).
>
> That is not true. OOP simply gives a different (and typically less useful)
> kind of flexibility.
Ah, but it's still flexibility, and it's usefulness is up to the
programmer.

> Specifically, OOP groups by type whereas variants
> group by function. If you're adding new types then OOP is arguably better
> because the source code changes are localised. If you're adding functions
> (which is more common) then variants are better.

Those are misnomers. Certain languages force you to choose between the
two, but decent OOP/functional languages have facilities that solve the
expression problem, e.g. python and OCaml. The reason flexibility by
default is important is that it's easier to take it away later than it
is to add it.

> On the other hand, pattern matching over variants provides functionality not
> exposed by OOP. For example, parallel pattern matching, variable binding,
> structure matching, or-patterns, guarded patterns and so forth.

To an extent, yes. I'm not trying to say OOP is the best solution for
everything; rather, it's the best solution for most things. Certainly
pattern matching is great when you only need to extend along the
algorithm boundary and when the exotic features of pattern matching are
actually useful.

> >> I said "at least as concise", so:
> >>
> >> in most cases python verbosity >= OCaml verbosity
> >
> > Possibly, but only if you fail to code the equivalent amount of
> > flexibility into the OCaml version.
>
> Again, your retreat into a subjective notion of "inflexible" is unsupported
> and evades the issue anyway.

I've already shown you why non-OO OCaml is inflexible--if you don't
pass around the functions that operate on the data, you end up with a
mess of dependencies and it becomes impossible to extend the types
without recompiling that function. This is especially bad in libraries,
where people generally don't have the luxury of recompiling it every
time they want to create a new type.

> >> >> print_int(int(eval(get_input())) * 2)
> >> >
> >> > I don't like forcing methodologies on other people.
> >>
> >> Like dynamic typing?
> >
> > No, like error handling. There's a reason so many people despise
> > checked exceptions (and static typing, for that matter).
>
> OCaml doesn't require checked exceptions.

It was an analogy.

> >> > Most of the time, I
> >> > don't care about errors. Unhandled exceptions are generally fine, but
> >> > that still leaves the door open for people who do want to handle them.
> >>
> >> People who want to handle exceptions can use an exception handler.
> >
> > If only type errors happened at runtime. Oh wait, they do in dynamic
> > languages!
>
> Static typing is about proving that run-time exceptions cannot occur.

Ah, but what if I want them to occur? Furthermore, I fail to see how
warnings can't do the same.

> >> > Not directly. OCaml becomes verbose when the programmer needs
> >> > flexibility, since it defaults to inflexiblility and speed/typeability.
> >>
> >> That would be the retreat. Real programs are usually more concise in
> >> OCaml AFAIK.
> >
> > When I can do this in OCaml I'll retract my statement:
> >
> > let rec factorial = function
> > 1 -> 1
> > | x -> x * (factorial x-1);;
> >
> > factorial 4.0;;
>
> If you want to pretend that int and float are interchangeable then I'd
> rather we used different languages...

Who said those were normal ints and floats? Let's just stipulate that
'4.0' has the exact same semantics as '4' besides the difference in
precision.

> > or even better:
> >
> > 4.0#factorial();;
>
> How on Earth is that better than "factorial 4" or "4!"?

Let's say I have some random function:

let foo x = x#factorial() + x;;

Because 'factorial' and '+' are both member functions of x, I can
easily pass in a custom, let's say bignum class, and it will still work
as expected without modification.

Curtis W

unread,
Aug 21, 2006, 5:55:12 PM8/21/06
to
Jon Harrop wrote:
> Curtis W wrote:
> > Jon Harrop wrote:
> >> We really need to ossify this with examples. Try converting the
> >> interpreter from that page into Python and I think you'll find it is a
> >> lot more verbose than the OCaml. I am sure there are cases where OOP can
> >> save you some space but they are few and far between and can also be
> >> implemented in OCaml.
> >
> > Do you know how verbose passing around 15 functions and the data they
> > operate on can get? That is the only way to get the same amount of
> > flexibility without using classes, so don't try and argue that you
> > don't need to include some of them (what happens if you need it
> > later?).
>
> That is not true. OOP simply gives a different (and typically less useful)
> kind of flexibility.
Ah, but it's still flexibility, and it's usefulness is up to the
programmer.

> Specifically, OOP groups by type whereas variants


> group by function. If you're adding new types then OOP is arguably better
> because the source code changes are localised. If you're adding functions
> (which is more common) then variants are better.

Those are misnomers. Certain languages force you to choose between the
two, but decent OOP/functional languages have facilities that solve the
expression problem, e.g. python and OCaml. The reason flexibility by
default is important is that it's easier to take it away later than it
is to add it.

> On the other hand, pattern matching over variants provides functionality not


> exposed by OOP. For example, parallel pattern matching, variable binding,
> structure matching, or-patterns, guarded patterns and so forth.

To an extent, yes. I'm not trying to say OOP is the best solution for
everything; rather, it's the best solution for most things. Certainly
pattern matching is great when you only need to extend along the
algorithm boundary and when the exotic features of pattern matching are
actually useful.

> >> I said "at least as concise", so:


> >>
> >> in most cases python verbosity >= OCaml verbosity
> >
> > Possibly, but only if you fail to code the equivalent amount of
> > flexibility into the OCaml version.
>
> Again, your retreat into a subjective notion of "inflexible" is unsupported
> and evades the issue anyway.

I've already shown you why non-OO OCaml is inflexible--if you don't
pass around the functions that operate on the data, you end up with a
mess of dependencies and it becomes impossible to extend the types
without recompiling that function. This is especially bad in libraries,
where people generally don't have the luxury of recompiling it every
time they want to create a new type.

> >> >> print_int(int(eval(get_input())) * 2)


> >> >
> >> > I don't like forcing methodologies on other people.
> >>
> >> Like dynamic typing?
> >
> > No, like error handling. There's a reason so many people despise
> > checked exceptions (and static typing, for that matter).
>
> OCaml doesn't require checked exceptions.

It was an analogy.

> >> > Most of the time, I
> >> > don't care about errors. Unhandled exceptions are generally fine, but
> >> > that still leaves the door open for people who do want to handle them.
> >>
> >> People who want to handle exceptions can use an exception handler.
> >
> > If only type errors happened at runtime. Oh wait, they do in dynamic
> > languages!
>
> Static typing is about proving that run-time exceptions cannot occur.

Ah, but what if I want them to occur? Furthermore, I fail to see how
warnings can't do the same.

> >> > Not directly. OCaml becomes verbose when the programmer needs


> >> > flexibility, since it defaults to inflexiblility and speed/typeability.
> >>
> >> That would be the retreat. Real programs are usually more concise in
> >> OCaml AFAIK.
> >
> > When I can do this in OCaml I'll retract my statement:
> >
> > let rec factorial = function
> > 1 -> 1
> > | x -> x * (factorial x-1);;
> >
> > factorial 4.0;;
>
> If you want to pretend that int and float are interchangeable then I'd
> rather we used different languages...

Who said those were normal ints and floats? Let's just stipulate that
'4.0' has the exact same semantics as '4' besides the difference in
precision.

> > or even better:


> >
> > 4.0#factorial();;
>
> How on Earth is that better than "factorial 4" or "4!"?

Jon Harrop

unread,
Aug 22, 2006, 7:11:01 AM8/22/06
to
Curtis W wrote:
> Jon Harrop wrote:
>> Specifically, OOP groups by type whereas variants
>> group by function. If you're adding new types then OOP is arguably better
>> because the source code changes are localised. If you're adding functions
>> (which is more common) then variants are better.
>
> Those are misnomers. Certain languages force you to choose between the
> two, but decent OOP/functional languages have facilities that solve the
> expression problem, e.g. python and OCaml.

Neither Python nor OCaml have solved this problem, AFAIK.

> The reason flexibility by
> default is important is that it's easier to take it away later than it
> is to add it.

Again, OOP is less flexible in other, more important, ways.

>> On the other hand, pattern matching over variants provides functionality
>> not exposed by OOP. For example, parallel pattern matching, variable
>> binding, structure matching, or-patterns, guarded patterns and so forth.
>
> To an extent, yes. I'm not trying to say OOP is the best solution for
> everything; rather, it's the best solution for most things.

No, it is not. Why do you think OCaml programmers rarely use OOP?

> Certainly
> pattern matching is great when you only need to extend along the
> algorithm boundary and when the exotic features of pattern matching are
> actually useful.

Pattern matching is ubiquitous in any language which supports it.

>> Again, your retreat into a subjective notion of "inflexible" is
>> unsupported and evades the issue anyway.
>
> I've already shown you why non-OO OCaml is inflexible--

And I have already shown many more ways that it is more flexible. This is
why people use it.

> if you don't
> pass around the functions that operate on the data, you end up with a
> mess of dependencies

On the contrary, OOP leads to code with unknown execution paths.

> and it becomes impossible to extend the types
> without recompiling that function.

No, it does not. See "code reuse through polymorphic variants" by Jacques
Garrigue, for example.

> This is especially bad in libraries,
> where people generally don't have the luxury of recompiling it every
> time they want to create a new type.

You're citing a problem that doesn't exist.

>> > If only type errors happened at runtime. Oh wait, they do in dynamic
>> > languages!
>>
>> Static typing is about proving that run-time exceptions cannot occur.
>
> Ah, but what if I want them to occur?

Type errors are bugs. Why do you want bugs?

> Furthermore, I fail to see how warnings can't do the same.

Type checking is a mathematical proof. If you break bits in the middle then
you can't type check the code in between, so the whole system becomes
useless.

>> If you want to pretend that int and float are interchangeable then I'd
>> rather we used different languages...
>
> Who said those were normal ints and floats?

Ok, what are their semantics?

> Let's just stipulate that
> '4.0' has the exact same semantics as '4' besides the difference in
> precision.

I can't think of a single operation that has the same semantics between ints
and floats.

>> > or even better:
>> >
>> > 4.0#factorial();;
>>
>> How on Earth is that better than "factorial 4" or "4!"?
>
> Let's say I have some random function:
>
> let foo x = x#factorial() + x;;
>
> Because 'factorial' and '+' are both member functions of x, I can
> easily pass in a custom, let's say bignum class, and it will still work
> as expected without modification.

SML uses ad-hoc polymorphism to implement that functionality and you still
write in conventional style:

fun factorial 0 = 1
| factorial n = n * factorial(n-1)

Curtis W

unread,
Aug 22, 2006, 11:02:12 AM8/22/06
to
Jon Harrop wrote:
> Curtis W wrote:
> > Jon Harrop wrote:
> >> Specifically, OOP groups by type whereas variants
> >> group by function. If you're adding new types then OOP is arguably better
> >> because the source code changes are localised. If you're adding functions
> >> (which is more common) then variants are better.
> >
> > Those are misnomers. Certain languages force you to choose between the
> > two, but decent OOP/functional languages have facilities that solve the
> > expression problem, e.g. python and OCaml.
>
> Neither Python nor OCaml have solved this problem, AFAIK.
Well, python doesn't suffer from this problem in the first place, since
the expression problem is solely a problem of static (or soft)
languages, not dynamic. Ironically, "code reuse through polymorphic
variants," which you mention later on, is a paper that shows a solution
to the expression problem in OCaml. Maybe you should read the papers
you post before you link them ;-)

> > The reason flexibility by
> > default is important is that it's easier to take it away later than it
> > is to add it.
>
> Again, OOP is less flexible in other, more important, ways.

And those would be?

> >> On the other hand, pattern matching over variants provides functionality
> >> not exposed by OOP. For example, parallel pattern matching, variable
> >> binding, structure matching, or-patterns, guarded patterns and so forth.
> >
> > To an extent, yes. I'm not trying to say OOP is the best solution for
> > everything; rather, it's the best solution for most things.
>
> No, it is not. Why do you think OCaml programmers rarely use OOP?

Why do you think BASIC programmers use goto? OCaml obviously has a long
history of functional programming and I suspect most of its community
use it because of that fact, so its not surprising to me why nobody
uses the OO features.

> > Certainly
> > pattern matching is great when you only need to extend along the
> > algorithm boundary and when the exotic features of pattern matching are
> > actually useful.
>
> Pattern matching is ubiquitous in any language which supports it.

So is goto in BASIC, does that make it right for all situations?

> >> Again, your retreat into a subjective notion of "inflexible" is
> >> unsupported and evades the issue anyway.
> >
> > I've already shown you why non-OO OCaml is inflexible--
>
> And I have already shown many more ways that it is more flexible. This is
> why people use it.

My memory must be failing me. When did you do that?

> > if you don't
> > pass around the functions that operate on the data, you end up with a
> > mess of dependencies
>
> On the contrary, OOP leads to code with unknown execution paths.

Flexibility in general does, yes. But then, obviously this doesn't
matter much, since just a second ago you were saying that functional
programming is _more_ flexible. Well, which is it? (I'll give you a
hint: it's definitely not more flexible)

> > and it becomes impossible to extend the types
> > without recompiling that function.
>
> No, it does not. See "code reuse through polymorphic variants" by Jacques
> Garrigue, for example.

As I pointed out above, that paper is about the expression problem.
You'll notice that it actually takes an 'eval' function as an argument
so that it can be extended later on, which is basically an implicit
class. Aside from being impractical when one fully utilizes classes, it
also makes it hard to add methods since you have to update every
function signature and call site. If, for example, you wanted to add a
'print' function that works on the expression tree, you'd have to
update every 'eval' call site as well as all of the signatures. You
might say that this isn't true because 'print' isn't used within eval,
but as I pointed out before, it might very well need to be in the
future, e.g. if you want to insert a 'print' if you're debugging it.

> > This is especially bad in libraries,
> > where people generally don't have the luxury of recompiling it every
> > time they want to create a new type.
>
> You're citing a problem that doesn't exist.

Only because you don't want to see it. This "nonexistant" problem can
be seen all throughout OCaml, e.g. in its arithmetic operators.

> >> > If only type errors happened at runtime. Oh wait, they do in dynamic
> >> > languages!
> >>
> >> Static typing is about proving that run-time exceptions cannot occur.
> >
> > Ah, but what if I want them to occur?
>
> Type errors are bugs. Why do you want bugs?

What does and does not constitute a "bug" is up to the programmer. A
bug is simply an unintended action or result in a program. If it's not
unintended its not a bug. You'll probably say that an error is never
something that somebody would want to happen, which may or may not be
right. It may sound like not complaining about an error at compile time
is just brushing it under the rug, but if you read my first post you'll
see that I'm in favor of having compile time warnings, just not errors.
Do you need to be forced to write bug-free code?

> > Furthermore, I fail to see how warnings can't do the same.
>
> Type checking is a mathematical proof. If you break bits in the middle then
> you can't type check the code in between, so the whole system becomes
> useless.

If that's what the programmer wants, I'm completely fine with it.

> >> If you want to pretend that int and float are interchangeable then I'd
> >> rather we used different languages...
> >
> > Who said those were normal ints and floats?
>
> Ok, what are their semantics?

I just told you. Their semantics are identical. What they are is
besides the point: just assume that they're compatible enough with
numbers for my purposes.

> > Let's just stipulate that
> > '4.0' has the exact same semantics as '4' besides the difference in
> > precision.
>
> I can't think of a single operation that has the same semantics between ints
> and floats.

It's a good thing you're not designing a language... Besides, I already
told you they aren't traditional ints and floats.

> >> > or even better:
> >> >
> >> > 4.0#factorial();;
> >>
> >> How on Earth is that better than "factorial 4" or "4!"?
> >
> > Let's say I have some random function:
> >
> > let foo x = x#factorial() + x;;
> >
> > Because 'factorial' and '+' are both member functions of x, I can
> > easily pass in a custom, let's say bignum class, and it will still work
> > as expected without modification.
>
> SML uses ad-hoc polymorphism to implement that functionality and you still
> write in conventional style:
>
> fun factorial 0 = 1
> | factorial n = n * factorial(n-1)

Ok, so how do I use that function without importing that module?

Jon Harrop

unread,
Aug 22, 2006, 6:51:00 PM8/22/06
to
Curtis W wrote:
> Ironically, "code reuse through polymorphic
> variants," which you mention later on, is a paper that shows a solution
> to the expression problem in OCaml. Maybe you should read the papers
> you post before you link them ;-)

It addresses the expression problem but I would not call it a solution any
more than wrapping a function in a class is a solution to not having
closures.

>> Again, OOP is less flexible in other, more important, ways.
>
> And those would be?

parallel pattern matching
variable binding
structure matching
or-patterns
guarded patterns
static checking
algorithmic matching
...

>> > To an extent, yes. I'm not trying to say OOP is the best solution for
>> > everything; rather, it's the best solution for most things.
>>
>> No, it is not. Why do you think OCaml programmers rarely use OOP?
>
> Why do you think BASIC programmers use goto? OCaml obviously has a long
> history of functional programming and I suspect most of its community
> use it because of that fact, so its not surprising to me why nobody
> uses the OO features.

I came to OCaml from OOP. Now that I have learned more, I rarely use OOP.
Most OCaml programmers are the same. The reason is that OOP really doesn't
live up to its hype.

>> > Certainly
>> > pattern matching is great when you only need to extend along the
>> > algorithm boundary and when the exotic features of pattern matching are
>> > actually useful.
>>
>> Pattern matching is ubiquitous in any language which supports it.
>
> So is goto in BASIC,

Untrue and irrelevant.

>> >> Again, your retreat into a subjective notion of "inflexible" is
>> >> unsupported and evades the issue anyway.
>> >
>> > I've already shown you why non-OO OCaml is inflexible--
>>
>> And I have already shown many more ways that it is more flexible. This is
>> why people use it.
>
> My memory must be failing me. When did you do that?

http://groups.google.co.uk/group/comp.lang.misc/msg/ce110b3cfe3811c5?hl=en&

>> > if you don't
>> > pass around the functions that operate on the data, you end up with a
>> > mess of dependencies
>>
>> On the contrary, OOP leads to code with unknown execution paths.
>
> Flexibility in general does, yes. But then, obviously this doesn't
> matter much, since just a second ago you were saying that functional
> programming is _more_ flexible.

Straw man. I haven't even mentioned functional programming.

However, first class lexical closures are also more capable than OOP in that
the compiler captures environment for you.

> Well, which is it? (I'll give you a hint: it's definitely not more
> flexible)

I've just given another specific example.

Again, I dare you to try translating my interpreter or symbolic code into
OOP. Incidentally, do you have a simple (say <300LOC) program that is
ideally suited to OOP that I can try to translate into idiomatic OCaml?

>> > and it becomes impossible to extend the types
>> > without recompiling that function.
>>
>> No, it does not. See "code reuse through polymorphic variants" by Jacques
>> Garrigue, for example.
>
> As I pointed out above, that paper is about the expression problem.
> You'll notice that it actually takes an 'eval' function as an argument
> so that it can be extended later on,

Yes.

> which is basically an implicit class.

It has nothing to do with classes.

> Aside from being impractical when one fully utilizes classes,

No classes.

> it
> also makes it hard to add methods since you have to update every
> function signature

Type inference.

> and call site.
> If, for example, you wanted to add a
> 'print' function that works on the expression tree, you'd have to
> update every 'eval' call site as well as all of the signatures. You
> might say that this isn't true because 'print' isn't used within eval,
> but as I pointed out before, it might very well need to be in the
> future, e.g. if you want to insert a 'print' if you're debugging it.

Just call the "print" function from the body of the "eval" function.

>> > This is especially bad in libraries,
>> > where people generally don't have the luxury of recompiling it every
>> > time they want to create a new type.
>>
>> You're citing a problem that doesn't exist.
>
> Only because you don't want to see it. This "nonexistant" problem can
> be seen all throughout OCaml, e.g. in its arithmetic operators.

Use the higher-order module system or higher-order functions.

>> Type errors are bugs. Why do you want bugs?
>
> What does and does not constitute a "bug" is up to the programmer. A
> bug is simply an unintended action or result in a program. If it's not
> unintended its not a bug. You'll probably say that an error is never
> something that somebody would want to happen, which may or may not be
> right. It may sound like not complaining about an error at compile time
> is just brushing it under the rug, but if you read my first post you'll
> see that I'm in favor of having compile time warnings, just not errors.
> Do you need to be forced to write bug-free code?

Static checking helps remove bugs.

>> > Who said those were normal ints and floats?
>>
>> Ok, what are their semantics?
>
> I just told you.

No, you didn't. You said "Who said those were normal ints and floats?".

> Their semantics are identical. What they are is
> besides the point: just assume that they're compatible enough with
> numbers for my purposes.

Famous last words.

>> > Let's just stipulate that
>> > '4.0' has the exact same semantics as '4' besides the difference in
>> > precision.
>>
>> I can't think of a single operation that has the same semantics between
>> ints and floats.
>
> It's a good thing you're not designing a language...

Evasive and non-specific. The fact is, ints and floats have sufficiently
little in common that it is a bad idea to pretend that they are
interchangeable.

> Besides, I already told you they aren't traditional ints and floats.

What are they? Mineral? Celebrity? I know! They are both singleton types
containing only 4 but one of the types stores 4 to one decimal place of
accuracy?

>> SML uses ad-hoc polymorphism to implement that functionality and you
>> still write in conventional style:
>>
>> fun factorial 0 = 1
>> | factorial n = n * factorial(n-1)
>
> Ok, so how do I use that function without importing that module?

You can use that function like this:

factorial 4

in which case its type will be inferred to be int -> int.

There is no module.

Curtis W

unread,
Aug 22, 2006, 8:02:11 PM8/22/06
to
Jon Harrop wrote:
> Curtis W wrote:
> > Ironically, "code reuse through polymorphic
> > variants," which you mention later on, is a paper that shows a solution
> > to the expression problem in OCaml. Maybe you should read the papers
> > you post before you link them ;-)
>
> It addresses the expression problem but I would not call it a solution any
> more than wrapping a function in a class is a solution to not having
> closures.
So what requirement does it not fulfill to be considered a "solution"?

> >> Again, OOP is less flexible in other, more important, ways.
> >
> > And those would be?
>
> parallel pattern matching
> variable binding
> structure matching
> or-patterns
> guarded patterns
> static checking
> algorithmic matching

Why would I want to use those?

> >> > To an extent, yes. I'm not trying to say OOP is the best solution for
> >> > everything; rather, it's the best solution for most things.
> >>
> >> No, it is not. Why do you think OCaml programmers rarely use OOP?
> >
> > Why do you think BASIC programmers use goto? OCaml obviously has a long
> > history of functional programming and I suspect most of its community
> > use it because of that fact, so its not surprising to me why nobody
> > uses the OO features.
>
> I came to OCaml from OOP. Now that I have learned more, I rarely use OOP.
> Most OCaml programmers are the same. The reason is that OOP really doesn't
> live up to its hype.

Perhaps, although I find it much more likely that OOP is simply
overhyped, especially in the case of inheritance and data hiding, which
I find completely useless.

> >> >> Again, your retreat into a subjective notion of "inflexible" is
> >> >> unsupported and evades the issue anyway.
> >> >
> >> > I've already shown you why non-OO OCaml is inflexible--
> >>
> >> And I have already shown many more ways that it is more flexible. This is
> >> why people use it.
> >
> > My memory must be failing me. When did you do that?
>
> http://groups.google.co.uk/group/comp.lang.misc/msg/ce110b3cfe3811c5?hl=en&

I've already told you that's irrelevant. Because there are solutions to
the expression problem using both OO and procedural/functional
programming, you can't say that one is better at a specific subset of
it than the other.

> >> > if you don't
> >> > pass around the functions that operate on the data, you end up with a
> >> > mess of dependencies
> >>
> >> On the contrary, OOP leads to code with unknown execution paths.
> >
> > Flexibility in general does, yes. But then, obviously this doesn't
> > matter much, since just a second ago you were saying that functional
> > programming is _more_ flexible.
>
> Straw man. I haven't even mentioned functional programming.

Oh yes, because most OCaml supporters usually like to program
procedurally...

> Again, I dare you to try translating my interpreter or symbolic code into
> OOP. Incidentally, do you have a simple (say <300LOC) program that is
> ideally suited to OOP that I can try to translate into idiomatic OCaml?

Heh. I think I'd rather not waste an entire day translating that, but I
will give you a short program:

class Feet:
def __init__(self, feet):
self.feet = feet
def to_meters(self):
return Meters(self.feet*0.3048)

class Meters:
def __init__(self, meters):
self.meters = meters
def to_feet(self):
return Feet(self.meters/0.3048)

> > which is basically an implicit class.
>
> It has nothing to do with classes.

Only in the same way a bird has nothing to do with a sparrow. What do
you think classes are? They're essentially functions bound to data,
which is exactly what's going on when you pass around the data and
functions as arguments. Just because you're not using an explicit
'class' construct doesn't mean it isn't one.

> > Aside from being impractical when one fully utilizes classes,
>
> No classes.

Are you just skirting around my statements or do you actually not
understand what I'm getting at?

> > it
> > also makes it hard to add methods since you have to update every
> > function signature
>
> Type inference.

By signature I'm talking about the actual function, not its type
signature.

> > and call site.
> > If, for example, you wanted to add a
> > 'print' function that works on the expression tree, you'd have to
> > update every 'eval' call site as well as all of the signatures. You
> > might say that this isn't true because 'print' isn't used within eval,
> > but as I pointed out before, it might very well need to be in the
> > future, e.g. if you want to insert a 'print' if you're debugging it.
>
> Just call the "print" function from the body of the "eval" function.

What if its not defined in this module?

> >> > This is especially bad in libraries,
> >> > where people generally don't have the luxury of recompiling it every
> >> > time they want to create a new type.
> >>
> >> You're citing a problem that doesn't exist.
> >
> > Only because you don't want to see it. This "nonexistant" problem can
> > be seen all throughout OCaml, e.g. in its arithmetic operators.
>
> Use the higher-order module system or higher-order functions.

At which point you're either using or emulating classes.

> >> Type errors are bugs. Why do you want bugs?
> >
> > What does and does not constitute a "bug" is up to the programmer. A
> > bug is simply an unintended action or result in a program. If it's not
> > unintended its not a bug. You'll probably say that an error is never
> > something that somebody would want to happen, which may or may not be
> > right. It may sound like not complaining about an error at compile time
> > is just brushing it under the rug, but if you read my first post you'll
> > see that I'm in favor of having compile time warnings, just not errors.
> > Do you need to be forced to write bug-free code?
>
> Static checking helps remove bugs.

You're avoiding the question. Do you or do you not need to be forced to
write bug-free code?

> >> > Who said those were normal ints and floats?


> >>
> >> Ok, what are their semantics?
> >
> > I just told you.
>
> No, you didn't. You said "Who said those were normal ints and floats?".

I told you they had identical semantics and that the rest doesn't
matter. Seriously, you can't figure out what a number class would look
like?

> > Their semantics are identical. What they are is
> > besides the point: just assume that they're compatible enough with
> > numbers for my purposes.
>
> Famous last words.

Or famous first words.

> >> > Let's just stipulate that
> >> > '4.0' has the exact same semantics as '4' besides the difference in
> >> > precision.
> >>
> >> I can't think of a single operation that has the same semantics between
> >> ints and floats.
> >
> > It's a good thing you're not designing a language...
>
> Evasive and non-specific. The fact is, ints and floats have sufficiently
> little in common that it is a bad idea to pretend that they are
> interchangeable.

Little in common besides the fact that they're both types of numbers?
Yeah, I can't understand why people seem to think they're related.
After all, they only share practically all arithmetic operations as
well as several other properties.

> > Besides, I already told you they aren't traditional ints and floats.
>
> What are they? Mineral? Celebrity? I know! They are both singleton types
> containing only 4 but one of the types stores 4 to one decimal place of
> accuracy?

They're numbers.

> >> SML uses ad-hoc polymorphism to implement that functionality and you
> >> still write in conventional style:
> >>
> >> fun factorial 0 = 1
> >> | factorial n = n * factorial(n-1)
> >
> > Ok, so how do I use that function without importing that module?
>
> You can use that function like this:
>
> factorial 4
>
> in which case its type will be inferred to be int -> int.
>
> There is no module.

Eh? What if I want to use it in another source file? Don't tell me I
have to cut and paste it in from the other file...

It is loading more messages.
0 new messages