The Artima Developer Community
Sponsored Link

Weblogs Forum
Implicit versus Explicit Dynamic Typing

95 replies on 7 pages. Most recent reply: Apr 17, 2006 11:09 AM by Isaac Gouy

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 95 replies on 7 pages [ « | 1 2 3 4 5 6 7 | » ]
Vesa Karvonen

Posts: 116
Nickname: vkarvone
Registered: Jun, 2004

Re: Implicit versus Explicit Dynamic Typing Posted: Sep 20, 2005 11:01 AM
Reply to this message Reply
Advertisement
> Dynamically types languages have a tradition of being able to compile very
> small pieces of code, like a single method. Statically typed languages
> normally compile hole files.

Your comment somewhat surprises me given that you said to have programmed in SML.

Being able to compile a small snippet of code in a dynamically checked language is not very useful in the sense that the compiler usually can not detect many kinds errors. In other words, the fact that you can compile a snippet of code doesn't necessarily tell you many things about the code. In some dynamically checked languages, you can basically compile almost anything. The compiler merely translates the code from a textual representation into some other representation (e.g. AST, bytecode) and performs little more than trivial syntactic analysis.

As I'm sure many already know, there are statically typed (and compiled) languages that allow interactive development (a REPL) similar to what many dynamically checked languages provide. Standard ML is one such language and its roots go back all the way to 1973. (You might want to differentiate between the "traditional" or "normal" and the "mainstream".) What many might not understand is that good statically typed languages actually allow you to compile (and type check) small snippets of code as long as you are being explicit about the environment in which the code is to be type checked.

Here is a simple but realistic example in Standard ML:


signature GROUP =
sig
type t
val zero : t
val plus : t * t -> t
val neg : t -> t
end

functor GroupOps (G : GROUP) =
struct
open G

fun minus (x, y) = plus (x, neg y)
(* ... *)
end


The idea here is that we wish to write functions for manipulating groups, but we don't want to tie the functions to any particular representation of groups. The signature GROUP specifies the abstraction of groups. It leaves the type t abstract. You can compile the above in SML and the compiler actually type checks the GroupOps functor. If (and when) a functor definition compiles in SML, you know that any instantiation of the functor with a module that matches the signature of the functor argument will pass the type checker and the resulting code will be type safe. This is very different from C++ templates, for instance, where template definitions aren't actually type checked.

Vesa Karvonen

Posts: 116
Nickname: vkarvone
Registered: Jun, 2004

Re: Implicit versus Explicit Dynamic Typing Posted: Sep 20, 2005 11:18 AM
Reply to this message Reply
> Here's the trick though: typical UTs test values and types
> come along for the ride. It's "two for the price of one."

From a rigorous point-of-view that is BS. A finite set of tests can not provide the same guarantees that any useful type system can.

In a type inferred language you can actually have both (and more) for little more than the price of one (the tests). You can use just the amount of type declarations that you find appropriate to enforce the abstractions that you want and you can write the tests in an attempt to find particular errors in the dynamic semantics.

> Type systems tell us we have the correct types, but they
> don't go down to the computation level.

That depends. You can argue that so called dependent type systems (and restrictions of such systems) actually do. They are still under active research, though. The main theoretical problem with such type systems is that the type system becomes undecidable.

Terje Slettebø

Posts: 205
Nickname: tslettebo
Registered: Jun, 2004

