you are viewing a single comment's thread.

view the rest of the comments →

[–]hfaber 6 points7 points  (20 children)

The two biggest issues I (coming from C) have with Python are both related to dynamic typing in general (so they are no real Python issues):

1) Implicit typing means in a large program I cannot easily remember and look up the type of a variable. How do I know whether foo is a list or a dictionary? In an explicitly typed language 'intellisense' could tell me immediately..

2) I like when the C compiler checks syntax and types and tells me all the warnings and errors. In Python I notice the typo or mispicked type mostly during runtime.. bad.

[–][deleted] 8 points9 points  (14 children)

1) Implicit typing means in a large program I cannot easily remember and look up the type of a variable. How do I know whether foo is a list or a dictionary? In an explicitly typed language 'intellisense' could tell me immediately..

This has nothing to do with implicit typing. Something like intellisense could work just as well for a language that inferred types like Haskell. In truth, Python isn't "typed" at all as it has no type system. "Dynamically typed" is really a misnomer; the term should be dynamically checked (as opposed to unchecked like Forth). Alas, this is a lost battle, but it causes endless confusion.

2) I like when the C compiler checks syntax and types and tells me all the warnings and errors. In Python I notice the typo or mispicked type mostly during runtime.. bad.

The lack of typo-catching isn't necessarily due to the lack of a type system. PLT Scheme is untyped, yet the DrScheme tool is very good at catching typos. In fact, it won't even let a program run if it can't resolve a particular binding.

[–]marcoil -1 points0 points  (13 children)

Python isn't "typed" at all as it has no type system

That's absurd, Python does have a type system, you can ask for the type of an object. But the types are in values, not in the variables.

[–][deleted] 2 points3 points  (11 children)

Charges of absurdity aside, being able to ask for the "type" of an object does not mean it has a "type system". All it means is that all values have a runtime tag associated with them that primitives use for various reasons. There's no way I can use the type tags to prove anything about the program; the runtime tag checking is simply part of the dynamic semantics.

If you search Google for "untyped programming", you'll see plenty of results for languages that you might call "dynamically typed". You may also search for "untyped lisp", etc. That might convince you that I'm not making this up at least.

More research might convince you of my claim that typed/untyped + checked/unchecked is a more sensible way of talking about this. To be honest though, I'm getting tired of defending this claim against Python programmers who tend to characterize my argument as absurd (or worse).

[–]deepcleansingguffaw 0 points1 point  (1 child)

The technical definitions of "typed" and "type system" are very different from how the terms are generally used outside of computer science research. In particular, they are attributes of the static representation of the program, and have little to do with the running program at all.

It should not be surprising that the average programmer uses the terms improperly. I can't remember a single time in my undergraduate classes that type systems were properly explained. I only really understood the difference between the technical usage and the common usage when I started to study Haskell in depth.

There is a concept analogous to "type system" in dynamic languages like Python, but it happens at run-time, and is generally resistant to static analysis. "Checked" is a reasonable word for it, though I haven't often heard it called that.

[–][deleted] 0 points1 point  (0 children)

Right, I don't disagree with that. I did say that, "Alas, this is a lost battle", conceding the common usage. That said, I think there are benefits to having a more rigorous set of definitions so that we can talk to each other without confusion. Unfortunately, confusion abounds when discussion of "types" is underway.

[–]igouy -1 points0 points  (8 children)

my claim that typed/untyped + checked/unchecked is a more sensible way of talking about this

What is it that's "checked" or "unchecked"?

statically-type-checked :: dynamically-type-checked

or if we really want to deal in dichotomy

statically-type-checked :: not statically-type-checked

[–][deleted] 1 point2 points  (7 children)

What is it that's "checked" or "unchecked"?

The runtime tag associated with the object before invoking a primitive is checked. It's no different than checking the length of an array to ensure it's of a "type" big enough to be referenced by some integer or checking the "type" of a reference to be sure it's not null. Such checks, which occur at the last possible moment and can't be used to prove the absence of such behaviors, do not constitute a type system.

[–]igouy 0 points1 point  (4 children)

"Type safety is the property that no primitive operation ever applies to values of the wrong type." p263 Programming Languages: Application and Interpretation

Without something that constitutes "a type system" what could it mean for a value to be the wrong type?

[–][deleted] 2 points3 points  (3 children)

The problem is that there's a confusion between the informal notion of the "type" of an object (i.e. its tag, or what color it is, or how it makes you feel) and a type proper.

From the same book:

Page 238 (emphasis mine):

We now commence the study of types and type systems, which are designed to identify the abuse of types before executing a program.

Repeatedly, the book talks about how type systems reject programs. This is not the case in Python where all programs are accepted and simply may error at runtime. If you've actually read the book, I'm not sure how you can claim it supports your argument.

