I’m in a similar boat; also starting with Python. Python is intuitive and flexible, which makes it easy to learn but also, in a sense easy to avoid understating how a language actually works. In addition I’m now learning Java and OCaml.
Java isn’t a pretty language but it’s widely used and a relatively easy transition from Python. But it, I find, makes the philosophy behind object oriented programing much more explicit; forcing the developer to create objects from scratch even to accomplish basic tasks.
OCaml is useful because of the level of discipline it imposes on the programer, e.g. not being able to mix an integer with a floating point, or even—strictly speaking—being able to convert one to another. It forces one to get it right the first time, contra Python’s more anything goes, fix it in debugging approach. It also has features like lazy evaluation and function programing, not supported at all in the case of the former (as far as I know) and as a kind of add on in the case of the latter, by Python. Even if you never need or want these features experience with them goes some way to really understating what programs are fundamentally.
Java is primarily useful for huge things. Since it makes so many things explicit, you can orient yourself very quickly in a project. If you see a symbol, you don’t need to pull out a special tool (like cscope for C) to tell where it was defined—the code tells you. Yes, it is possible to write spaghetti Java, but it’s easy not to.
Also, if you have something that will be on for a long time and need it to eventually act with compiled speed (e.g. a webapp), java with the JIT is soon as fast as an always-compiled language.
The inability to pass functions as arguments without creating a class for them is one of the annoying parts. Maybe some syntactic sugar will be (or recently has been?) added.
The inability to pass functions as arguments without creating a class for them is one of the annoying parts. Maybe some syntactic sugar will be (or recently has been?) added.
Java 8 (currently scheduled for March 2014) is adding proper lambdas.
There are other JVM-based languages that do have more easily accessible functions, but most of them come at a performance cost—the JVM really isn’t very flexible.
To the best of my knowledge, no-one has tried to design a language that gets the best possible performance from the JVM while still throwing away C-style syntax and unnecessary limitations.
What I’m talking about here would still compile to Java bytecode. It would just be some syntactic sugar to easily wrap static functions in anonymous classes.
The only thing that really bugs me is the inability to use variables declared in a try block in an ensuing catch or finally block. That would let you scope things much better.
You can do polymorphism with generic types, and that’s been around for a while.
Like,
List listOfThings = new ArrayList();
listOfThings.add(new Thing());
Thing t = listOfThings.get(0);
Is this not what you’re talking about? Generics need no runtime support, but they do enable a lot of compile-time checks.
Generics certainly don’t do parametric polymorphism or algebraic data types. Of course anyone can write a Pair or Triple class with trivial get and set methods, but that looks (and acts) silly.
Ooh, another thing I’d love is to have there be a Bracketable interface that lets you use brackets to call the class’s get and set methods. Then you could access Lists and even Maps with array syntax. It’d be sweet.
At some point you should also learn Prolog and Haskell to have a well-rounded education.
I’m not sure knowing Prolog is actually useful, and I speak as someone who has been teaching Prolog as part of an undergraduate AI course for the last few years, and who learned it way back when Marseilles Prolog didn’t even support negative numbers and I had to write my own code just to do proper arithmetic. (I’m not responsible for the course design, I’m just one of the few people in the department who knows Prolog.)
Functional languages, imperative languages, object-oriented languages, compiled languages, interpreted languages: yes. Even some acquaintance with assembler and the techniques that are used to execute all the other languages, just so you know what the machine is really doing. But Prolog remains a tiny, specialised niche, and I’m inclined to agree with what Paul Graham says of it: it’s a great language for writing append, but after that it’s all downhill.
I mean learning Prolog in the way it would be taught in a “Programming Languages” course, not as an attempt at facilitating AI. Two angles are important here: (1) programming paradigm features: learning the concept of late-bound / dataflow / “logical” variables. http://en.wikipedia.org/wiki/Oz_(programming_language) is an OK substitute. (2) logic, which is also something to be taught in a “Programming Languages” context, not (only) in AI context. With Prolog, this means learning about SLD-resolution and perhaps making some broader forays from there. But one could also explore connections between functional programming and intuitionistic logics.
I’m in a similar boat; also starting with Python. Python is intuitive and flexible, which makes it easy to learn but also, in a sense easy to avoid understating how a language actually works. In addition I’m now learning Java and OCaml.
Java isn’t a pretty language but it’s widely used and a relatively easy transition from Python. But it, I find, makes the philosophy behind object oriented programing much more explicit; forcing the developer to create objects from scratch even to accomplish basic tasks.
OCaml is useful because of the level of discipline it imposes on the programer, e.g. not being able to mix an integer with a floating point, or even—strictly speaking—being able to convert one to another. It forces one to get it right the first time, contra Python’s more anything goes, fix it in debugging approach. It also has features like lazy evaluation and function programing, not supported at all in the case of the former (as far as I know) and as a kind of add on in the case of the latter, by Python. Even if you never need or want these features experience with them goes some way to really understating what programs are fundamentally.
Java is primarily useful for huge things. Since it makes so many things explicit, you can orient yourself very quickly in a project. If you see a symbol, you don’t need to pull out a special tool (like cscope for C) to tell where it was defined—the code tells you. Yes, it is possible to write spaghetti Java, but it’s easy not to.
Also, if you have something that will be on for a long time and need it to eventually act with compiled speed (e.g. a webapp), java with the JIT is soon as fast as an always-compiled language.
The inability to pass functions as arguments without creating a class for them is one of the annoying parts. Maybe some syntactic sugar will be (or recently has been?) added.
Java 8 (currently scheduled for March 2014) is adding proper lambdas.
There are other JVM-based languages that do have more easily accessible functions, but most of them come at a performance cost—the JVM really isn’t very flexible.
To the best of my knowledge, no-one has tried to design a language that gets the best possible performance from the JVM while still throwing away C-style syntax and unnecessary limitations.
What I’m talking about here would still compile to Java bytecode. It would just be some syntactic sugar to easily wrap static functions in anonymous classes.
Sure, that’s what I was talking about.
Though Java syntax really isn’t that great, and if you’re changing it at all, there’s a lot more low-hanging fruit than just functions.
The only thing that really bugs me is the inability to use variables declared in a try block in an ensuing catch or finally block. That would let you scope things much better.
What are you thinking of?
Lack of multi-parameter polymorphism, lack of return-type polymorphism, lack of algebraic data types, lack of parametric polymorphism, etc.
Okay, essentially I want Java to be Haskell. That’s an impossibility, but most of the type-level stuff needs no runtime support whatsoever.
You can do polymorphism with generic types, and that’s been around for a while.
Like,
List listOfThings = new ArrayList(); listOfThings.add(new Thing()); Thing t = listOfThings.get(0);
Is this not what you’re talking about? Generics need no runtime support, but they do enable a lot of compile-time checks.
Generics certainly don’t do parametric polymorphism or algebraic data types. Of course anyone can write a Pair or Triple class with trivial get and set methods, but that looks (and acts) silly.
Ooh, another thing I’d love is to have there be a Bracketable interface that lets you use brackets to call the class’s get and set methods. Then you could access Lists and even Maps with array syntax. It’d be sweet.
All three of the things I asked for in this chain now exist as part of Java -
-- Lambdas—code snippets you can pass (without even declaring them as functions, even!),
-- brackets for accessing Lists and Maps, and
-- a way to declare variables for both a try and its associated catch and finally blocks.
I’m kinda floored.
OCaml is my favorite language. At some point you should also learn Prolog and Haskell to have a well-rounded education.
I’m not sure knowing Prolog is actually useful, and I speak as someone who has been teaching Prolog as part of an undergraduate AI course for the last few years, and who learned it way back when Marseilles Prolog didn’t even support negative numbers and I had to write my own code just to do proper arithmetic. (I’m not responsible for the course design, I’m just one of the few people in the department who knows Prolog.)
Functional languages, imperative languages, object-oriented languages, compiled languages, interpreted languages: yes. Even some acquaintance with assembler and the techniques that are used to execute all the other languages, just so you know what the machine is really doing. But Prolog remains a tiny, specialised niche, and I’m inclined to agree with what Paul Graham says of it: it’s a great language for writing append, but after that it’s all downhill.
I mean learning Prolog in the way it would be taught in a “Programming Languages” course, not as an attempt at facilitating AI. Two angles are important here: (1) programming paradigm features: learning the concept of late-bound / dataflow / “logical” variables. http://en.wikipedia.org/wiki/Oz_(programming_language) is an OK substitute. (2) logic, which is also something to be taught in a “Programming Languages” context, not (only) in AI context. With Prolog, this means learning about SLD-resolution and perhaps making some broader forays from there. But one could also explore connections between functional programming and intuitionistic logics.