Re: Implicit versus Explicit Dynamic Typing Posted: Sep 20, 2005 11:29 AM
Reply to this message Reply
> > You say that "Typing is just one of many aspects that
> makes
> > development in Smalltalk, Lisp and Python very different
> from
> > development in C++, Java and C#". I guess what I'm
> looking for is: Why
> > would lack of static type checking be an advantage?
> (leaving aside the
> > discussion of whether or not the types should be
> declared or
> > inferred)?
>
> I would like all the static typing I could get, but it
> does not have very high priority, that is, I would like
> static typing, but not if I have to sacrifice things I
> value more. Many of these things i value more, could
> properly work in a statically typed context, but I haven't
> seen this so far (at least not enough to make me shift
> language).
>
> Some of the things I value high are: easy-to-use top level
> loop, fine grained compilation, a live image with good
> reflective capabilities, being able to run/test code that
> has holes (ex. missing function declarations) and keyword
> arguments.
>
> I strongly believe that programming languages should
> restrict the programmer as little as possible. I don't
> find languages that force one mindset like OO or static
> typing to be optimal. A language should give the
> programmer the option to model some or all of an
> application using OO, and give the option to verify some
> or all of an application statically, if the programmer
> feel it is needed.
>
> A complex problem consists of many subproblems, that each,
> in my eyes, are best expressed in its own terms. This
> could be done with for example SQL, regular expressions, a
> markup language, OO, logic programming, and unique domain
> specific extensions/languages.
>
> My impression of programming languages are that the
> dynamic ones, and in particular Common Lisp, are much more
> flexible in this regard than the static ones.
>
> The above is a bit off topic, but hopefully it gives an
> idea of why I'm not particular interested in static
> typing.
>
> By the way. If you have met the term "Language Oriented
> Programming", this resembles my view on programming very
> closely.

Interestingly, a lot of what you say here are things I could have said myself, like not being forced to use a single paradigm (it being procedural, OO, functional programming, or whatever), and as you probably know, C++ is a multi-paradigm language, but I don't want to start a "language war" here... :) (I've yet to see one that lead to anything good). Also, as you basically say, use the best tool for the job, and indeed, in many cases it may be better to use a DSL, such as those you mention. So it seems we're quite in agreement when it comes to that. :)

I also find LOP, and similar things like Intentional Programming, very interesting.

As you say, I may place more emphasis on static type checking, because I've good experience with it being able to catch many errors, without having to write any tests for it. Also, as Christopher point out in another posting, explicit declarations also serve as compiler/runtime-enforced documentation (and is therefore guaranteed to be up-to-date). It's similar with Design by Contract and unit/integration tests, both giving information about what is expected and guaranteed, etc.

Regards,

Terje

Todd Blanchard

Posts: 316
Nickname: tblanchard
Registered: May, 2003

Re: Implicit versus Explicit Dynamic Typing Posted: Sep 20, 2005 11:42 AM
Reply to this message Reply
> What is with this irrational fear of verbosity? Verbosity
> is a Good Thing.

Oh really?

So you think

Button b = new Button();
b.addActionListener(new ActionListener() {
public void actionPerformed(Component target) {
System.out.println("Button was clicked"); }});

is better than

b := Button new.
b onClickDo: [:btn | Transcript show: 'Button was clicked'].

One of these is hopelessly cluttered with worthless boilerplate and one is clear as day.

Verbosity limits your productivity.

Vesa Karvonen

Posts: 116
Nickname: vkarvone
Registered: Jun, 2004

Re: Implicit versus Explicit Dynamic Typing Posted: Sep 20, 2005 11:45 AM
Reply to this message Reply
> Verbosity is a Good Thing.

No it isn't. Using more words than necessary (verbose) is by definition unnecessary.

> Explicit type annotations serve as a form of automated
> documentation.

There is very little "automated" about having to manually declare the types of all variables. If you are looking for automated documentation about types, I would suggest looking at the -dtypes option of the Ocaml compiler and the Show type at point command of the Tuareg mode (an Emacs mode for Ocaml). The -dtypes option causes the compiler to output a file describing the types of all (sub)expressions. The Show type at point command extracts the type of the (smallest) expression under the cursor and displays the type. This is what I would call automated documentation (about types).

> This has nothing to do with being statically typed, but
> are simply examples of languages with insufficient type
> systems.

I agree with latter but not with the former. Being able to specify and enforce abstractions is pretty much the essense of static typing. It is sad that many of the mainstream languages are so bad at it.

Todd Blanchard

Posts: 316
Nickname: tblanchard
Registered: May, 2003

Re: Well trodden path Posted: Sep 20, 2005 11:51 AM
Reply to this message Reply
> I'm trying to understand your reasoning, here. What's the
> problem with inheritance and static typing?

