Static vs. Dynamic Typing

Please compose all posts in Emacs.

Moderators: phlip, Moderators General, Prelates

zenten
Posts: 3799
Joined: Fri Jun 22, 2007 7:42 am UTC
Location: Ottawa, Canada

Re: Re:

Postby zenten » Sat Apr 19, 2008 7:22 pm UTC

Rysto wrote:
poohat wrote:The only real reason for static typing is speed

So basically, you haven't read this thread at all.


Or just disagreed with it.

Rysto
Posts: 1460
Joined: Wed Mar 21, 2007 4:07 am UTC

Re: Static vs. Dynamic Typing

Postby Rysto » Sat Apr 19, 2008 8:43 pm UTC

Then he should address the points he disagrees with, instead of pretending that they don't exist.

zenten
Posts: 3799
Joined: Fri Jun 22, 2007 7:42 am UTC
Location: Ottawa, Canada

Re: Static vs. Dynamic Typing

Postby zenten » Sun Apr 20, 2008 2:08 am UTC

Rysto wrote:Then he should address the points he disagrees with, instead of pretending that they don't exist.


Anyone making a post that long would just get ignored.

User avatar
Hammer
Because all of you look like nails.
Posts: 5491
Joined: Thu May 03, 2007 7:32 pm UTC
Contact:

Re: Static vs. Dynamic Typing

Postby Hammer » Sun Apr 20, 2008 2:58 am UTC

Enough. Move on.
"What's wrong with you mathematicians? Cake is never a problem."

Rysto
Posts: 1460
Joined: Wed Mar 21, 2007 4:07 am UTC

Re: Static vs. Dynamic Typing

Postby Rysto » Tue Apr 22, 2008 12:04 am UTC

I just wrote a piece of code that amuses me. I guess it forms an argument against static typing -- or at least, mandatory type annotations. Get a load of this monstrosity:

Code: Select all

class InvertibleNavigableMapImpl<K, V>
        extends AbstractInvertibleMap<K, V, NavigableMap<K, V>, NavigableMap<V, K>,
          InvertibleNavigableMapKeySet<K, V, InvertibleNavigableMapImpl<K, V>>,
          InvertibleNavigableMapKeySet<V, K, InvertibleNavigableMapImpl<V, K>>,
          InvertibleMapEntrySet<K, V, InvertibleNavigableMap<K, V>>,
          InvertibleMapEntrySet<V, K, InvertibleNavigableMap<V, K>>,
          InvertibleNavigableMapImpl<V, K>>
        implements InvertibleNavigableMap<K, V>


To honest, a lot of the verbosity would be cut down if Java allowed you to parameterize type variables. My long class names don't help, either.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Static vs. Dynamic Typing

Postby EvanED » Tue Apr 22, 2008 1:45 am UTC

:shock:

BTW, I was thinking today, and I think I have figured out my thoughts on terminology about whether "dynamically typed" is an oxymoron. I know the topic of using the term "untyped" to refer to "dynamically typed" languages has come up before, and I don't know how much of this has been said. (I don't see discussion in this thread anywhere, which seems weird. Meh.) But I saw it with more clarity than I had before, so thought I would share. :-p

Anyway, I think the critical part of this is what you consider "type" to apply to in the context of "typed language", for it can apply to either variables or to values. In short, if you view types as applying to variables, it makes sense to call dynamically-typed languages "untyped", and to view "dynamically-typed" as a horrible perversion in terms. If you view types as applying to values, then "dynamically-typed" makes perfect sense.

In a dynamically-typed language, it doesn't make sense to talk about the type of a variable, because the type of the data it holds can change over time. It doesn't even make sense to talk about the type of a variable at a particular program point, because you have code such as

Code: Select all

if foo():
    x = 5
else:
    x = "Hello"
What is the type of x at the end of the code snippet? At best you can say it is either an int or a string. But the reason you can't really do better is because x itself doesn't have a type... the value it holds is either an int or a string, but x itself is untyped.

So then we ask what it means if a language is "typed". If it means that variables have types, then the above code cannot be a typed language. If values have types, then the above code is a dynamically-typed language.

