The Artima Developer Community
Sponsored Link

Weblogs Forum
Can Static and Dynamic Languages Live in Harmony?

19 replies on 2 pages. Most recent reply: Aug 3, 2003 12:06 PM by David Jeske

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 19 replies on 2 pages [ « | 1 2 ]
matthias felleisen

Posts: 5
Nickname: matthias
Registered: May, 2003

Re: Typing versus Testing Posted: May 22, 2003 5:56 PM
Reply to this message Reply
Advertisement
Apologies for cross-posting. I just realized the discussion continued here. -- MF

Some remarks on this topic in general:

1. Statically type checking a function gives you the guarantee that it uses the proper operations for all input values. Notice the for-all part, but also note that this is only true for safe type systems. Contrary to rumors, C++ is not safe.

2. Dynamically type checking (in say Scheme) means that you guarantee that you only check for those values that the function is actually applied to. So in future runs, it may actually fail.

3. Having said that, I strongly believe that building a test suite before you write your program finds far more errors quickly than a static type system, including powerful systems like those in Cayenne, Haskell, or ML. This is also what I teach in my introductory courses and what I wish to instill as a culture in those courses. Take a look at http://www.htdp.org/ and look for all the design recipes to see what I mean. (The book is on-line but also in paper.)

4. A static type system, especially an inference system, comes with a huge problem. Nobody has found a way to provide good feedback when the system discovers type errors. (First research efforts on this: POPL 1986!). So yes programs run when they type check but until they type check, you can't use the debugger or any other tool to find the problem.

5. We (the PLT crew) have developed an alternative to address exactly this dichotomy. The idea is to develop auxiliary value flow analysis tools for dynamically typed languages. If you write a script to add a header line to each file, you don't even think about it. If you have a prototype that you want to turn into a product, you carefully get each portion "type right".

6. We also addressed the error reporting issue. We explain the error that our inference tool finds via flow diagrams that we draw atop the program. It shows how a bad value might end up in a position where it violates a primitive function. The programmer can then figure out whether this is a weakness in the analysis tool or the program (usually).

7. We accomplished this by giving up on equational reasoning a la ML and use subset reasoning instead. We find it more natural. The cost is that the complexity of the algorithm is high.

8. We're in the process of re-engineering MrSpidey now. We are
also exploring an ML-like alternative again, simply to find out whether we can tame it, too.

9. If you're interested, go to my home page and peruse some of our publications on Soft Scheme, MrSpidey, and MrFlow:
http://www.ccs.neu.edu/home/matthias/

-- Matthias Felleisen

Quentin Crain

Posts: 1
Nickname: czrpb
Registered: May, 2003

Re: Typing versus Testing Posted: May 23, 2003 3:24 PM
Reply to this message Reply
Robb says:

"Typing and testing are largely complementary. Even if you do have tests it is not credible to claim that your code is correct. Tests establish that a particular set of cases are not wrong but this falls far short of establishing that the code is actually correct in all cases. Typing guarantees that there are no "type" errors in the program but what this guarantee is worth depends to a large extent on the quality of the type system."

One of the most important things to notice IMHO is his statement about typing guaranteeing the lack of "type" errors.

Not getting into whether or not this is true, I am not sure a system that allows one to get out of creating tests is a good thing. In short I would prefer a test or tests over any implicit correctness. I would prefer Python code with tests that raise TypeError exceptions over Java and compiler-errors.

-- Quentin Crain

Ian Bicking

Posts: 900
Nickname: ianb
Registered: Apr, 2003

Adding formalism Posted: May 23, 2003 5:50 PM
Reply to this message Reply
I can understand the desire to more formally define a program, which static type annotation does help do. But I think this is also possible in Python, though the facilities are still young.

The most obvious example is the use of interfaces, a young concept in Python that is gaining popularity fairly quickly as of late. While, as a dynamic language, there is no static type analysis, you can do assertions on interfaces. This is not the same as saying "assert type(arg1) is type(1)", i.e., you are not checking for a particular type. Instead you are asking the object if it obeys the necessary rules (and more often, you ask for some object that obeys the necessary rules -- enter adapters).

I think this makes Python a much more object-oriented system, because you are asking the object, where in Java you are asking the compiler. Though it's a subtle difference, this sort of dynamicism is very central to Python's power.

Testing creates an empirical result of your success, but formalism is something else, with real benefits. But again, static typing is a weak formalism. What really matters isn't types, but semantics, which are tied up in the entire program. Often a subclass will not obey the required semantics, or a non-subclass will.

Documentation is another alternative to static typing. I usually find that writing documentation gives me a better feel for the design of my application. Writing developer documentation even moreso. Docstrings are also useful to give the exact expectations in an informal manner as well.

Something inbetween docstrings and unit tests might be contract programming. Just recently software was released to implement Eiffel-style contracts in Python:

http://www.wayforward.net/pycontract/