Foo f = new Bar();

f isn't a Foo, well, it sort of is, but it might not act much like a Foo, in fact, I may need to use it as a Bar if it is one, so I'll have to interrogate it as to its type and downcast. Downcasting ends up being inevitable in non-trivial systems.

> However, what we _are_ somewhat struggling with in C++ -
> but where I see the same problem in dynamically typed
> languages - is the support for "duck typing"

Does it not strike you as odd that template programming has become so much more important/prevalent in C++ because it provides duck typing? In the end, it turns out that duck typing is the more sensible model IFF you have a runtime that can catch and allow you to recover from type errors.

C++ tries to do it all at compile time, in the end this never quite works and you'll end up downcasting somewhere because the compiler's notion of type safety is too limiting. Downcasting gives you wiggle room at the expense of safety.

Vesa Karvonen

Posts: 116
Nickname: vkarvone
Registered: Jun, 2004

Re: Implicit versus Explicit Dynamic Typing Posted: Sep 20, 2005 12:59 PM
Reply to this message Reply
Here is an equivalent snippet of code in SML + mGtk:


let val b = Button.new ()
in Signal.connect
b (Button.clicked_sig (fn () => print "Button was clicked\n"))
end


Voilà! Statically typed, but no type annotations.

Max Lybbert

Posts: 314
Nickname: mlybbert
Registered: Apr, 2005

Re: Well trodden path Posted: Sep 20, 2005 3:10 PM
Reply to this message Reply
> C++ tries to do it all at compile time, in the end this
> never quite works and you'll end up downcasting somewhere
> because the compiler's notion of type safety is too
> limiting. Downcasting gives you wiggle room at the
> expense of safety.

Boy did I miss a fun discussion. Oh well, here's the second round:

/* Does it not strike you as odd that template programming has become so much more important/prevalent in C++ because it provides duck typing? In the end, it turns out that duck typing is the more sensible model IFF you have a runtime that can catch and allow you to recover from type errors.
*/

While it is true that Java Generics are something like a run-time test followed by duck typing, that isn't completely true in C++.

Rather, it *can* be true in C++, but that's not why C++ templates are so useful and popular right now. Instead, C++ templates provide a way to do things like std::sort(iter first, iter last, [class] comp) (http://www.sgi.com/tech/stl/sort.html). That is, the sort that takes a "compare" function/function-like object as an argument. The ability to pass policy through functions/function-like objects is very powerful, and not available in some other languages.

This isn't the same as duck typing, in that passing policy classes to C++ templates is a way of expressing conceptual similarity (the ability to sort), compared to calling by function signature (duck typing).

That may not be well-worded. If my mini-rant doesn't make sense, please let me know.

Matt Gerrans

Posts: 1153
Nickname: matt
Registered: Feb, 2002

Re: Well trodden path Posted: Sep 20, 2005 9:26 PM
Reply to this message Reply
<i>Instead, C++ templates provide a way to do things like std::sort(iter first, iter last, [class] comp) (http://www.sgi.com/tech/stl/sort.html). That is, the sort that takes a "compare" function/function-like object as an argument.</i>

Gosh, that's powerful stuff. Hey, wait a minute, isn't that what qsort() did in plain old C thousands of years ago? :)

Anyway, I find myself unconvinced by arguments on both sides of this debate (all lacking any hard data or proof, but full of opinions stated unequivocally), so I'll keep on using both Python and C# along with a sprinkling of C++, JavaScript and a few others when necessary.

Todd Blanchard

Posts: 316
Nickname: tblanchard
Registered: May, 2003