(For my own opinion, while I don't see how you can say that x is typed in the above example, I still tend to use the term "dynamically-typed". I think that even if it isn't completely correct in some sense, it's far more useful to speak of untyped languages like ASM, statically-typed languages like ML, and dynamically-typed languages like Python, as if there were three separate categories, rather than conflate the sense that ASM is untyped with the sense that Python is untyped. Of course, to even do this means that you are being rigid... where does C go? It's not untyped like ASM, but nor is it as deserving of "statically-typed" as ML is, because it's too easy to break type safety through buffer overruns and pointer casts and such.)

User avatar
Berengal
Superabacus Mystic of the First Rank
Posts: 2707
Joined: Thu May 24, 2007 5:51 am UTC
Location: Bergen, Norway
Contact:

Re: Static vs. Dynamic Typing

Postby Berengal » Tue Apr 22, 2008 12:34 pm UTC

So, statically typed = variables have type (and they cannot be changed), while dynamically typed = variables don't have types? (Untyped = everything's a single type).
Using this definition, C is statically typed because its variables have type. Just because it's values don't have type (they're all bits anyway. Cast them to whatever you want) doesn't mean the language is untyped.
There's also the strong-weak-untyped axis. Untyped is the same as in the static-dynamic-untyped axis; when everything's a single type, there's no point in talking about types at all and the discussion is void. Strong typing means types are enforced. Use a string where an int is required, and the program doesn't even try to evaluate. Weak means it'll try anyway, stopping only if the types are incompatible. This would mean C is weakly typed, because it'll just divide that *char with 15, continuing on as if everything was fine (the compiler will complain, but it'll still compile). It isn't completely untyped, because it will do type-conversion in some cases, for example int + float will convert the int to a float before performing the addition instead of adding the float like it was an int (or the int like it was a float). C is an example of a static-weak typed language. Python is a dynamic-strong typed language (although one could argue that duck-typed languages care less about types than properties of data. Python still has type-checking available though).

I'd say a language is typed as long as it has a notion of type somewhere, be that in it's variables or values or conversion norms. If everything in a language is of a single type, if 0x41 and 'A' simply are two ways of writing the number 65, and "AKTBD" + 0x4384629572 is a perfectly valid piece of code, then the language is untyped. Assembly is such a language.
It is practically impossible to teach good programming to students who are motivated by money: As potential programmers they are mentally mutilated beyond hope of regeneration.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11116
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Static vs. Dynamic Typing

Postby Yakk » Tue Apr 22, 2008 2:16 pm UTC

static typed: you can introduce type-checks that are static in nature, that are not based off of run-time state.

dynamic typed: you can introduce type-checks that are dynamic in nature, that are based off of run-time state.

non typed: has neither of the above features.

Most static typed languages have dynamic typing as well. Typically dynamically typed languages have easier syntax for doing dynamic type checks.

C has static types, but they are weak static types: you get at most warnings.

C++ has stronger static types, and dynamic typing.
It also has the exceedingly powerful template and shortly concept language features to create crazy static type checks.

Python/perl/etc has dynamic types.

That work?
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

Rysto
Posts: 1460
Joined: Wed Mar 21, 2007 4:07 am UTC

Re: Static vs. Dynamic Typing

Postby Rysto » Tue Apr 22, 2008 2:42 pm UTC

Yakk wrote:C has static types, but they are weak static types: you get at most warnings.

Not always. Consider:

struct foo * ptr = (struct bar *)something;

That's a type error in C. Now, there are certainly many cases in which you do only get a warning, if that.

coppro
Posts: 117
Joined: Mon Feb 04, 2008 6:04 am UTC

Re: Static vs. Dynamic Typing

Postby coppro » Sun Apr 27, 2008 5:36 am UTC

Rysto wrote:I just wrote a piece of code that amuses me. I guess it forms an argument against static typing -- or at least, mandatory type annotations. Get a load of this monstrosity:

To honest, a lot of the verbosity would be cut down if Java allowed you to parameterize type variables. My long class names don't help, either.
This is why C++ has typedefs.

User avatar
ash.gti
Posts: 404
Joined: Thu Feb 07, 2008 1:18 am UTC
Location: Probably a coffee shop.

Re: Static vs. Dynamic Typing

Postby ash.gti » Wed Jul 23, 2008 7:16 pm UTC

You know, if you want duck typing in C you can use Objective-C's id type.

It lets you do this:

Code: Select all

id a = [[NSNumber alloc] initWithInt: 100];
a = [[NSString alloc] init:"Hello World"];



Only catch is you have to use Objective-C types. However, they do have wrappers, like NSNumber for all the basic types.

No warnings, or errors or anything. But it is duck typing so you need to make sure you check your data type before you do something.

That's why they give you the isKindOf method

Code: Select all

#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSString.h>
#import <iostream>

int main (int argc, char * const argv[]) {
   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   id ptr[2] = {[[NSString alloc] initWithCString: "Hello World"], [[NSNumber alloc] initWithInt: 85]};

   
   if ([ptr[0] isKindOfClass: [NSString class]] == YES)
      std::cout << "its a string " << [ptr[0] UTF8String] << std::endl;
   else
      std::cout << "its not a string" << std::endl;
   
   if ([ptr[1] isKindOfClass: [NSNumber class]] == YES)
      std::cout << "its a number " << [[ptr[1] stringValue] UTF8String] << std::endl;
   else
      std::cout << "its not a number" << std::endl;

   [ptr[1] release];
   ptr[1] = [[NSString alloc] initWithCString: "Hi Mom!"];

   if ([ptr[1] isKindOfClass: [NSString class]] == YES)
      std::cout << "its a string " << [ptr[1] UTF8String] << std::endl;
   else
      std::cout << "its not a string" << std::endl;
   
   [ptr[0] release];
   [ptr[1] release];
   [pool release];
}


The id data type is pretty useful I have found. The thing I like most about Objective-C++ is I get to choose when to use static typing or duck typing, and when I need strong data types or weak data types. It really lets you do just about anything you'd want to.
# drinks WAY to much espresso

User avatar
hotaru
Posts: 1045
Joined: Fri Apr 13, 2007 6:54 pm UTC

Re: Static vs. Dynamic Typing

Postby hotaru » Thu Jul 24, 2008 6:39 am UTC

EvanED wrote:In a dynamically-typed language, it doesn't make sense to talk about the type of a variable, because the type of the data it holds can change over time. It doesn't even make sense to talk about the type of a variable at a particular program point, because you have code such as

Code: Select all

if foo():
    x = 5
else:
    x = "Hello"
What is the type of x at the end of the code snippet? At best you can say it is either an int or a string. But the reason you can't really do better is because x itself doesn't have a type... the value it holds is either an int or a string, but x itself is untyped.

except in languages where you can do things like this...

Code: Select all

int|string x;
if(foo())
  x = 5;
else
  x = "Hello";

Code: Select all

factorial product enumFromTo 1
isPrime n 
factorial (1) `mod== 1

User avatar
aleflamedyud
wants your cookies
Posts: 3307
Joined: Tue Oct 09, 2007 7:50 pm UTC
Location: The Central Bureaucracy

Re: Static vs. Dynamic Typing

Postby aleflamedyud » Sat Jul 26, 2008 5:44 am UTC

As someone spending his summer implementing a GUI designer in Python, allow me to definitely and STRONGLY side with static typing. I've gone through this situation at least a hundred fucking times by now:

1) Make minor change to program.
2) Try to start program from GUI shell, the only way to provide it its proper runtime environment.
3) It doesn't start. The icon just sits there, blinking and saying it's starting.
4) I read the logs and find out I made a minor syntax or punctuation error. Or maybe I tried to call insert instead of add on a container widget. Or the runtime library can't find a process ID because it didn't create a process, but expected a process object.
5) Repeat until the program actually works, for restricted values of "works".

Dynamic typing is great for prototyping and for small scripts, but as the size of the program in question grows the ability to detect trivial and stupid errors without having to actually run the program becomes polynomially more useful.
"With kindness comes naïveté. Courage becomes foolhardiness. And dedication has no reward. If you can't accept any of that, you are not fit to be a graduate student."

Rysto
Posts: 1460
Joined: Wed Mar 21, 2007 4:07 am UTC

Re: Static vs. Dynamic Typing

Postby Rysto » Sat Jul 26, 2008 2:06 pm UTC

I went through similar pain working on a GUI in TCL. In fact, that's what prompted this thread.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11116
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Static vs. Dynamic Typing

Postby Yakk » Sat Jul 26, 2008 6:54 pm UTC

To be fair, the dynamic typing zealots typically say that you should be having heavy duty unit tests on your entire infrastructure regardless of your type system.

And with heavy duty unit tests, you can create something stronger than a static type system. (Except, of course, running your unit tests usually takes longer than recompiling).

This does miss the efficiency, brevity and precision of a static type check system -- you end up being pretty sure that your static type engine that your language provides is bug free, while the test harness you write for your unit tests might be full of bugs, take as much work as the code you are testing, and be large, cumbersome and verbose compared to normal type markup.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

qbg
Posts: 586
Joined: Tue Dec 18, 2007 3:37 pm UTC

Re: Static vs. Dynamic Typing

Postby qbg » Sat Jul 26, 2008 8:07 pm UTC

Yakk wrote:And with heavy duty unit tests, you can create something stronger than a static type system. (Except, of course, running your unit tests usually takes longer than recompiling).

Yeah, most static type systems won't catch when you give a function that needs three integers the integers in the wrong order.

Using unit tests rather than a static type system could theoretically (though theory isn't practice) be faster because one would be able to invoke a subset of the tests when deemed necessary instead of a larger subset all the time.

Rysto
Posts: 1460
Joined: Wed Mar 21, 2007 4:07 am UTC

Re: Static vs. Dynamic Typing

Postby Rysto » Sat Jul 26, 2008 8:58 pm UTC

qbg wrote:Yeah, most static type systems won't catch when you give a function that needs three integers the integers in the wrong order.

Sometimes that's just a flaw in the type system, or in the programmer's use of it. Opaque types can catch these kind of bugs, but only in situations where the three integers represent different concepts. Here's an example. Here's a method declaration from the runtime of a parser generator I wrote:

public Action getAction(int state, int symbol);

Now, the fact that the states of this parser are represented by integers is just an implementation detail. If I could have declared an opaque "state" type that looked like an integer, but could not be used interchangeably with integers, then I couldn't mix up the order whenever I called the getAction() method.

Yet another example of the type of bug that a strong type system can catch easily that a dynamically typed language doesn't have a hope of catching.

qbg
Posts: 586
Joined: Tue Dec 18, 2007 3:37 pm UTC

Re: Static vs. Dynamic Typing

Postby qbg » Sun Jul 27, 2008 6:23 pm UTC

Rysto wrote:
qbg wrote:Yeah, most static type systems won't catch when you give a function that needs three integers the integers in the wrong order.

Sometimes that's just a flaw in the type system, or in the programmer's use of it. Opaque types can catch these kind of bugs, but only in situations where the three integers represent different concepts. Here's an example. Here's a method declaration from the runtime of a parser generator I wrote:

public Action getAction(int state, int symbol);

Now, the fact that the states of this parser are represented by integers is just an implementation detail. If I could have declared an opaque "state" type that looked like an integer, but could not be used interchangeably with integers, then I couldn't mix up the order whenever I called the getAction() method.

Yet another example of the type of bug that a strong type system can catch easily that a dynamically typed language doesn't have a hope of catching.

You can do something similar in a strongly & dynamically typed language.

Code: Select all

;; Just one way to implement your own type
(deftype state ()
  `(cons (eql state) integer))

(deftype our-symbol ()
  `(cons (eql our-symbol) integer))

(defun state (value)
  (check-type value integer)
  (cons 'state value))

(defun our-symbol (value)
  (check-type value integer)
  (cons 'our-symbol value))

(defun unpack-symbol (our-symbol)
  (check-type our-symbol our-symbol)
  (cdr our-symbol))

(defun unpack-state (state)
  (check-type state state)
  (cdr state))

(defun get-action (state symbol)
  (check-type state state)
  (check-type symbol our-symbol)
  (let ((state (unpack-state state))
         (symbol (unpack-symbol symbol)))
    (format t "Given ~a and ~a~%" state symbol)))

Then:

Code: Select all

CL-USER 15 > (state 5)
(STATE . 5)

CL-USER 16 > (state 'foo)

Error: The value FOO of VALUE is not of type INTEGER.
  1 (continue) Supply a new value of VALUE.
  2 (abort) Return to level 0.
  3 Return to top loop level 0.

CL-USER 24 > (get-action (state 5) (our-symbol 4))
Given 5 and 4
NIL

CL-USER 25 > (get-action (state 5) (our-symbol 'foo))

Error: The value FOO of VALUE is not of type INTEGER.
  1 (continue) Supply a new value of VALUE.
  2 (abort) Return to level 0.
  3 Return to top loop level 0.

CL-USER 27 > (get-action (our-symbol 5) (state 4))

Error: The value (OUR-SYMBOL . 5) of STATE is not of type STATE.
  1 (continue) Supply a new value of STATE.
  2 (abort) Return to level 0.
  3 Return to top loop level 0.


So you can do something similar, but your errors still won't be caught until run time, unless your compiler can deduce obvious type errors and your code is structured in such a way that the type error is obvious.

photosinensis
Posts: 163
Joined: Wed Aug 22, 2007 6:17 am UTC

Re: Static vs. Dynamic Typing

Postby photosinensis » Sun Jul 27, 2008 11:08 pm UTC

In the grand tradition of flame wars everywhere (why else would this forum be called "Religious Wars"?), I'm going to jump in without having actually read the rest of the thread. Know that while these may be my actual opinions, my defense of them is somewhat tongue-in-cheek.

Personally, I prefer dynamic typing. In my cursory glance through this thread, I've seen some things like "static typing helps you find type errors sooner" and "IDEs have better support for statically typed languages".

IDEs are for people who want to look like programmers. Real programmers don't really give a damn about them, and may eschew them entirely.

The first one is bull, particularly for interpreted/bytecode interpreted languages, where there is no compile step. I'm going to use Python as my dynamic language here, and C++ as my static language (because I know them well enough to explain myself in them).

In Python, you don't really care what type a variable is. It could be an object (old or new style), a built in type (all of which are new style objects), or a function. As long as that variable has the attribute you're using, you're fine. If you do have a type error, the interpreter will spit out an AttributeError and tell you exactly how you broke everything. Any type checking beyond that is what one professor of mine called "chicken typing" (this was actually in his book on the Groovy programming language, which allows for some static typing for optimization), done mostly out of insecurity by those unused to duck-typed languages like Python. In short, if you're worrying about typing in a dynamic language, you're probably doing it wrong. Of course, if you absolutely must have a type conversion (such as casting an int to a float for the purposes of division, as we all know that most languages1 treat integer division and floating point division very differently.

Now, in C++, if you bork a method, you may be royally screwed, particularly if the method called looks like a method that's already defined. I know that on several occasions while overloading operators, I've gotten several pages worth of compiler output for a single type error, and I had no clue what to do with it. Of course, a large chunk of my problem here is C++ itself. In contrast to Python's single line telling me where my AttributeError is and what I've screwed up, I have a giant mess on my hands. (Of course, it also helps that overloading operators is far easier in Python than C++. Don't get me started on Java here.)

What's more, static languages don't usually have very good support for closures or performing operations on functions, both of which I've used in even toy programs. For example, I was working on a program that fetched rates from several different hotels earlier this summer as a part of a class. Compared to the majority of the class, which was schooled in C++, C#, and Java, my project's class hierarchy was much simpler and easier to follow for a fairly simple reason. Most of the other students were forced by their languages to implement a different class (using a common interface, of course--they weren't stupid) for each hotel just to change the rate fetching function. Unlike them, I was able to define that particular function at runtime by creating the fetching functions as I needed them (yay for lambda!), and providing that as an argument to the object's initializer (that's kind of like a constructor for you C++/Java/C# folk). Try doing that in a static language--none of them that I know of allow for such things (though I could be wrong).

And don't get me started on C's typing shenanigans--statically typed, but the typing is so weak and unsafe that it may as well not exist. Storing a number as a char simply because char is 7 bits instead of small int's 8 bits is insane. Yes, you can still do whatever you want with that variable. It's crazy2.

As for unit tests, all code, regardless of language, should be rigorously and thoroughly tested. Dynamic (and object oriented) languages make unit testing a bit easier than other testing methods. Unit tests may not be right for your project and/or language, but there is some way of testing it.

1. Python 3.0 will not do this, removing this particular instance of type conversion. However, you'll still want to convert input strings to other types as needed. I'm not sure how I feel about this.
2. Of course, I love C, simply because it's insane like that--obviously Dennis Ritchie was correct in thinking that coder types would love this devil that he hath wrought.
While I clicked my fav'rite bookmark, suddenly there came a warning,
And my heart was filled with mournng, mourning for my dear amour.
"'Tis not possible!" I uttered, "Give me back my free hardcore!"
Quoth the server: 404.

Rysto
Posts: 1460
Joined: Wed Mar 21, 2007 4:07 am UTC

Re: Static vs. Dynamic Typing

Postby Rysto » Sun Jul 27, 2008 11:39 pm UTC

photosinensis wrote:IDEs are for people who want to look like programmers. Real programmers don't really give a damn about them, and may eschew them entirely.

Oh, kindly spare us this "Real Programmer" nonsense. IDEs are a tool to increase programmer productivity. I don't know about "Real Programmers", but professional programmers aren't afraid of new tools that make them better coders.

The first one is bull, particularly for interpreted/bytecode interpreted languages, where there is no compile step.

"Bytecode interpreted" languages have to be compiled to bytecode before they can be run. You know, like Java?

In short, if you're worrying about typing in a dynamic language, you're probably doing it wrong.

I couldn't disagree more. Because ultimately, the type of an object tells you what you can do with the object -- what methods can be called on it, and what variables it exposes. And even in a dynamic language, you had better be certain that you can call foo() on an object if you're going to try to do so(or, you have to handle whatever the language does if you can't call foo()).

Now, in C++, if you bork a method, you may be royally screwed, particularly if the method called looks like a method that's already defined. I know that on several occasions while overloading operators, I've gotten several pages worth of compiler output for a single type error, and I had no clue what to do with it. Of course, a large chunk of my problem here is C++ itself. In contrast to Python's single line telling me where my AttributeError is and what I've screwed up, I have a giant mess on my hands. (Of course, it also helps that overloading operators is far easier in Python than C++. Don't get me started on Java here.)

This is a terrible example. C++ is absolutely the worst example to use when you're talking about quality of error messages, especially if you're talking about the quality of error messages you get from g++. This doesn't generalize to all statically typed languages at all, so the argument is totally invalid.

What's more, static languages don't usually have very good support for closures or performing operations on functions, both of which I've used in even toy programs. For example, I was working on a program that fetched rates from several different hotels earlier this summer as a part of a class. Compared to the majority of the class, which was schooled in C++, C#, and Java, my project's class hierarchy was much simpler and easier to follow for a fairly simple reason. Most of the other students were forced by their languages to implement a different class (using a common interface, of course--they weren't stupid) for each hotel just to change the rate fetching function. Unlike them, I was able to define that particular function at runtime by creating the fetching functions as I needed them (yay for lambda!), and providing that as an argument to the object's initializer (that's kind of like a constructor for you C++/Java/C# folk). Try doing that in a static language--none of them that I know of allow for such things (though I could be wrong).

How about you try using a statically typed functional language instead of an imperative one? ML and Haskell are the most prominent examples. Your argument here is that you prefer to program in a functional style, with is completely orthogonal to the issue of static vs. dynamic typing.

BTW: C++ 0x is going to add support for lambdas and (I believe) closures, although I don't they'll be useful because C++ uses manual memory management.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Static vs. Dynamic Typing

Postby EvanED » Sun Jul 27, 2008 11:49 pm UTC

photosinensis wrote:IDEs are for people who want to look like programmers. Real programmers don't really give a damn about them, and may eschew them entirely.
Agreed with Rysto here: "Oh, kindly spare us this "Real Programmer" nonsense. IDEs are a tool to increase programmer productivity. I don't know about "Real Programmers", but professional programmers aren't afraid of new tools that make them better coders." See the IDE thread for my thoughts.

The first one is bull, particularly for interpreted/bytecode interpreted languages, where there is no compile step. I'm going to use Python as my dynamic language here, and C++ as my static language (because I know them well enough to explain myself in them).
No it isn't. Here's an error which can easily crop up in a dynamic language. (Hell, it crops up in Java before 1.4.) You have a list of objects. Because it's dynamically typed, that list can hold anything. By accident, you insert an int into it, when you expect them to be strings. (To be more precise, to support the methods that string provides, say length().) Later you pull that element out and call .length(). It fails because ints don't have that method.

But where was that put into the list in the first place? Because /that's/ where the bug is. Tracking down this kind of error is a lot of times only a little less annoying than tracking down pointer errors in C.

Contrast that with a language like C++ or Java 1.5+, where you declare that list so that it only holds strings, and it gives you an error at the insertion point.

Try doing that in a static language--none of them that I know of allow for such things (though I could be wrong).
Yes, you're (very) wrong. Haskell, SML, OCaml, Miranda, I believe C# now (or at least soon), I believe an upcoming version of Java, and even C++0x all support closures. There's even a set of Common Lisp macros that give you something like a statically-typed Lisp.

Rysto wrote:BTW: C++ 0x is going to add support for lambdas and (I believe) closures, although I don't they'll be useful because C++ uses manual memory management.
Don't worry... they'll be plenty useful. Maybe not so much as in a functional language, but I fully expect there will be plenty of cases where it's the best thing to do.

qbg
Posts: 586
Joined: Tue Dec 18, 2007 3:37 pm UTC

Re: Static vs. Dynamic Typing

Postby qbg » Mon Jul 28, 2008 12:32 am UTC

EvanED wrote:Here's an error which can easily crop up in a dynamic language. (Hell, it crops up in Java before 1.4.) You have a list of objects. Because it's dynamically typed, that list can hold anything. By accident, you insert an int into it, when you expect them to be strings. (To be more precise, to support the methods that string provides, say length().) Later you pull that element out and call .length(). It fails because ints don't have that method.

But where was that put into the list in the first place? Because /that's/ where the bug is. Tracking down this kind of error is a lot of times only a little less annoying than tracking down pointer errors in C.

Contrast that with a language like C++ or Java 1.5+, where you declare that list so that it only holds strings, and it gives you an error at the insertion point.

The same solution would in a dynamically typed language too.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11116
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Static vs. Dynamic Typing

Postby Yakk » Mon Jul 28, 2008 3:51 pm UTC

Now, in C++, if you bork a method, you may be royally screwed, particularly if the method called looks like a method that's already defined. I know that on several occasions while overloading operators, I've gotten several pages worth of compiler output for a single type error, and I had no clue what to do with it. Of course, a large chunk of my problem here is C++ itself. In contrast to Python's single line telling me where my AttributeError is and what I've screwed up, I have a giant mess on my hands. (Of course, it also helps that overloading operators is far easier in Python than C++. Don't get me started on Java here.)


If you bork a method signature in C++, you get the error before you run your program.

If you do a similar bork in python, you get the error 10 months down the line when an edge case turns up, and an attribute error is spit out. It is quite disconnected from the actual point where the error was, because you stored it in intermediate data structures, and possibly 99% of the methods lined up with the right signatures (or ones sufficiently compatible).

What's more, static languages don't usually have very good support for closures or performing operations on functions, both of which I've used in even toy programs. For example, I was working on a program that fetched rates from several different hotels earlier this summer as a part of a class. Compared to the majority of the class, which was schooled in C++, C#, and Java, my project's class hierarchy was much simpler and easier to follow for a fairly simple reason. Most of the other students were forced by their languages to implement a different class (using a common interface, of course--they weren't stupid) for each hotel just to change the rate fetching function. Unlike them, I was able to define that particular function at runtime by creating the fetching functions as I needed them (yay for lambda!), and providing that as an argument to the object's initializer (that's kind of like a constructor for you C++/Java/C# folk). Try doing that in a static language--none of them that I know of allow for such things (though I could be wrong).


Yes, when building toy throw-away programs, Python is quite quick. So is perl. :-)

Also on the C++ side, you can often write a program that writes, compiles, and links C++ code, and it will still run faster than the Python equivilent. ;)

Closures are coming in C++0x. C# has them. I know someone who (completely insane) implemented them in a platform-dependent way in C (he manually wrote to the byte code. . .)

As for unit tests, all code, regardless of language, should be rigorously and thoroughly tested. Dynamic (and object oriented) languages make unit testing a bit easier than other testing methods. Unit tests may not be right for your project and/or language, but there is some way of testing it.


Interestingly, I can do extensive unit tests 'out of the bag' using the static type system. I can check the types of my arguments ... by giving each one a type. I can then have my compiler do a decent proof that I only get arguments of those types by ... compiling.

Rysto wrote:This is a terrible example. C++ is absolutely the worst example to use when you're talking about quality of error messages, especially if you're talking about the quality of error messages you get from g++. This doesn't generalize to all statically typed languages at all, so the argument is totally invalid.


A good chunk of that is because good old C was developed before they knew how to develop languages in such a way that parsers don't have to be batshit insane. :)

As an aside, the 0x line will make template errors MUCH easier with the new concept concept.

BTW: C++ 0x is going to add support for lambdas and (I believe) closures, although I don't they'll be useful because C++ uses manual memory management.

You can copy the local variables by value. If you are using smart pointers and references, this copy-by-value will prevent the data from going "poof" on you.

If you are using bare C-style memory management, you won't be able to assume pointer lifespan will last long enough.

Note that in C0x you'll be able to specify which variables from the surrounding scope you import. That means the "python this-is-not-a-leak" closure problem (variables, possibly holding significant resources, silently persisting because a closure that could refer to them is hanging around indefinately) is less likely to happen.

Of course, such problems really rear their ugly head in large, complex projects, where if you accidentally keep every variable you have ever used in memory you have a problem. In small projects, keeping every reference alive indefinately isn't a problem -- you could emulate that kind of garbage collection in C by #define delete(x) to nothing. ;) (ok ok, it doesn't quite work, because 3rd party code could delete your memory...)
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

photosinensis
Posts: 163
Joined: Wed Aug 22, 2007 6:17 am UTC

Re: Static vs. Dynamic Typing

Postby photosinensis » Tue Jul 29, 2008 12:28 am UTC

Okay, so my inexperience with functional languages other than Lisp (and what support the paradigm has in Ruby and Python) is showing.

Rysto wrote:
photosinensis wrote:In short, if you're worrying about typing in a dynamic language, you're probably doing it wrong.

I couldn't disagree more. Because ultimately, the type of an object tells you what you can do with the object -- what methods can be called on it, and what variables it exposes. And even in a dynamic language, you had better be certain that you can call foo() on an object if you're going to try to do so(or, you have to handle whatever the language does if you can't call foo()).


This seems to be more of an argument about strong vs. weak typing, not dynamic vs. static typing. I can still fairly easily tell what attributes are available in an object in Python. If I'm in doubt (because I've lost the documentation or something), I can readily drop into the interactive interpreter and call the type attribute (though I believe this only works on new style objects). What's more, most dynamically typed languages have a fairly consistent way of handling a call to an attribute that isn't there.

EvanED wrote:Quote:
The first one is bull, particularly for interpreted/bytecode interpreted languages, where there is no compile step. I'm going to use Python as my dynamic language here, and C++ as my static language (because I know them well enough to explain myself in them).
No it isn't. Here's an error which can easily crop up in a dynamic language. (Hell, it crops up in Java before 1.4.) You have a list of objects. Because it's dynamically typed, that list can hold anything. By accident, you insert an int into it, when you expect them to be strings. (To be more precise, to support the methods that string provides, say length().) Later you pull that element out and call .length(). It fails because ints don't have that method.

But where was that put into the list in the first place? Because /that's/ where the bug is. Tracking down this kind of error is a lot of times only a little less annoying than tracking down pointer errors in C.

Contrast that with a language like C++ or Java 1.5+, where you declare that list so that it only holds strings, and it gives you an error at the insertion point.


And this is why you don't just do shit blindly. The language assumes you know what you're doing, even if you don't. I can still declare a Vector or ArrayList of objects in Java and from there put anything I want in it (except primitives, damn Java). If you're depending on the language to stop you from doing something stupid, you're doing it wrong. What's more, your language's idea of "something stupid" may get in your way. This is exactly why I hate Java.

Rysto wrote:This is a terrible example. C++ is absolutely the worst example to use when you're talking about quality of error messages, especially if you're talking about the quality of error messages you get from g++. This doesn't generalize to all statically typed languages at all, so the argument is totally invalid.


I chose C++ because it's the perfect straw man in this case. Well, that, and I don't know C# at all (it's a language I've spent the last year or so artfully avoiding). C++ shouldn't be taken seriously today anyway: the problems it solved are better tackled using other languages that weren't available/mature in its heyday.
While I clicked my fav'rite bookmark, suddenly there came a warning,
And my heart was filled with mournng, mourning for my dear amour.
"'Tis not possible!" I uttered, "Give me back my free hardcore!"
Quoth the server: 404.

User avatar
Berengal
Superabacus Mystic of the First Rank
Posts: 2707
Joined: Thu May 24, 2007 5:51 am UTC
Location: Bergen, Norway
Contact:

Re: Static vs. Dynamic Typing

Postby Berengal » Tue Jul 29, 2008 2:25 pm UTC

Rysto wrote:ultimately, the type of an object tells you what you can do with the object

Wrong. Ultimately, the attributes of an object tells you what you can do with it. A common pattern in python is "getattr($OBJECT, $FUNCTION_NAME, $DEFAULT_FUNCTION)($ARGUMENTS)", which combined with giving single instances new attributes makes for some pretty neat tricks. It's a while ago since I wrote this, so it's in pseudo-python:

Code: Select all

class Socket(twisted.something):
  #------
  def recieve(self, message):
    tokens = message.split()
    getattr(self, "command_" + tokens[0], invalidCommand)(tokens[1:])
#------

class Server(twisted.somethingElse):
  #------
  def giveAdminRights(self, connection):
    for command in self.adminCommands:
      setattr(connection, 'command_admin_' + command.__name__, command)
#------

Note that the connection argument to the giveAdminRights method is of type Socket. This means that I potentially have lots of Sockets running around, where only some of them have admin commands.

Also, as another point in dynamic languages' favor, reflection makes parsing commands and adding and removing commands much easier and less error-prone, as I don't have to maintain a separate switch statement to parse the input and call the right method (and possibly checking (or forgetting to check) admin rights). Some static languages support reflection (java is one of them), but I consider it exclusive to dynamic languages nontheless because reflection is dynamic and happens at runtime, so it's impossible to check statically at compile time anyway. The only errors you'll get are runtime errors.
It is practically impossible to teach good programming to students who are motivated by money: As potential programmers they are mentally mutilated beyond hope of regeneration.


Return to “Religious Wars”

Who is online

Users browsing this forum: No registered users and 4 guests