I expect this could easily be enhanced to ease type checking, since it has a rather ad hoc syntax embedded in the docstring. Of course it would be more interesting if it used interfaces instead of types. Maybe more interesting still (for interfaces) would be a metaclass that took the type information, and tried to attain all the necessary adapters in a method wrapper.

matthias felleisen

Posts: 5
Nickname: matthias
Registered: May, 2003

Re: Adding formalism Posted: May 24, 2003 8:07 AM
Reply to this message Reply
> Documentation is another alternative to static typing. I
> usually find that writing documentation gives me a better
> feel for the design of my application. Writing developer
> documentation even moreso. Docstrings are also useful to
> give the exact expectations in an informal manner as
> well.

If the consistency between documentation and the program
is not checked, documentation is nice but often outdated.

> Something inbetween docstrings and unit tests might be
> contract programming. Just recently software was released
> to implement Eiffel-style contracts in Python:
>
> http://www.wayforward.net/pycontract/
>
> I expect this could easily be enhanced to ease type
> checking, ...

Yes, PLT Scheme has been there for several years. I hope
you have fixed the serious problems with Eiffel's contract
checker. If you're unaware, take a look at Findler's work on
contracts.

http://people.cs.uchicago.edu/~robby/publications/

David Jeske

Posts: 1
Nickname: jeske
Registered: Aug, 2003

Re: Static and Dynamic Languages Posted: Aug 3, 2003 12:06 PM
Reply to this message Reply
I have written on and worked on large programs writtin in static (C/C++/Java), dynamic (Python), and smaller programs written in quasi-dynamic (Objective-C) environments.

I find that the biggest reason I prefer to write some larger software in statically (or declarative) type systems, is the type documentation.

It is very easy to keep every nuance of the typing of a small script in my head. However, when the application grows to a certain number of type patterns, it is hard to remember what concrete type is sitting in the variable I'm working with, or in the hashtable I was just passed, or in the list I just got back from the hashtable. I say "number of type patterns", becuase I have found that reducing the number of object types which pass between files is an effective way to reduce this mental working-set when developing larger software in dynamically typed languages.

You can see this technique in the Python standard libraries, where they choose to use basic datatypes as arguments and return values (i.e. string, list of strings) rather than construct more specific types as is done in Java or C++ (Urls, BufferedString, byte[], etc). Bill Venners commented about the Python API being "somehow designed such that using them also usually requires minimal coding", and I think this is a large part of why he made this statement.

In fact, I agree with Bill wholeheartedly when he asserts that many of the reasons Python is pleasant to develop for are not because of typing, but because of the economy and expressiveness of it's constructs. To his list I would also add the effects of the Python import and scoping semantics. In Python, one imports the module which is the starting point for work. The use of the initial module entry point is still fully qualified with that module name, conveying to the reader the 'start point'. However, any return values which come back can be used directly without additional imports. This provides a clarity and utility to the usage of dependent modules. Java/C# on the other hand, create an import chain-reaction. One has to import not only the module which is called, but every module which declares a type which is returned by that module, and then every module which declares a type returned by that return type, and so on through the functionality accessed from each class type. This is terribly inconvinent, and muddies the entire meaning of the import.

I appreciate developing in dynamic typed languages most when I need to build several complex data relationships inside a function, just to produce a simple result. For example, taking lists of items and building a few hashes, or hashes of hashes, which are all temporarily created for the purpose of providing the same items back in a different order. In Java, Generic Java, or C++, the number of characters in my source code just to declare, allocate, and iterate over these temporary sets of basic datatypes is often larger than the number of characters to perform the re-organization algorithm itself. In Python, the datastructures and manipulation are concise and small, letting the algorithm shine through.

Returning to the benefits of type-declaration documentation. It is convinent when all types used are visible when looking at code. In fact, Java's import system again fails here as a non-fully qualified type declaration still requires hunting to track down. Type-aware completion (i.e. Intellisense) and help systems provided in IDEs are truly amazing, and provide exactly what is needed when it is needed. They are possibly the biggest benefit of using today's static typed languages.

Ironically, understanding available types is not often improved when writing code in systems which make use of type-inference (i.e. ML), because even though the inference system can determine what appears at a type-variable when compliing, it seldom has useful ways to explain that type to the user when editing (i.e. no simple interface names, no types for non-complete programs).

Ultimately, when making a choice I consider the task at hand very central to what type of language is best used. Consider an analogy to sketch drawing. If I want to draw a picture of a scene with trees and flowers, any drawing implements other than the pencil itself mostly get in the way. However, if I am drawing a perspective correct downtown cityscape, the rigid constraints provided by rulers and protractors are a benefit, not a hinderance. The same is true of software systems. If I want the ability to drastically refactor code into another organization, there is nothing so good as my preserved type declarations to help me iterativly work towards the new organization -- while keeping my lines straight.

Flat View: This topic has 19 replies on 2 pages [ « | 1  2 ]
Topic: Overload Overload Previous Topic   Next Topic Topic: Java Performance News

Sponsored Links



Google
  Web Artima.com   

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