Re: Well trodden path Posted: Sep 20, 2005 10:20 PM
Reply to this message Reply
> /* Does it not strike you as odd that template programming
> has become so much more important/prevalent in C++ because
> it provides duck typing? In the end, it turns out that
> duck typing is the more sensible model IFF you have a
> runtime that can catch and allow you to recover from type
> errors.
> */
>
> C++ templates provide a way to do things like
> std::sort(iter first, iter last, [class] comp)
> (http://www.sgi.com/tech/stl/sort.html).

I actually think people use templates in c++ to eliminate the coupling between hierarchy/type and protocol.

> That is, the
> sort that takes a "compare" function/function-like object
> as an argument. The ability to pass policy through
> functions/function-like objects is very powerful, and not
> available in some other languages.

You mean like

array sort: [:x :y | x > y]

? Neither x nor y is typed. The code will work if x responds to > with a y argument. It won't if it doesn't. C++ templates amount to the same thing only I have to put in a placeholder for type (usually T) and provide something that looks/acts like a 2 argument function (function pointer or object implemention op()).

Peter Mechlenborg

Posts: 8
Nickname: pmech
Registered: Sep, 2005

Re: Implicit versus Explicit Dynamic Typing Posted: Sep 21, 2005 1:24 AM
Reply to this message Reply
> > Dynamically types languages have a tradition of being able to compile very
> > small pieces of code, like a single method. Statically typed languages
> > normally compile hole files.
>
> Your comment somewhat surprises me given that you said to have
> programmed in SML.

Sorry, you are correct. I just looked at my old SML-mode for emacs, and it has a shortcut for compiling just one function. I don't have SML installed so I haven't tested it. Eclipse is also doing a good job at making compilation very lightweight.

> Being able to compile a small snippet of code in a dynamically checked
> language is not very useful in the sense that the compiler usually can
> not detect many kinds errors. In other words, the fact that you can
> compile a snippet of code doesn't necessarily tell you many things
> about the code. In some dynamically checked languages, you can
> basically compile almost anything. The compiler merely translates the
> code from a textual representation into some other representation
> (e.g. AST, bytecode) and performs little more than trivial syntactic
> analysis.

That has more to do with tradition than technical limits. Type inference can also work in a dynamic context, and there is no reason way the compiler cannot exploit all the knowledge it has in the image. Of cause you cannot be given any global guaranties of ex. type safety, and at the same time be dynamic.

Peter Mechlenborg

Posts: 8
Nickname: pmech
Registered: Sep, 2005

Re: Implicit versus Explicit Dynamic Typing Posted: Sep 21, 2005 1:38 AM
Reply to this message Reply
> Interestingly, a lot of what you say here are things I could have said
> myself, like not being forced to use a single paradigm (it being
> procedural, OO, functional programming, or whatever), and as you
> probably know, C++ is a multi-paradigm language, but I don't want to
> start a "language war" here... :) (I've yet to see one that lead to
> anything good). Also, as you basically say, use the best tool for the
> job, and indeed, in many cases it may be better to use a DSL, such as
> those you mention. So it seems we're quite in agreement when it comes
> to that. :)

I don't know C++ that well, but I have found many similarities between it and Common Lisp. I find that quite funny, because the two languages have so different strategies of doing things. It's kind of like the Jedi and the Sith, although I don't know who is the Jedi and who is the Sith :-).

Vesa Karvonen

Posts: 116
Nickname: vkarvone
Registered: Jun, 2004

Re: Well trodden path Posted: Sep 21, 2005 2:15 AM
Reply to this message Reply
> I find myself unconvinced by arguments on both sides of this debate (all
> lacking any hard data or proof, but full of opinions stated
> unequivocally)

Let's see. Here are some arguments I've used in this debate along with a couple of additional notes.

> [The SML/NJ] compiler infers the types of expressions and responds with
> the result of the inference

The proof is right next to the statement. If you don't take my word for it you can try SML/NJ by yourself. The same applies to other type inferred languages with a REPL, such as Ocaml and Haskell.

> there are cases where Hindley-Milner style type-infering can yield
> rather difficult to understand errors, because the cause of the type
> error and the place where the error is detected may be far away. You can
> limit such problems by using type ascriptions.

Here is a link to a particular article on the subject of improving error messages from H-M type systems that specifically tries to improve the location information: http://citeseer.ist.psu.edu/680831.html .

