Great talk! I throughly enjoyed it. Please post the slides. I didn't want to let you down with TSS comments ;) http://www.theserverside.com/news/thread.tss?thread_id=27239 I agree with a lot of the items that you talked about. Good stuff. I am not sure if I agree that JBoss is the best implementation of a J2EE server though. It is good, don't get me wrong, and I love the AOP stuff (although I wish it was usable outside of their container). However, J2EE has 'E' there for a reason. Why bother with a container if you don't have a top class JTA implementation? or JMS? If you don't need these things (90+% don't!) then just use a lightweight container such as Spring :) I was really impressed with your presentation. But it was very hard to follow because the camera sometimes missed your cursor. Could you upload the powerpoint file? Sincerely, Minkoo Seo Thanks for the talk Bruce, I enjoyed the insights from your particular multi-language perspective even though you did reinforce my disappointment with recent evolution in Java. I'm going on a diet anyway ! Looking forward to explore Groovy and Swing... Luis. (I meant Spring) Could you make the ppt on-line? Is there any way to obtain a full copy of the movie, not streaming? Or a different format like divx? The presentation is very interesting, but it took me 30 minutes to view the first 5 minutes and I am on a 1,5 Mbit/s line ;-( Ever tried Java Sound? I toyed around with it on Windows and it was playing mp3 fine. I had some problems on Linux, but then, there is always a problem with sound on Linux. I believe that meta data is more inspired by xdoclet than by C#. I am in the Java business since '99 and I have to admit that even though I should've known better I was very much following the Sun marketing path. It's just over the last 24 months, that I started to question Sun's marketing path. I believe it started with eclipse and Sun's way of trying to make this superior technology look bad. Your presentation helped me to put things into perspective. Very nice. Thx. Great talk! About unit testing... What do you think of the design by contract paradigm? Sincerely, Sylvain <hr><b>2004/07/13 23:37 EST (via web):</b><br> RE: Generics and typing Hi Bruce, I thought you talk was a little unfair on generics and also you said that python is latent (or inferred) typed. Python is weakly typed (checked at runtime), for an inferred (latent) type language see Haskell or Clean. The difference is that in a weakly typed language you get type errors at runtime whereas inferred typing is a type [sic] of strong typing and therefore you get type errors at compile time. However unlike traditionally strongly typed languages inferred type languages have very few type declarations. You can get Java to be weakly typed by declaring everything to be Object and using RTTI to call methods, see latest (or one back) edition of Dr. Dobb's. With generics you seem to be expecting it to be like templates, it isn't. Templates are almost like a separate language in C++. Whereas generics in Java are integrated with OO programming, the Generics in Java are inspired by generics in languages like Haskell and Clean (coincidently both inferred typing languages). Below is an example of generics which shows how it compliments rather than replaces OO. package junk.generics.bruceTalk; abstract class CatsAndDogs< CAT_DOG > { final int genes; CatsAndDogs( final int genes ) { this.genes = genes; } abstract CAT_DOG factory( final int genes ); abstract String speak(); } class Cat extends CatsAndDogs< Cat > { Cat( final int genes ) { super( genes ); } Cat factory( final int genes ) { return new Cat( genes ); } String speak() { return "Meow( " + genes + " )"; } } class Dog extends CatsAndDogs< Dog > { Dog( final int genes ) { super( genes ); } Dog factory( final int genes ) { return new Dog( genes ); } String speak() { return "Bark( " + genes + " )"; } } public class TestCatsAndDogs { static void speak( final CatsAndDogs catOrDog ) { System.out.println( catOrDog.speak() ); } static < CAT_DOG > CAT_DOG breed( final CatsAndDogs< CAT_DOG > female, final CatsAndDogs< CAT_DOG > male ) { return female.factory( ( female.genes + male.genes ) / 2 ); } public static void main( final String[] notUsed ) { final Cat katie = new Cat( 100 ); speak( katie ); final Cat ginger = new Cat( 200 ); speak( ginger ); final Cat kitten = breed( katie, ginger ); speak( kitten ); final Dog princess = new Dog( 10 ); speak( princess ); final Dog max = new Dog( 20 ); speak( max ); final Dog pup = breed( princess , max ); speak( pup ); } } The first thing to note is the example is very similar to normal OO. You start of with a base class or interface in this case CatsAndDogs. For the moment just forget the generics stuff and the factory stuff, its just an interface that defines speak. It used like any other interface, e.g. speak method. This is to emphasize that something like speak is best done with straight OO. Now the interesting bit, if you want to write a generic routine that breads either Cats or Dogs then you use generics. The declaration for bread is interesting: < CAT_DOG > CAT_DOG breed( final CatsAndDogs< CAT_DOG > female, final CatsAndDogs< CAT_DOG > male ) If the generics were omitted then you could bead a Cat with a Dog, with generics Cats can only bread with Cats and Dogs with Dogs and also bead returns a correctly typed object, either a Cat or a Dog not a CatsAndDogs. This is when you use generics, when you want to express a relationship that normal OO can't. In this case that the exact type of each argument must be identical and the return type is the same as the argument types. Breed must create a new type so we use a factory, the factory goes in the base class CatsAndDogs: abstract CAT_DOG factory( final int genes ); When the base class is extended the extension is qualified with its own type: class Cat extends CatsAndDogs< Cat > This way the compiler knows that the factory in Cat returns a Cat and the factory in Dog returns a Dog. Note how there is no casting in the program at all! I hope this doesn't sound preaching, I am a great fan of your books and taught myself Java from version 1 and also bought 2, Howard. howard.lovatt@iee.org ** very generous to put up this video, but please offer a low-bandwidth version :) ** Aurora - what's that when it's at home? Excellent talk. I only expected to watch about ten minutes of it at the beginning, such is the nature of these things but wound up watching the whole lot. Great stuff. On the subject of latent typing, one of the points you make is that you observe no more bugs in your programs using a language like Python as compared with Java. I'm sure this is the case, although I felt that compile-time type safety is more useful in a large program as compared with a small program. It helps to solve integration issues. The main point I would make is that whilst you may not find any more bugs in your programs, you yourself are a respected member of the programming community and I expect you've been programming for a long time! I doubt you have many bugs in your code full stop! The real test is when the average programmer finds no more bugs in their code using a language like Python/Smalltalk etc. The other aspect is it scaling to large teams; types can be useful in communicating interfaces. It's not so much of a problem when you develop a program yourself, but working with say ten others, I feel typing would reduce runtime errors in programs. >>> "I thought you talk was a little unfair on generics and also you said that python is latent (or inferred) typed." Wrong. Latent != Inferred. In latent typing, the action to be taken is based on the types of the objects used at run-time. Type _inference_ is performed by a compiler before run time. These cases are different, however they may appear similar to some programmers because, in both cases, the techniques save the programmer from an excess of keyboard typing. <hr><b>2004/07/19 12:18 EST (via web):</b><br> << In latent typing, the action to be taken is based on the types of the objects used at run-time. >> Who's the expert who has come up with that brilliant definition?? Taking an action "based on the types of the objects used at run-time" is exactly what's happening in every OO language. Ever heard of polymorphism? <hr><b>2004/07/19 12:18 EST (via web):</b><br> <hr><b>2004/07/19 12:28 EST (via web):</b><br> What you describe as latent typing should better be characterized by "no typing at all". You ask for an action on an object without specifying any type information and let the runtime machine find out whether the action is supported by that object. Where's the typing, please? Should it turn out that the action is not supported, don't worry: we are, in Bruce's definition, perfectly "type-safe", which means that there'll be a RT exception. Latent typing? Latent bugging... <hr><b>2004/07/19 12:38 EST (via web):</b><br> Please, folks, don't forget to check the "with heading" option. How come, by the way, that this forum is still in such a bad shape? Is that an example of Bruce's hypothesis that too much information hurts readability ;-) ? <hr><b>2004/07/19 17:26 EST (via web):</b><br> That's a little unfair isn't it? It wasn't my comment, but in OO languages despite choosing the actual implementation class at runtime, the method that's going to be invoked has been statically checked at compile time, because of the various rules surrounding superclasses and interfaces. That said, I'm not clear myself of what we see as the big advantage with "latent" typing and no typing at all; I mean, in that do you really win much if the thing falls over with some sort of segmentation violation or a type checking error; it's still fallen over and you didn't catch your defect at compile time. I suppose the latter is better, but perhaps not that much better. <hr><b>2004/07/20 10:25 EST (via web):</b><br> "in OO languages despite choosing the actual implementation class at runtime, the method that's going to be invoked has been statically checked at compile time". Yes, it has been statically checked but the action to be taken still depends on the implementation class chosen at runtime. I still fail to grasp the meaning of the term "latent typing". In which sense is there typing, and in which sense is it latent? <hr><b>2004/07/22 10:55 EST (via web):</b><br> I was almost sure and now I am pretty sure: Bruce is the Guru of the classroom example Java code. In real life it is all about 'Getting Things Done'. Yes, of course it is nice to explore the boundaries of Java, and then comparing it with Python, C++, write a book, walk in the park, do some relaxed interviews. It is nice to envision a world of peace. Unfortunately it is not what programmers are paid to do. Even worse: the average programmer does not even have a say in which language to code. IT managers are worse than marketeers, the sales can at least spell Java, while managers can't write. Anyway, I do think Bruce is an hounest person: he admits he does not understand a thing about enterprise programming. He is right, for once. If I was there I would have asked what Bruce thinks about Judoscript as I think it is a pretty cool platform. Yhere must be something wrong with it because I usually think exactly the opposite of Bruce. And yes: we want more video's! It was truly entertaining. jimC Bruce, thanks for releasing the video for us to see. About the Python vs. Perl question you were asked? The difference is in the scope. Perl was designed close to the shell (Bash on Steroids) just as PHP was designed for web scripting. Sure you can do other things with them, but they're intended purpose is specific, whereas Python is a general purpose language. Both languages in their most recent releases are trying to be more general purpose by adding scalability features, but at the same time, they're retaining their specific features (Sound familiar C/C++). The new versions are practically new languages and I would rather used the proven, tested Python than the new versions of these languages. I agree with you that there are advantages to checking types at compile time, that those advantages are small, or even insignificant. I think that static type checking benefits the machine more than the programmer. It helps the machine by allowing the code to compile to optimized machine language. How much does it really help the progammer? How often is a function argument just an integer? It usually requires additional constraints. Maybe it must be an integer between 50 and 100. Maybe it must be an odd integer. Normal type checking does not help here. In the end the program needs to be tested regardless of the typing method. Because good testing goes far beyond checking types, I believe type checking is insignificant. Randall Smith <hr><b>2004/07/26 12:55 EST (via web):</b><br> "Because good testing goes far beyond checking types, I believe type checking is insignificant." I'm sorry but don't you realize what an absurd statement this is? Is unit testing also insignificant because "good testing goes far beyond unit testing"? It's a complete mystery to me what problem you have with type checking. Why does the fact that type checking is sometimes too weak (one would like to check more sophisticated constraints) call for abandoning type checking, rather than making it stronger? tm <hr><b>2004/07/27 14:07 EST (via web):</b><br> When you consider type checking to be nothing more than "is it an integer", then it is of limited use. When a type is a BankAccount for example, which in itself is an aggregate of many other types, which in themselves are aggregates of many other types, then you are making lots of assumptions about the validity of your data. These assumptions are what saves you time and effort. It's also not insignificant the benefits strong typing bring to IDEs; intellisense or code assist for example cannot exist without it. I find this helps me no end, especially when using classes written by others. Keith. <hr><b>2004/07/28 05:22 EST (via web):</b><br> With respect to the earlier question about "latent typing", I don't think it's about runtime typing at all. Latent types are simply evaluated toward the end of compilation in a statically typed language. For instance, in C++ templates, I can write code that calls "speak" on an object of unknown type because *during compilation* at some point in the future that type will be determined, and using a class without a "speak" method in that context will result in a compiler error. The effect is similar to the "duck typing" phenomenon of dynamically typed languages, but it is still statically typed and will not result in runtime errors. Dave Benjamin <hr><b>2004/07/28 05:36 EST (via web):</b><br> Also, in languages with more modern type systems such as OCaml, you can call a method on an object without knowing its class. This is statically type-checked: # let speak x = x#talk;; val speak : < talk : 'a; .. > -> 'a = <fun> Here, "speak" will take any object "x" with at least a method "talk" that takes no parameters, and call that method. This is possible because the type of speak's parameter is not the class of "x" but merely the set of methods it supports, where ".." is a "row variable" meaning any number of additional methods. So, the static vs. dynamic argument over "latent typing" is in some sense a false dilemma. There are other ways of achieving what Bruce wants without templates or dynamic typing. Dave Benjamin <hr><b>2004/07/28 14:32 EST (via web):</b><br> There was some confusion whether Bruce's "latent typing" is statically or dynamically typed. In Python, it is not checked at compile time so the situation is different to OCaml. Bruce has clearly stated that what he considers "latent typing" is the dynamically-typed, Python way, and he has also argued that Python is nevertheless "type-safe" because for the definition of type-safety, it doesn't matter whether the check is done at compile- or at runtime. I disagree. however. tm Let's recapitulate how Bruce defined "latent typing": '''latent type: one that is implied by how it is used, but never explicitly specified. That is, the latent type is implied by the methods that you call on it. If your template function calls f() and g() on a type, then you imply a type that has methods f() and g(), even though that type is never actually defined anywhere.''' This is not the same as your OCaml example: here, I understand some type constraint on the parameter is explicitly specified. <hr><b>2004/07/29 01:43 EST (via web):</b><br> I wouldn't say that Bruce "clearly stated" that latent typing refers to the Python way, because he specifically compared Java to C++ in terms of their support for latent typing. If dynamic typing is prerequesite, why talk about statically typed languages at all? The OCaml example has no type constraint - for some reason this wiki removed the newline after the double-semicolon; the following line is the compiler's response to the statement, as if to say, "I have processed your request, and have determined that the type of 'speak' is a function taking an object with at least a "talk" method--which takes no arguments and returns a value of type 'a--and returning a value of type 'a. Since we did not define what "talk" returns, this function is actually polymorphic on the return type as well, ie. it returns whatever type "talk" returns. This is not to say that a type is never actually defined anywhere; in fact, this response tells you precisely what type is defined. What is not defined, however, is the *class* of speak's parameter. The distinction between types and classes is another issue that is often a bit fuzzy, unfortunately. PS - I still really enjoyed the presentation. Thanks for publishing it, Bruce. =) Dave Benjamin <hr><b>2004/07/29 10:17 EST (via web):</b><br> I don't speak OCaml and I need some help here. Maybe you could translate your code example into Java syntax to make the differences clear? What I don't understand is: how exactly does the compiler check a constraint if it hasn't been specified? I'll get back to a Python example that has been discussed in this forum (wiki-0053), similar to Eckel's robot.speak() example: def broadway(someone): print someone.sing() print someone.walk() print someone.speak() In Python, this is not checked at compile time (http://diary.recoil.org/pixel/archives/000193.html). Could it be? Blogger Pixel has pointed out that, if there is no constraint at someone, it's class simply can't be known at compile time. It could be determined by a random generator, for example. Unless the compiler really creates a "latent" type constraint that it attaches to someone, like "this must be an object that has a sing, walk and speak method". The problem of course is that now your type checking depends on implementation! In other words, the compiler has to analyze implementation details in order to define the interface. If you add print someone.scream() to the implementation of broadway, all your method calls will be broken, although the interface hasn't changed. That's why I have said, "latent typing" according to this definition has nothing at all to do with typing. There is no type, no interface, no OO. Is that what we want? I hope you can shed some light on this, Dave. tm <hr><b>2004/07/29 14:07 EST (via web):</b><br> It's difficult to express this concept in Java because the Java language simply does not support this type of behavior. Hopefully with some explanation this will make sense to you. Imagine we had a method like the following: public static ReturnType speak(ArgumentType x) { return x.talk(); } Let's ignore ReturnType for now and just focus on ArgumentType. What is ArgumentType? In Java, it must be one of the following: - the name of a class - the name of an interface However, what we want here is a third option. We want a type that doesn't care about classes or interfaces; all it cares about is what methods "x" supports. In an imaginary Java-like language, it might look something like this: type ArgumentType { public ReturnType talk(); public *; } Where the "*" means that an object of type ArgumentType may have any number of additional methods, as long as it has a "talk" method. The key idea here is that the class of "x" is completely irrelevant. It doesn't have to inherit from another class, and it doesn't have to be declared as implementing any particular interface. You can pass anything in as "x" as long as it satisfies the definition of ArgumentType. So, yes, there is a constraint on "X", and ArgumentType is an expression of that constraint. But it is an open constraint; as long as you meet the minimum criteria (implementing "talk"), there is no restriction on implementing any additional methods. In OCaml, this is all transparent, because the type of "x" is inferred. In the example I wrote earlier: let speak x = x#talk the type of "x" is "any object that implements 'talk'". If I were to rewrite it as follows: let speak x = x#talk; x#scream now the type of "x" has changed to "any method that implements 'talk' and 'scream'". If you had existing code that called "speak" on an object, and that object did not also implement "scream", you would now have a compiler error. I'm not quite sure why you see this as a dependency on implementation details. It makes no difference whatsoever how "talk" and "scream" are implemented, so long as they take the right parameters and have the right return types. In Java, this effect is usually accomplished with interfaces, but this is invasive. The object's class must be modified to say "implements Speaker" or something similar. Sometimes this is not possible, or not desirable. For instance, say you wanted to create a new class that behaves like a String in some ways--perhaps it has a "substring" and "replace" method only. If you wanted to write a method that took either a String or a member of this new class as an argument, you're stuck. You can't modify String to add an interface, and you can't inherit from it either. The best you can do is wrap String in an adapter class that implements an interface supporting "substring" and "replace". In a language where values can be typed not by their class but by the methods they support, this is not an issue. C++ (via templates) and OCaml can do this. Java can't. Going back to the above example, it still doesn't fully express what this simple one-liner of OCaml does, because it is not polymorphic on the return type. What we really want is something like this: public static <T> T speak(ArgumentType<T> x) { return x.talk(); } type ArgumentType<T> { public T talk(); public *; } Now, "speak" returns whatever type "x.talk" returns. It is now a polymorphic method. Another interesting approach is that taken by the Nice language. I'm not very well-versed in Nice, but basically, it allows you to assign interfaces to classes after the fact. So the type of "x" can be an interface providing the "talk" method (say, "Speaker"), and you can instruct the compiler that all instances of class "Dog" are "Speakers". This is more explicit because you must create an interface to get the effect, but it's non-invasive because you don't have to modify the original definition of "Dog". It's as if to say, "By the way, Dog is a Speaker", completely separate from where "Dog" was originally defined. Once again, this is compile-time checked. As to what is or is not a "latent type" and what is or is not "OO", I haven't been able to satisfy myself with a solid definition of either. But with respect to Bruce Eckel's C++ templates vs. Java generics argument, I believe the above solutions all attempt to satisfy his intent. Maybe Bruce will clarify this further in the future. Hope this helped, tm. Dave Benjamin The above post got pretty mangled. You might want to view source to understand the second example with template syntax, since the angle brackets turned the template parameters into HTML tags... I'd fix it if I knew how. =P -Dave <hr><b>2004/07/29 15:13 EST (via web):</b><br> "I'm not quite sure why you see this as a dependency on implementation details." I was talking about the (hypothetical) situation where there is no type constraint (like in Python) and the compiler tries to infer it itself (it doesn't, actually, because it couldn't). As you explained and as I had suspected, this is not the case in OCamL because there _is_ a type constraint. What you have explained above about OCamL is, in my view, en extension of the type concept which allows you to specify "ad hoc" types that have never been formally defined as an interface. But nevertheless, there is a type constraint. It is more flexible than the Java way and IMHO also more confusing but it's not like the Python examples given by Bruce and others where there is no type constraint and the program crashes at runtime. So thanks for clarifying that. But I'm still confused about the 'polymorphic' return type. "Now, "speak" returns whatever type "x.talk" returns.". And you don't know what x might be, so the compiler can't even guess what the return type might be. How, then, can it make compile time checks? Consider that your x is returned by a 'polymorphic' method getRandomObject() (this method decides randomly what kind of object to return). Like speak( getRandomObject()); // nothing is known about the object type returned by getRandomObject(). How would the OCamL compiler handle this? Would it complain? tm How can the compiler verify whether x implements talk(), or whatever your type constraint is? (oops, forget the extra last line) tm P.S. As you have noted, there is some confusion about "latent" and "inferred" typing. Let's forget the "latent". Your OCamL type constraint is nowhere 'latent', it is quite plain, just a little unusual (I think it's fair to call it 'ad hoc'). Dito C++ templates. And in Python, you can just do without typing. Here, it's not latent, it's nonexistent. Type 'inference' is something different, it is a very limited device to save a few keystrokes, and it works only locally. Neither the Python nor the OCamL examples make use of type inference. The reason for the confusion seems to be the fact that Eckel used Python examples without type constraints to explain 'latent' typing. With this in mind, Pixel came to the conclusion (which I have explained above) that 'In the general case, inferring whether objects meet the contract required to support latent typing is impossible at compile time.' tm P.P.S. Let's go back to Eckel's first "latent typing" article (log-0050): ""So for example, in Python you can do this: def speak(anything): anything.talk() Notice that there is no constraint on the type of anything, which is just an identifier. Except that it must be able to perform the operations that speak() asks of it, so that implies an interface, but you never have to explicitly write out that interface – so it's latent."" Note 'there is no constraint on the type of anything' and that ''the operations that speak() asks of it'' are part of the implementation. Does that explain the confusion? tm (bye now) <hr><b>2004/07/29 16:09 EST (via web):</b><br> I just took a look at Bruce's earlier post here: http://mindview.net/WebLog/log-0051 First of all, I don't want this to descend into a tiresome argument, because as we've already ascertained, "latent typing" is not a very clear concept and it seems to be a term that Bruce has conjoured up himself (a Google search for "latent typing" brings you right back to this site). So, rather than going in circles about the term and what Bruce may or may not mean when he uses it, I'd rather focus on the concept he is promoting: by omitting specific type information, you can write functions that are more reusable because they make fewer assumptions about what kinds of things they take and return. In the dynamically-typed world, this is commonly called "duck typing", as in, "if it looks like a duck, and it has a 'quack' method, it's probably a duck." In the statically-typed world, this is usually accomplished with type inferencing (as with OCaml) or macro substitution (as with C++). But the general advantage is that I can write a function that expects any object with a "print" and "close" method, for instance, and as long as they work the way I think they do, I don't have to worry about what classes they derive from or what interfaces they implement. There is an implicit interface here, of course, and that's the point that Bruce tries to make on the above-referenced page. By making interfaces implicit, you make generic programming convenient, and he sees this as an advantage. The return type of the OCaml example is polymorphic, and it is compile-time checked. I guarantee it. It all depends on the context in which "speak" is called. If the result of the call is used in an expression that requires a void/null/unit object, the method of the object you pass in as "x" must return that type. This is made possible by means of OCaml's elaborate type-inferencing system in which the type of every single expression can be determined by the compiler without the need for explicit annotation. In your question about speak(getRandomObject()), you are calling speak in a void (or "unit") context, so it is necessary that "talk" returns void. In OCaml, everything is an expression, so that bit of code can only exist as part of a larger expression. The semicolon means, "evaluate this void-returning expression, and then..." so in this case your code is incomplete. It is like a sentence fragment. However, if you were to write "ignore (speak (getRandomObject ()))", then the return value of speak would be discarded, so it doesn't really matter what type it is. Otherwise, you are obviously trying to do something with it, and whatever you're trying to do is typed as well, so the compiler can statically verify its correctness. The compiler can verify that "x" implements "talk" because you have to define "x" somewhere. Is this what you mean by dependency on implementation? If so, why do you see this sort of thing as problematic? Python is not type-free. It just happens to have a single type for all objects (two, if you count instances of new-style classes). I don't see how you can argue that the OCaml example makes no use of type inference. In fact, it's a perfect example of type inference in action. In my original post, I gave an OCaml statement, and the compiler's response. The compiler's response was the type signature of the function I had just defined. How did it know that? It inferred it! In either the OCaml or Python examples, there is no explicit interface. Whether or not this qualifies as "latent" depends on your definition of "latent"; according to the above link, it seems like this fits Bruce's definition, but I'm not really sure it's worth the energy to debate it; it seems like a moving target to me. =) Dave Benjamin <hr><b>2004/07/29 17:02 EST (via web):</b><br> Dave, you explained earlier that in OCamL, you explicitly say "x must be an object that implements a talk() method". If this is true, then I don't see where inference comes into play. Once again, I don't see anything inferred or latent here, just a different way of expressing a constraint (your words: "yes, there is a constraint ... but it is an open constraint"; an interface, too, is "open", in that it specifies a minimum set of supported operations and leaves you the freedom af supporting any number of additional operations.) In Eckel's Python example, there was nowhere any constraint on the something parameter, and Eckel pointed this out as the big advantage, that's what I cited above in His Own words. Now we are stuck discussing something weird, IMHO. The return type question remains a mystery to me. In the example above, getRandomObject() is a method which returns an object but it's impossible to tell at compile time what type it will be. This implies in my understanding that I cannot operate on the return value (I don't know which operations it supports, except maybe the trivial ones, like toString() in Java). But if I can't operate on it, what's the point of having it passed? That was my question, and I am still eager for light on it. ("The type of every single expression can be determined by the compiler without the need for explicit annotation" - even if it depends on a random number?? That's impressing.) tm <hr><b>2004/07/29 17:03 EST (via web):</b><br> Sorry to both show my ignorance and perhaps ask a different question but... I've never heard of OCaml, but I assume it uses something in the form of Robin Milner's polymorphic type inference, whereby types are inferred at compile time without explicit definition in code. If this is indeed the case, and I'm stretching my mind back to university here so I'm probably wrong :) does this not require OCal to be a functional language? As I remember, it's not possible to do type inference without the stricter requirements that a functional language places on you (I may well be wrong here). The other question to ask is a follow on from this point; it's a great thing polymorphic type inference; however, at university, we were taught ML and around half of the computer science undergraduates at the time failed to understand it at all! So if I'm right in the above, the question is: it may be clever, it may be typechecked at compile time, but is it of any use out in the real world if only really clever people can do it? Keith. <hr><b>2004/07/29 18:39 EST (via web):</b><br> Now I have taken a look at an OCamL tutorial and, sorry, I have to ask another ignorant question. An example of polymorphic type inference given is # let average a b = (a +. b) /. 2.0;; val average : float -> float -> float = <fun> "OCaml worked out all on its own that the function takes two float arguments and returns a float. How did it do this? Firstly it looks at where a and b are used, namely in the expression (a +. b). Now, +. is itself a function which always takes two float arguments, so by simple deduction, a and b must both also have type float." etc. (http://www.merjis.com/developers/ocaml_tutorial/ch1/) I'm afraid I misunderstood what Dave said above. So the constraint is not explicit, it is _in the implementation_ (if it makes any sense to distinguish interface and implementation in that language at all). I admit I couldn't believe that this is true ;-) Now it looks like the compiler _does_ analyze the implementation to check the types involved. In other words, somebody who uses the average function in their own code and expect it to return a float might get into trouble should the implementation be changed in some obscure way. Right, you'll get a compiler warning. But what is maybe worse, as a developer, you have to read the code line by line in order to figure out how to use that function. I have a hard time to see the advantage of this programming style. Would you ever use polymorphic functions like that in a real world project involving more than one developer? And how are things like Lists and Maps handled, doesn't the compiler have to be more restrictive than it would be in Java? tm # let average a b = (a +. b) /. 2.0;; val average : float -> float -> float = <fun> # let average a b = (a +. b) /. 2.0;; val average : float -> float -> float = <fun> How can a deaf software developer access the contents of the talk? If anyone transcribed the talk, please E-mail a copy to w1@zak.co.il <hr><b>2004/07/30 23:04 EST (via web):</b><br> Keith, you are correct in your guess that OCaml uses the Hindley-Milner type inference system. I don't think it requires a functional language; you can use only the imperative flavor of OCaml and still benefit from type inference, for instance. But there is definitely a strong correlation between languages that use the HM system and functional languages. Consider yourself lucky to have been taught ML at all--my college only mentioned ML in passing, during an intro to programming languages course. Yes, it's a bit alien, and tough to learn, but well worth the effort, IMHO. As for ML's viability in the "real world", only time will tell. =) My primary reason for bringing it up (aside from my interest in OCaml and functional programming) was to prove that template-style genericity vs. dynamic typing is a false dilemma. tm, in a dynamically typed language, do you have to read the implementation of a function line-by-line to know how to use it? This doesn't seem the case for the many users of dynamically typed languages, at least not where there is good documentation and intuitive API design. I have done lots of programming with various Python libraries like PIL, PyXML, and mod_python without having to read the source for clues. Since type inferenced code looks rather similar to dynamically typed code, it can't be any worse to program to, can it? Plus, if you've got an interpreter for the language, you can ask the compiler for the type of any function, so you still don't have to look at the implementation. The compiler can do it for you. Anyway, languages with type inference support optional type annotation, and in library design, type annotation of published functions is the norm. As to whether or not there is real world benefit to polymorphic functions, I don't think I'd want to program without them. It's almost impossible to implement abstract containers without them. Lists and Maps are typically more restrictive in a type inferenced langauge because of the rule that every expression must have a "principal type". This means that dynamic casts are pretty much out of the question (unless you explicitly tag your data types) so Java's style of casting in and out of "Object" is not possible. However, Java is moving away from this (since it can result in runtime errors) and toward polymorphic, parameterized data structures. This is what "generics" are all about, and in Java it will be a limited form of what languages like Haskell and ML can already express. By the way, and completely coincidentally, I just read a post on Usenet by Isaac Gouy stating that "latent typing" is the opposite of "manifest typing". In other words, it's another way of saying "implicit typing"; the types of variables are not explicity specified. Pardon the ad hominem argument ;) but Isaac really knows his stuff, so I'm inclined to take his word for it. Dave Benjamin <hr><b>2004/07/31 13:23 EST (via web):</b><br> <br>><i>Consider yourself lucky to have been taught ML </i> I don't think there was much luck involved, Robin Milner was one of the lecturers :) Keith. <hr><b>2004/08/02 11:45 EST (via web):</b><br> I wasn't lectured by Robert Milner - whether this is lucky or not I don't know. I think that this point is valid: if the method signature has to be inferred from its implementation, then I can't rely on the distinction between interface and implementation that is so crucial in Java. Maybe I'm wrong but I suspect that code in a language which doesn't require the developer to precisely specify method signatures/interfaces is easier to screw up. Java (pre 1.5)'s handling of collections is a case in point as it is effectively a regression to runtime type checking. I welcome Java generics for hopefully fixing this problem. tm This, by the way, is exactly the reason why I welcome Java generics: before Java 1.5, as soon as a collection is involved, you have nothing but Object, which is really the worst case because you the type is simply unkn . I want to be able to specify what is in my List, for compile time checking but even more for clarity. I never had a need for fancy stuff like your polymorphic return types, Oh dear, put that away. This editor is such a crap. I'll never use it again. I am unable to download the Presentation? I have no idea how Bruce came to the conclusion that Ruby was similar to Perl. It's certainly no more similar that Python. Probably less so. It's too bad Bruce chose Python over Ruby as his scripting language of choice. Now he gets to deal with creeping featuritis and workarounds like PEP 318. Ruby's OO and dynamicity much better IMHO, plus I much prefer Ruby's syntax. I have watched the "Thinking About Computing" presentation, you mentioned the Eclipse RCP, there plugin engine is nice. I am working on an open source project that's creates a plugin engine based on some ideas of the Eclipse one. Are engine is indepent of UI toolkit, we build a Swing UI frawork around it. We are working on our M1 of the engine (pre-release is availible on http://sourceforge.net/projects/genpluginengine). It going to support dynamic loading of plugins (load, unload and reload) so you don't have to restart your appliction. In our UI framework we have a plugin that handles the creating of menu and menu items and actions, a plugin who automaticly loads plugins that are added to the application while the application is running without restart. Our plugin engine can handle to types of plugins, does that are in a directory and in a plugin archive. The plugin archives can contain embeded jar/zip files, we have a classloader that can load resources and class files from the embeded jar/zip files. Different xml parsers can be used to parse the configuration file of a plugins, the smalest version of the engine which use a parser from the JSDK is just 25kb in size. Are engine may be small but is very capable. You also mentioned in your presentation about XAML but did you heard of XUL? You can create rich cross-platform web application with it, its developed by the Mozilla foundation and use in there applications like Mozilla FireFox. Some information about XUL can be found at http://www.xulplanet.com/. You also told that c++ is getting a GC, they need more (like runtime compilation) to get better performance. <hr><b>2004/08/15 04:23 EST (via web):</b><br> Ruby is similar to Perl! Matz admits it himself; he cites Perl, Python, and Smalltalk as his main influences, if I recall correctly. Among the similarities are Perl-style global punctuation variables (although these aren't highly regarded), symbols indicating variable types (though the semantics are different), and regular expression literals, which are about as Perlish as it gets. This isn't necessarily good or bad. Perl has its good points. But I think Ruby is much more similar to Python in terms of its object model. Python's OO implementation is much closer to Ruby's than Perl's. From the Ruby perspective, it's really just Smalltalk with "popular syntax". That's how I see it, anyway. =) What are the current, practical applications of XUL? It seems like I can use it to write Mozilla extensions. How about standalone apps? Is there an XUL player or plugin available for other browsers? There seem to be a lot of solutions to the problem of creating cross-platform remote applications with rich user interfaces, but they all have their caveats. Flash is everywhere, but it's not a very dynamic programming environment, and doesn't always play well with non-Flash parts of web sites. XUL seems like it mostly pertains to Mozilla, and XAML is decidedly Microsoft-based. It's hard to decide which tool to use, since each one requires you to narrow your audience somewhat. I thought FLEX would be the answer, but I have to agree with Bruce there... too expensive, too "big business" oriented... SWF can do most of what I'm interested in, and it seems to be everywhere. What it really needs is some way of doing dynamic code compilation and evaluation. We can go into all sorts of directions from there. Barring that, we need better languages that compile to SWF. ActionScript 2 is a disappointment (talk about confusing type terminology--they call it "statically weakly typed"). I'd like to see something like Python or Ruby compile to SWF on-the-fly. Dave Benjamin Concerning all the comments of 'latent type' verses 'static type' checking. Why should we believe that either one is the correct object for our "technology fetish"? WHy not instead partition the checking into 1) that which is best done at compile time and 2) that which is best done at runtime? This is similar (but obviously not the same) to one of the things accomplished by templates in C++: the old stricter-than-C static type checking was realized as too restrictive, so a "back-door" was created, namely, templates. Of course templates do more than this, too. But the interesting thing is that it does not _undo_ static type checking, but it loosens the restriction precisely where it does the most good to do so. Matthew Johnson
Optional change note
:
For editing help, see
HelpPage
.