• Welcome to the new COTI server. We've moved the Citizens to a new server. Please let us know in the COTI Website issue forum if you find any problems.
  • We, the systems administration staff, apologize for this unexpected outage of the boards. We have resolved the root cause of the problem and there should be no further disruptions.

Python 2 or 3?

I wrote Java 1 when it was new, and basically had to track with its development for my career. I don't ever remember Java having un-or-dynamically typed variables. If so, then no wonder they clamped down on that quickly. Perhaps it was in a prototype (Oak)?

I don't recall this in Java. C had templates that I think might have done something with variable typing, but IIRC (and it's been almost 20 years) you had to instantiate with a specific type. Then again, my memory is faulty in my old age.

Cheers,

Baron Ovka
 
C had void pointers which could point to "anything", but... it didn't feel the same.
 
I wrote Java 1 when it was new, and basically had to track with its development for my career. I don't ever remember Java having un-or-dynamically typed variables. If so, then no wonder they clamped down on that quickly. Perhaps it was in a prototype (Oak)?

Found the reference. "Design Patterns in Ruby", Russ Olsen (Addison-Wesley, 2008) From page 69:

"Almost all Java programs written before the advent of Java 1.5 -- and that covers the bulk of existing Java programs -- use the containers from the java.util package, things like HashMap and ArrayList. The pre-1.5 versions of these containers provided no type safety at all, and even post-1.5 Java continues to provide non-type-safe versions of these containers fro backward compatibility."
 
Found the reference. "Design Patterns in Ruby", Russ Olsen (Addison-Wesley, 2008) From page 69:

"Almost all Java programs written before the advent of Java 1.5 -- and that covers the bulk of existing Java programs -- use the containers from the java.util package, things like HashMap and ArrayList. The pre-1.5 versions of these containers provided no type safety at all, and even post-1.5 Java continues to provide non-type-safe versions of these containers fro backward compatibility."

Java has always had full type safety. The problem with the legacy containers is that they work with the universal superclass of Object. Everything descends from Object. So, technically, the universal containers are "type safe", but in practice, it doesn't quite work that way.

Java 5 introduced Generics which allowed things like the containers to be typed and checked at compile time, but during execution, all of that is lost. So, at compile time you can get a modicum of type safety, but at runtime, it goes away as the containers are still, at their core, based on collections of Object.

Dynamic typing is wonderful for small projects, but it doesn't scale well with larger projects, larger teams, and legacy code where the original authors are no longer around. The magic of modern IDEs is mostly driven from working with typed languages.

Java is dynamic enough with its robust reflection capabilities, and commonplace runtime byte code engineering to mitigate most of the value of dynamic typing. The primary cost is wordiness of the code, which isn't a real issue with modern IDEs and auto complete.

There have only been a few occasions where I've wished for either Multiple Inheritance, or actual runtime dispatch.
 
Found the reference. "Design Patterns in Ruby", Russ Olsen (Addison-Wesley, 2008) From page 69:

"Almost all Java programs written before the advent of Java 1.5 -- and that covers the bulk of existing Java programs -- use the containers from the java.util package, things like HashMap and ArrayList. The pre-1.5 versions of these containers provided no type safety at all, and even post-1.5 Java continues to provide non-type-safe versions of these containers fro backward compatibility."

Oh you mean HASHTABLES. Well, duh, of COURSE they're not typed, because you should be able to put ANYTHING in them...

What?
 
Oh you mean HASHTABLES. Well, duh, of COURSE they're not typed, because you should be able to put ANYTHING in them...

What?

The value of universal containers far outweighed the costs of dealing with the early early Java type system.

Code:
List list = new ArrayList();
OtherClass o = new OtherClass();
list.add(o);
MyClass m = (MyClass)list.get(0); // <-- Runtime failure with Class Cast Exception


The Java Generic system is essentially a large construct of syntax sugar within the compiler to make working with such data structures easier, but the underlying runtime itself was essentially unchanged.

Code:
List<MyClass> list = new ArrayList<MyClass>(); // This can now be abbreviated: new ArrayList<>();
OtherClass o = new OtherClass();
list.add(o); // <-- Compile time failure, 'o' is not 'MyClass'
MyClass m = list.get(0); // no manual casting needed here as before

However, when compiled, the code for these routines is identical. You could use runtime constructs such as reflection (among other things) and stuff an "OtherClass" in to the list, internally, List is still a collection of Objects, and you'd still get the runtime exception on the get(0).

C would have the same problem as early Java were you to have a set of collections on void pointers (void *). However, you would NEVER know that you'd had the wrong "class" (struct, whatever), in your list, as the casts necessary to make it work in the source code are purely compile time, and not enforced at runtime. You'd find out by some awful core dump, if you're lucky.

C++ worked around it with its templating system. Here, you have universal source code, created for each different type (since the effect of invoking a template internally compiles a new version of the source code for the specific type), rather than a single set of universal code that's type agnostic as you have in Java.

Python suffers from the same problems as Java when it comes to generic data structures, but it does not enforce typing at runtime save through dispatch. You'll discover you have the wrong object when you try to invoke a method that does not exist on the wrong instance.

Java, too, of course, will fail if you try to invoke a method on an object that doesn't support it (yes, this is possible). But Java's casting also has a runtime effect of ensuring it's can be cast, vs simply a compile time effect. In Python, of course, you don't cast at all.

The Java model works. Has it's warts, but it works. I personally prefer typed code to untyped code, especially on large codebases. Having some faith that "if it compiles, it'll work (to a point)" when doing scary refactoring is a nice bedrock. Dynamic typed systems don't offer that.
 
I personally prefer typed code to untyped code, especially on large codebases. Having some faith that "if it compiles, it'll work (to a point)" when doing scary refactoring is a nice bedrock. Dynamic typed systems don't offer that.

For the most part I agree with a preference for strong types. Not sure that dynamic typing over-whelmingly adds great risk to the refactoring, compared to the other possible issues. This week's npm teapot issue is one, and one that any language with lots of add-ons faces.

One of my biggest drivers right now is testing. If I can't figure out how to write a test for something, and have a test ready, the code doesn't go in. It means I don't understand my path or my tools well enough. Frustrating at times, but strengthening. If I send an array to something that expects an integer, well, the tests should complain. Or I need more tests. :)
 
Not sure that dynamic typing over-whelmingly adds great risk to the refactoring, compared to the other possible issues. [...]

One of my biggest drivers right now is testing. If I can't figure out how to write a test for something, and have a test ready, the code doesn't go in. It means I don't understand my path or my tools well enough. [...]

Oh don't get me started about testing. After five years in the Pit of Quality, I have come out a rabid, rabid defender of anything that removes obstacles to testing. Test is a full decade behind dev. Or more.

You almost got me on a rant, there. As far as I know, there is no programming language (or environment, your pick) that has caught up with the need for developers to also be good at writing tests of all flavors. Whoops, almost started ranting again.

I'm waiting for the programming language that automagically builds the test scaffolding as programmers write code. I think it's going to require things that programming languages currently don't have. Or... well maybe it just requires oodles of annotations/decorators, but I bet that's not the answer.
 
Back
Top