> The undesirable declarations are the ones you write just because the
> language forces you to write them, but serve no other purpose than to
> keep the compiler happy (e.g. in Java, every variable declaration must
> be annotated by a type). The desirable kinds of declarations are the
> ones that you use to specify abstractions so that you can write modular
> programs. From another point of view, the desirable kinds of
> declarations are the ones you use to hide implementation details.

I assume you already know Java. Let me illustrate the two kinds of declarations. Let's first assume that SML would require type annotations on every binding. Here is how the Direction example using strings would look like:


structure LeakyStringDirection (* no sealing ascription *) =
struct
type direction = string

val north : direction = "north"
val south : direction = "south"
val west : direction = "west"
val east : direction = "east"

fun opposite (d : direction) : direction =
if d = north then south
else if d = south then north
else if d = west then east
else west
end


Although all the bindings are annotated with types, the above does not actually enforce the abstraction. We can, for example, pass an arbitrary string as a direction or to treat a direction as a string:


- LeakyStringDirection.opposite "look, no protection" ;
val it = "west" : LeakyStringDirection.direction
- print (LeakyStringDirection.north^"\n") ;
north
val it = () : unit


What I'm demonstrating here is that type annotations do not necessarily help you to provide any additional guarantees about your program.

In fact, the module LeakyStringDirection would exhibit the same properties if we left out all the annotations:


structure LeakyStringDirection (* no sealing ascription *) =
struct
type direction = string

val north = "north"
val south = "south"
val west = "west"
val east = "east"

fun opposite d =
if d = north then south
else if d = south then north
else if d = west then east
else west
end


While the above is clearly less verbose than the one with ascriptions, it has the exact same safety properties. In other words,

> The undesirable declarations are a major cause of verbosity and are
> usually a hindrance rather than a help.

Fortunately, SML allows you to actually specify and enforce abstractions. Let's first see a signature for directions:


signature DIRECTION =
sig
eqtype direction

val north : direction
val south : direction
val west : direction
val east : direction

val opposite : direction -> direction
end


What the above signature says is that there is a type direction whose values can be tested for equality. It also says that there are four (not necessarily distinct) named values of the type: north, south, west, and east. Finally, there is a function opposite that maps a direction to a direction.

Let's then create a sealed module matching the DIRECTION signature:


structure SealedStringDirection :> DIRECTION =
struct
type direction = string

val north = "north"
val south = "south"
val west = "west"
val east = "east"

fun opposite d =
if d = north then south
else if d = south then north
else if d = west then east
else west
end


The abstraction is now enforced. We can not pass an arbitrary string as a direction nor treat a direction as a string:


- SealedStringDirection.opposite "look, protection" ;
stdIn:1.1-8.25 Error: operator and operand don't agree [tycon mismatch]
operator domain: SealedStringDirection.direction
operand: string
in expression:
SealedStringDirection.opposite "look, protection"

uncaught exception Error
raised at: ../compiler/TopLevel/interact/evalloop.sml:52.48-52.56
../compiler/TopLevel/interact/evalloop.sml:35.55
- print (SealedStringDirection.north^"\n") ;
stdIn:1.7-8.16 Error: operator and operand don't agree [tycon mismatch]
operator domain: string * string
operand: SealedStringDirection.direction * string
in expression:
SealedStringDirection.north ^ "\n"

uncaught exception Error
raised at: ../compiler/TopLevel/interact/evalloop.sml:52.48-52.56
../compiler/TopLevel/interact/evalloop.sml:35.55


Essentially, SealedStringDirection.direction is a new abstract type, distinct from the underlying type string.

What the above demonstrates is the use of declarations to specify and enforce abstractions. Specification and enforcement of abstractions allows the compiler to detect errors.

> you can not express "concepts" in C++.

Try the book Generic Programming and the STL by Matthew Austern for starters. If you don't have it, you can look at http://www.osl.iu.edu/publications/prints/2003/comparing_generic_programming03.pdf .

> Another example is the lack of any means of abstracting over primitive
> types in Java. If you change between int and long in an interface,
> you'll get a nasty ripple effect.