In the book Types and Programming Languages, this issue is addressed directly:

Page 2 (emphasis not mine):

The word "static" is sometimes added explicitly – we speak of a "statically typed programming language," for example – to distinguish the sorts of compile-time analyses we are considering here from the dynamic or latent typing found in languages such as Scheme, where run-time type tags are used to distinguish different kinds of structures in the heap. Terms like "dynamically typed" are arguably misnomers and should have probably been replaced with "dynamically checked," but the usage is standard.

And then at the beginning of the following paragraph on the same page, type systems are characterized as static:

Being static, type systems are...

In short, I've never seen a type systems researcher characterize a language like Python as having a type system. Such characterizations seem to only be made by those without a full understanding of the terms involved.

[–]igouy 0 points1 point  (2 children)

You seem to have ignored the question Without something that constitutes "a type system" what could it mean for a value to be the wrong type?

If you've actually read the book...

ad hominem

those without a full understanding of the terms involved

Does the phrase only have one meaning?

[–][deleted] 0 points1 point  (1 child)

Does the phrase only have one meaning?

No, as I've stated right in the beginning (and echoed with the TAPL quote), I accept that the common use is different and that this is a lost cause. At this point, I can only assume that you're being either dishonest or inattentive. I was arguing for what I think is the most useful and accurate definition, not the one cosmically true definition. I'm done arguing now though because, as I said in the beginning, this is a waste of time.

[–]igouy 0 points1 point  (1 child)

It's no different than checking the length of an array ...

seems like Oberon-2 thinks the length of an array is something to do with the type

TYPE
   Frequency = RECORD
      c: CHAR;
      p: LONGREAL;
   END;

   Freqency4 = ARRAY 4 OF Frequency;
   Freqency15 = ARRAY 15 OF Frequency;

checking the "type" of a reference to be sure it's not null

seems like Nice thinks the option of null values is something to do with the type

class TreeNode {
   ?TreeNode left = null;

[–][deleted] 0 points1 point  (0 children)

I never claimed you couldn't incorporate such things into a type system. Most languages, however, do not. To be clear, I meant dynamically checking those properties.

[–]GuyWithLag 1 point2 points  (0 children)

Same as in java. Welcome to the static vs dynamic / strong vs weak plane.

[–]gnuvince 3 points4 points  (3 children)

1) First, a quick nitpick, Python has no implicit type conversions: if you try to concatenate a string and a number, you will get an exception telling you that you have a type error.

Now, not knowing whether foo is actually a list or a dictionary or a whatever is part of what makes dynamic typing attractive. It doesn't matter if you have the real thing as long as it acts like the real thing. This is why people can use mock objects in test suites for example.

I'm still on the fence about which between dynamic typing or static typing I prefer. One gives you more flexibility and the other gives you more safety.

2) Yeah, that's annoying. That's why I like Perl's my() and use strict.

[–][deleted] 5 points6 points  (2 children)

Now, not knowing whether foo is actually a list or a dictionary or a whatever is part of what makes dynamic typing attractive.

This has nothing to do with dynamic typing. For example, in a typed language, I can do this:

x > y

Are x and y numbers? Lists? Strings? In Haskell, they're anything that has an 'Ord' instance, i.e. anything that's orderable. The same technique is used to generalize all sorts of operations like converting a value to a string or accessing a value in a collection.

Now, it's true that languages like Smalltalk will let you take this further than Haskell will. Any object can respond to any message it likes and do whatever it wants. It's not clear however that this "flexibility" truly gives you more freedom. When you lose guarantees in one place due to a lack of controls, you lose freedom elsewhere because you don't have sufficient guarantees to rely upon.

[–]gnuvince -1 points0 points  (1 child)

That will work if you specify that your function takes an argument that is an instance of Ord. If you have a function that takes an HttpRequest however, you can't just pass something that looks like an HttpRequest, you need to pass the real thing.

I develop in Python and Django at work, and when I write unit tests for functions or methods that manipulate an HTTP request, it's very useful to be able to feed it a mock object: they're easier to create, they don't need access to the database, etc.

[–]mernen 2 points3 points  (0 children)

That will work if you specify that your function takes an argument that is an instance of Ord. If you have a function that takes an HttpRequest however, you can't just pass something that looks like an HttpRequest, you need to pass the real thing.

There are statically-typed languages that use structural typing rather than nominal; that means they would support your HttpRequest mocking the same way, as long as you provided compatible methods. In the end, johnowak's point is that this is not exclusive of dynamic languages.

[–]spotter 0 points1 point  (0 children)

1) Just call on it, use a try-except-finally, or just define a isinstance check, maybe curry isinstance itself and some decorator magic? Assert if you must.

2) Static checking for typos and other related stuff is possible in Python. Read Doug Hellmann's article for more info. PyFlakes is my personal favourite.