Suppose I have a Java class of the form:

  public class Foo {
    static int introduce();
    static void eliminate(int token);
  }


If, for some good reason (e.g. an external library changes), the interface needs to be changed to

  public class Foo {
    static long introduce();
    static void eliminate(long token);
  }


All clients of the interface will have to be changed. For instance, every place where a result of calling introduce is stored in a variable must be changed. Every interface that you need to pass through values returned by introduce potentially needs to change. This what I mean with the ripple effect.

In many other languages it is possible to avoid the ripple effect without a major programming effort. For example, in C++ you can use a typedef:


class Foo {
public:
typedef int token_type;
static token_type introduce();
static void eliminate(token_type token);
}


Unfortunately, the abstraction isn't actually enforced in C++. You can still write code that uses int rather than Foo::token_type. As I already demonstrated earlier, you can enforce abstractions like the above in SML by using abstract type specifications and opaque signature ascription:


structure Foo :>
sig
type token_type
val introduce : unit -> token_type
val eliminate : token_type -> unit
end =
struct
type token_type = int
val introduce = ...
val eliminate = ...
end


If we would change the above to


structure Foo :>
sig
type token_type
val introduce : unit -> token_type
val eliminate : token_type -> unit
end =
struct
type token_type = Int64.int
val introduce = (*...*)
val eliminate = (*...*)
end


in Standard ML, there would be no ripple effect, because it is essentially impossible to directly depend on the underlying representation of token_type.

> Except for a few exceptions (and the definition of new datatypes) you
> can essentially write your entire program without any type annotations
> or declarations.

This can be formalized and proven by defining a subset of the language (SML, for example) that type checks without type ascriptions. I leave it as an exercise to the reader.

[In SML, the few exceptions are related to certain kinds of polymorphic (top-level) declarations and certain uses of record types.]

> In a type inferred language you can actually have both (and more) for
> little more than the price of one (the tests). You can use just the
> amount of type declarations that you find appropriate to enforce the
> abstractions that you want and you can write the tests in an attempt to
> find particular errors in the dynamic semantics.

I hope my additional explanations above have clarified this statement. I have demonstrated that type ascriptions are optional in SML. I have demonstrated that you can use signatures in SML to specify abstractions and signature ascription to enforce abstractions. It is quite obvious that you can write unit tests in SML. Here is a concrete example of an ad hoc unit test from my utility library (you can't compile it without the rest of the library):


local
open UnitTest

structure LP = ListProduct
val A = LP.A
val L = LP.L
val S = LP.S
val V = LP.V
in
val () =
unitTests
title "ListProduct"

test (fn () =>
verify (LP.all (thunk true) $))

test (fn () =>
verify (LP.all (fn s & i & r =>
s = Int.toString i andalso real i <= r)
L["1", "2"] L[1, 2] A(Array.fromList [1.0, 2.0, 3.0]) $))

test (fn () =>
verify (not (LP.allEq (fn i & s & r =>
s = Int.toString i andalso real i <= r)
L[1, 2, 3] L["1", "2"] L[1.0, 2.0] $)))

test (fn () => let
val results = ref []
in
LP.app (fn i & r =>
push (Real.toString (real i + r) ^ "\n",
results))
L[1, 2, 3] L[0.1, 0.2] $
; verify (["2.2\n", "1.1\n"] = !results)
end)

test (fn () =>
expect (fn () =>
LP.appEq ignore L[1, 2] L["1", "2", "3"] L[0.1, 0.2] $,
fn ListPair.UnequalLengths => ()))

test (fn () =>
verify (not (LP.exists (fn i & r =>
real i <= r)
L[3, 4] L[1.0, 2.0] $)))

test (fn () =>
verify ("c3.3b2.2a1.1\n" =
LP.foldl (fn (s & r & i, rest) =>
s^Real.toString (real i + r)^rest)
"\n"
L["a", "b", "c"] V(Vector.fromList [0.1, 0.2, 0.3]) L[1,2,3,4] $))

test (fn () =>
verify (["a" & 1, "b" & 2, "c" & 3] =
LP.foldr op:: [] L["a", "b", "c", "d"] L[1, 2, 3] $))

test (fn () =>
verify ([(~1, #"A", false), (~3, #"B", true), (~5, #"C", false)] =
LP.map (fn i & s & b =>
(~i, Char.toUpper s, not b))
L[1,3,5] S"abcd" L[true, false, true] $))

test (fn () =>
verify ([1, 3, 2] =
LP.map Real.round
L[1.0, 3.0, 2.0] $))

$
end


The above is an ad hoc unit test for a ListProduct module. The module UnitTest is a very simple unit testing "framework" I've written for my own use.

> dependent type systems

Use google: http://www.google.com/search?q=dependent+types

> Being able to specify and enforce abstractions is pretty much the
> essense of static typing.

Ditto: http://www.google.com/search?q=static+types+enforce+abstractions

...

If you would care to elaborate on what you think is "lacking proof or data" then maybe I can provide it.

Here is a summary of some of my positions:
- You should use types to specify and enforce abstractions. When you do so, the types actually help to detect errors.
- Type ascriptions that do not either specify or enforce abstractions are unnecessary. You don't fundamentally need them.
- Manifest typing (as in Java and C++) leads to verbosity (having to read/write unnecessary words).
- Type inferred languages allow you to omit the unnecessary type ascriptions.

Vesa Karvonen

Posts: 116
Nickname: vkarvone
Registered: Jun, 2004

Re: Implicit versus Explicit Dynamic Typing Posted: Sep 21, 2005 2:34 AM
Reply to this message Reply
> That has more to do with tradition than technical limits.
> Type inference can also work in a dynamic context, and
> there is no reason way the compiler cannot exploit all the
> knowledge it has in the image.

Well, I'm aware of implementations of dynamically checked languages that do perform some type inference or soft typing. However, there are genuine technical limitations as to what can be done. For instance, some dynamically checked languages allow you to make forward references to variables that have not been declared. The best a compiler can do is to warn about the non-existence of a declaration for the variable. Such a warning doesn't necessarily indicate an error in the program. In other words, the compiler can sometimes only make guesses. Making the compiler make more guesses would probably only make it extremely annoying to program using the compiler.

> Of cause you cannot be given any global guaranties of ex.
> type safety, and at the same time be dynamic.

Depends on what is meant by "dynamic". It seems to me that the word is often used quite loosely to refer to things like polymorphism, reflection, or even concise syntax for lexically scoped anonymous functions (closures in implementation parlance).

Peter Mechlenborg

Posts: 8
Nickname: pmech
Registered: Sep, 2005

Re: Implicit versus Explicit Dynamic Typing Posted: Sep 21, 2005 3:18 AM
Reply to this message Reply
> Well, I'm aware of implementations of dynamically checked languages
> that do perform some type inference or soft typing. However, there are
> genuine technical limitations as to what can be done. For instance,
> some dynamically checked languages allow you to make forward
> references to variables that have not been declared. The best a
> compiler can do is to warn about the non-existence of a declaration
> for the variable. Such a warning doesn't necessarily indicate an error
> in the program. In other words, the compiler can sometimes only make
> guesses. Making the compiler make more guesses would probably only
> make it extremely annoying to program using the compiler.

I'm not sure where you are heading.

Of cause a compiler cannot reason about something that does not exist. I think it's a feature if the compiler gives the programmer the option to continue, even though the program is incomplete.

> Depends on what is meant by "dynamic". It seems to me that the word is
> often used quite loosely to refer to things like polymorphism,
> reflection, or even concise syntax for lexically scoped anonymous
> functions (closures in implementation parlance).

In the context of this discussion, I mean dynamic typing, i.e. that type information is associated with values and not variables.

Flat View: This topic has 95 replies on 7 pages [ « | 1  2  3  4  5  6  7 | » ]
Topic: Bridging Static and Dynamic Typing Previous Topic   Next Topic Topic: Where Did All the Beautiful Code Go?

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use