Showing posts with label Ruby. Show all posts
Showing posts with label Ruby. Show all posts

Wednesday, December 7, 2011

Good and not so good reasons to learn Java (or any other language) [part 2.5]

So this is the third part after the not so good reasons to learn Java and the other good reasons to do it.


Java could be fun


Really. There is some stuff that is really nicely done. I like Akka, for example. And I find the idea of hacking with assertion really funny. It is a totally different approach to meta-programming that I really liked. I also like Antlr... after that every other library for imperative/oo-languages to build parsers seemed primitive.

There is some nice stuff in the Python world as well (and yeah, in Lisp you have Lisp and Haskell has wonderful stuff to). But I can tell: implement a language in Java and in C++. In Java you will be finished so much earlier... of course, other languages are faster too. But your team may not include other Haskell hackers.

Libraries, libraries, libraries

In Java there is a library for everything. Quite often, they are very well done, even if somewhat over-engineered. Probably my idea of over-engineering is a bit extreme (it comes from having seen lots of lean languages). But really, they are robust and well tested.

Moreover, Java is usually efficient enough to be a decent contendant for more demanding tasks.. Maybe C/C++ can be avoided for your application (and Java libraries are usually easier to use than C++ ones).

Java as an intermediate level platform

Say you are interested in language design. As far as I can see, you have few choices.

  • Write your own runtime, vm, etc. That was the "old" approach (Python, Ruby)
  • Implement your language on the top of a Lisp[0] or Prolog[1] interpreter
  • Use LLVM
  • Use JVM
  • Use CLR/Mono
I would rule out the latter, because I don't do any windows. Between LLVM and JVM as far as I understand it may depend on the language. JVM has a few quirks (who said lack of TCO?), but has plenty of available documentation, real world examples (Scala & Clojure), a large number of developers working for the well-being of the plarform, and a huge amount of libraries, libraries, libraries you may want to use.

LLVM is probably going to be faster, though. And has lots of optimizations and stuff for static languages. In any case, to make an informed choice, you need to know Java

Tools (IDEs, Maven, Ant)

IDEs are the bless and the curse of Java. After having used for sometime IntelliJ I really feel that the amount of functionality that IDEs for other languages offer is puny. The possible exception is Emacs for Lisps.

The funny thing is that I'm not an IDE gui. However, really, when you do refactoring (even simple stuff like moving functions and files around) it is an invaluable time-saver. I miss vim as a text manipulating programming language, but still... for Java IDEs are almost necessary. And not only bridge part of the gap with other languages, they have lots of useful stuff.

Regarding Maven... well, I just like it. I also like the fact that I'm able to build IntelliJ projects from Maven scripts is wonderful. And also Ant is a very good tool (although rather over-engineered). My humble opinion is that Ant is far easier to use than the whole autotools company. This may also have something to do with the fact that the whole Java deploy process is easier.

In any case, the point here is not how cool is Maven. Developers from other platform may want to know what is boiling up in Java-land. Sometimes we have sub-par tools and we do not even know it. Of course quite often Java tools fix "Java problems" that are different from the ones we have in other languages. Sometimes not.

E.g., the design of Maven could inspire similar tools for the other platform. Both for its strengths and for its weaknesses (to avoid them, of course).

Learn "classical" threads

Ah, this is weak. However, other languages have a "threading" module that is heavily inspired by the way Java does threading. I don't particularly like it, but being familiar with it may be a very good idea. As far as I can tell, is also what most people have in mind when thinking about threading. Who am I to say that they are wrong? I can just tell them there is better stuff.

And yes, pthreads are even more a PITA.

Find Java in other languages. Sometimes.

This is basically the extended version of the older argument. Java is hugely popular. Many "new" things are created in Javaland, and then are ported to other platforms. Or perhaps are not created but became first popular inside the Java community.

For example, xUnit libraries are available everywhere, but I think that most people first started working with it in Java. Some of the authors of the original Smalltalk library actively work on JUnit, etc etc etc.


Conclusion


I do not think that Java is particularly good. Not particularly bad, either. It is not the kind of enlightening language Scheme is. It is not easy to use and predictable like Python. However, its popularity may make it unwise not to learn it. Especially for communication reasons:

  • Books
  • Other developers (talking about OOP, libraries)
  • New ideas brewed in Javaland

wow... that's it. ;)

---
[0] Scheme, Clojure, Common Lisp...
[1] Erlang was created this way, even if now it has its own (wonderful) runtime

Saturday, December 3, 2011

Good and not so good reasons to learn Java (or any other language)[part 2]

So this is basically the second part of "Good and not so good reasons to learn Java".

And here I will discuss the good reasons to learn Java. Some of them...
I decided to split this in two posts. The next one will be published in a few days.

If you know me a bit, you probably know that I do not like Java particularly. In fact I found out that the essential problem is with Java being presented as something modern or "superior". It is not. However, it did something very good in the software environment (a part from electing over-engineering as a form of art): many technology that were outside the mainstream and was dubbed slow (garbage collector) are now widely accepted and that is partly because of Java. This is no reason to learn Java, though.

Moreover, my opinion is that Java is not a good first language. It is not a good second language either. However, after learning a high level language like Python or Ruby, a couple of functional languages (maybe Clojure and Haskell or Scheme and Scala) and something lower level, such as C, well... learning Java it could be a very good idea.

Lots of interesting stuff runs on the JVM

Yes... I'm talking about Clojure and Scala. And perhaps JRuby too. Sometimes understanding the underlying platform helps understanding some design choices. Moreover, there is stuff (e.g., in Clojure) that has not yet a fully clojurized variant and we have to use Java stuff.

Knowing Java is a plus, of course.

Lots of interesting books deal with Java

I'm not talking here about the wonderful Effective Java or Java Puzzles. They are great Java books, of course. And some suggestions may also apply to other languages. Still, if you are not interested into Java, you may miss them.

No, I'm talking about other great books...


Some of them are not entirely in Java and some have non-Java alternatives. Still reading Java is a huge plus in reading those books. I believe part of the reason is that:

Java is like a common-denominator object oriented language


Forget the Java platform. Consider just the language. Essentially Java is really a common-denominator of other object oriented language. Other languages typically offer more. Are more dynamic, offer more powerful type-systems, more expressive constructs.

Just thing about the OOP building blocks. Here we are talking about the mis-interpreted OOP as a matter of types vs. a matter of messages. That is what most people think about when referring to OOP. Unfortunately, as I said.

Java has those. But does not have much more. If you want to design OO stuff, Java gives you the building block, but does not stand above offering higher level construct. Think about Python or Ruby or Lisp... their OO facilities are so superior (plus they typically offer stuff outside the OOP model -- well, Lisp is so much more than an OO language...) that you are probably going to design stuff differently. Probably you are not going to over-engineer stuff.

Modifications are cheap. Abstractions are easy. And of course you can go outside the OO model when it makes sense.

On the other hand in Java you cannot. You can just get back at a procedural level, which is clearly inferior. The best thing you can do in Java is try to be as OO as possible: other choices usually do not pay.

As a consequence:

  1. Java is a great language to expose those "ill-conceived OOP" concepts that are used in every other language where ill-conceived OOP techniques are used.
  2. Java is a great language to truly learn to program like an object-oriented zealot

Please notice that I consider the latter a very good thing. It is a very good exercise that lets you understand the merits and the drawbacks of the paradigm. Probably when you think that something really sucks in Java, you hit a limit of OOP in a static language. Other languages may make that easier, but the wall is still there.

Java is good to learn "good OOP" too

Yes! As I already said there is a lot of smart people working with Java. They have already discovered and taught how to do "good" OOP in Java. You should learn it too.

Then, when using a different language things could only be easier. Some of the techniques you learned may be useless, because the language offers better abstractions. Still you will have a pretty clear understanding of what such abstractions are doing and perhaps you may develop a feeling for when not to use them.

As a matter of fact, too much magic is bad, even if it may seem cool. While sticking too much to simple things may actually complicate the design in the long run (meta-programming leads to code that you do not write and that is the only kind of code that needs no debugging or testing or maintenance, as it does not exist), too much magic has the same effect at the opposite position of the spectrum.

Avoid writing Java in other languages

If you know Java, at a certain point you may discover you would be writing much the same code if you were using Java. If the language you are using is C++, you probably have done something wise: chosen a restricted subset of C++ and used that one (than we may argue if you actually left out good stuff).

However, if you are using Python or Ruby, or, worse, Clojure, then you are writing awful code. $x code is not meant to be structured like Java. If it does, you are not using the language well. This is basically a side effect of "Java is like a common-denominator object oriented language".








Saturday, November 26, 2011

Good and not so good reasons to learn Java (or any other language)

The first thing to consider is there is really not such a thing like a reason not to learn a programming language. Or better, there is only one reason: lack of time. Learning a language is a tricky business[0]. Learning to use a whole platform is way trickier.

Please notice that some of the reasons presented here are general enough to be applied to any programming language (especially the bad reasons to learn a language). Others are specific of Java (especially the reasons to learn it).

Also keep in mind that the good reasons to learn Java will be presented in another post because this one is becoming far to long to be readable in the few minutes I feel entitled to ask you, dear reader. So believe me... you probably should learn Java. Still, not for the reasons I list here.

Not so good reasons to learn Java

It is widespread

You may be lead to think that since Java is a very widespread language, it is easier to find jobs if you know it. In the case of Java there is the question that I am convinced that it is not a bad thing to know Java and that can have pleasant effect on finding jobs (more on that later), still I would not consider it a good reason to learn Java.

Learning a widespread language means more jobs and more applicants. What really matters is the ratio between jobs demand and offer. And usually for very widespread languages it is not always very high. Skilled, experienced and "famous" developers do not care much. The others should.


It is object oriented

This and the variant "it is more object oriented" are clearly wrong reasons. There is plenty of good object oriented languages. And it is rather hard to decide which is more object oriented (lacking function looks more like a wrong design decision than a clue of being more object oriented).

Besides, I'm not even sure that being more object oriented is good (or bad for what matters). Well... not sure that being object oriented is inherently good either. Maybe in ten years the dominant paradigm will be another. Maybe in two. Three years ago "functional programming" was murmured in closed circles and outsiders trembled in fear at its very sound.

No, joking. Most people thought that "functional" meant having functions (and possibly no objects) and thought about C or Pascal. They did not know it was about not having crappy functions. Yeah, more than that, of course, but that's a start.

It is a good functional language

Just checking if you were reading carefully...
That is a bad reason because it is not true!

It is fast/slow

Oh, come on! Java implementations are decently fast, faster than most other language implementations out there and usually slower than implementations of languages such as C, C++, Fortran. Still, for some specific things it may be nearly as fast or faster. Sometimes it is not only CPU efficiency that matters.

It is good for concurrency

The "classic" Java threading model sucks. It's old. Nowadays other ways of doing concurrency are better (more efficient, easier to use).

Such more efficient easier to use methods are built-in in languages such as Clojure (or Scala, or Erlang). Still, Java is probably the most supported platform in the world. Such concurrency models are not inside the language, but you may have them using libraries.

Sometimes this is a real PITA (language support is a great thing, because the syntax is closer to the semantics).

Moreover having the "older" concurrency model visible may be a problem with the newer stuff. And some other libraries and frameworks may just assume you want to do things the old way.

It is good for the web

Ok... most people do not even know how widespread is Java on the web. In fact, it is. But is it really good? I do not really think so. There is lots of good stuff in Java world for the web, of course. The point is that there is also for other platforms. Here Rails and Django spring to mind.

Moreover, there is loads of extremely cool stuff coming from the functional world. Erlang and Haskell have some terrific platforms. Scala and Clojure also have some extremely interesting stuff and can leverage mature Java stuff but make it really easier to use.

Grails (web framwork) may seem on the same wavelength, still I think there is a very important difference. First, I don't like Groovy at all. In fact Groovy very author says that he would not have created it if he knew Scala. And of course since I do not like Groovy, I do not see why I should be using Grails, which, as far as I know, does not offer killer features over Rails or Django.

Scala and Clojure are different. They are not just "easier" than Java. They teach a different way of thinking and approaching development. And of couse, they are great for the web also.

I already know it a bit

This is quite an interesting point. Why, if you know a language a little, shouldn't you learn it well? This essentially makes it clear the difference between a not so good reason to learn something and a reason not to learn it.

The point is simple: if you are interested in learning Java (for the good reasons), do it. But from knowing a language "a bit" and knowing it "well" there is quite the same distance that from not knowing it and knowing it well. So don't do it because you think your prior experience may be extremely relevant.

There are languages which are just easier to master (where easier means that to learn them from scratch it takes less time that to become as proficient in Java as you would learning those languages -- yeah, Python, Ruby, [1]...)

Besides, I feel that the second step in Java is rather hard. I think that Java is very easy to learn for experienced developers (it is not a joke). The very first step in Java is relatively easy (a part from lots of useless crap like having to declare a class to put there a static main method and overly complicated streams). The step just after that, the one that takes you from writing elementary useless programs to writing elementary useful programs is quite harder, since lots of useful stuff in Java requires to understand OO principles quite well to be used without too many surprises.

So, you may have learnt Java at the college. Still, if you to hack something and "grow" there are languages that let you do it faster (Python or Ruby).

I have to

This is the worse possible reason because I don't see the spark in it. You have to. You probably are an experienced developers that got bored to death reading this post, you did not know Java and you have to learn it. Maybe your boss wants you to do some Java.

I'm sorry for you. Java is not easy to learn (especially to learn it at the point you can work with it). Mostly because everybody has been doing Java in the last fifteen years. Smart people and dumb people.

As a consequence there are truly spectacular pieces of software it is a pleasure to work with and worthless pieces of over-engineered crap. I truly hope that you are going to work with the great stuff.

Still I consider a "bad reason" to learn a language, because you are probably not going to enjoy the learning process. If you were, you would have used a different sentece... like "I want to".
And perhaps the thing would have been "My boss gives me the opportunity to increase my professional assets learning this new technology, Java".

It was easier to download/find a book/my cousin knows it.

One of the most popular reasons people pick up a language is because they find it installed on their system. That is not usually the case for Java, in the sense that usually the JDK is not installed, even if the VM is. Variants of this argument are a friend proficient in the language or, more frequently, availability of books at the local bookstores. This kind of arguments usually apply for complete programming beginners or people who had prior experience that has not been refreshed for years (e.g., old Basic programmers).

It is true that it is easy to find manuals for Java. The point is that not every manual is a good starting point. Specifically, this kind of user really needs a manual targeted at a true beginner. Unfortunately, that is the category of books where more craps piles. First beginners usually do not really understand if the manual they are using is crap.

If their learning process is too slow (supposed that they see it) they usually blame: (i) programming in general, (ii) the language or, worse (iii) themselves. Well, the language may have its faults (especially in the case of Java, still C++ is worse for a beginner), but it is important to understand that the culprit is usually the manual.

The funny thing is that the people who know how to tell apart a good manual from a bad one are usually the ones that do not really need an introductory book, are probably not going to buy it and more often than not are not enquired about a good manual. So unless their cousin is actually a skilled programmer, beginners are really risking buying a bad manual. And please, notice that even skilled programmers are susceptible to a similar argument: if you are interested in a new language and you read a terrible manual you may build a wrong opinion on the language (and perhaps you are not interested in spending another 40 gold coins to convince you that the language is really bad).

So please: read reviews on Amazon (or similar site -- notice that I'm not going to suggest to buy from Amazon, even if I often do and I am an associate -- here I'm just saying that the amount of reviews on books on Amazon -- com -- is usually large enough to make an idea). Find people that are experts and have teaching experience: their reviews are probably the one to base the judgment upon. Then buy the book from whatever source you want.

So do not buy a Java book because you can find books on Java and not on Clojure[2]/Python/Ruby/Whatever[3]. Choose the language (this is hard), choose the book (this is easier), buy, read it, study it, code code code.


---
  1. I kind of found out that for people really convinced that learning a language is easy one or more of the following apply:
    1. have an unmotivatedly high opinion of their knowledge of the languages they claim to have learned
    2. have a very inclusive definition of "learning" a language (e.g., writing hello world in it)
    3. only know and learn very similar languages (really, if you know C++ it's gonna be relatively easy to pick up Java, if you know Scheme probably Clojure is not going to be a big deal, etc.)
    4. and tend to write "blurb" in every language they know (so for example they write Python as if it was C++ -- and usually are very surprised when things go badly)
    Of course there is also a lucky minority for which learning languages is very easy.
  2. It is funny that I am suggesting to learn only "object oriented dynamic" languages such as Python or Ruby. I understand that many advocates of functional programming may disagree. But I somewhat think that while some kind of people greatly benefit from learning a functional language as the first language they truly master, many others are just not fit for functional programming because it is too abstract and working imperatively may be easier for them. As a consequence, languages such as Python or Ruby may naturally lead you towards functional programming if it is the kind of stuff you like, but are still usable if you are not that kind of person. I have seen things...
    And yes... if you are the kind of person that likes functional programming, you will get into functional programming sooner or later. This is just a bit later. 
  3. Notice Clojure here...
  4. Whatever is not a language. Still, it would be a great name for a language. Maybe not.

Saturday, September 3, 2011

Too many cool languages (Python, Clojure, ...)

There is plenty of languages I like. I'm naming just a bunch of them here... so a non exclusive list may be:

  1. Python
  2. Common Lisp
  3. Scheme
  4. Clojure
  5. Erlang
  6. Haskell
  7. Prolog
  8. Ruby

The list is quite incomplete... for example I left out languages from the ML family. I do not have anything against them, I just think Haskell nowadays is way cooler (cooler != better) and also the Haskell platform is a definitive advantage. I did not mention languages such as Io, because although I'd really like to do something with it, it just does do not feel enough motivation to try and do it in Io instead than in one of the languages above.

Same thing for Javascript. It's not that I do not like it... it is just that if I can, I would rather use one of the languages I mentioned (which at least in case of client side JS most of the times is a no go). I also left out things like CoffeeScript and a whole lot of languages that did not even jump to my mind right now.

The list is quite representative of my tastes in programming languages. All the languages are very high level languages (I enjoy plain old C, but I tend to use it to extend the above languages and/or for problems which really need C points of strength). Most of them are declarative languages, almost every one of them has a strong functional flavor (basically just Prolog hasn't, the others are either functional languages or received a strong influence from functional programming).

Some of the languages are better for certain tasks, because they are built for them or have widely tested libraries/frameworks. And this somewhat makes it a difficult choice which one to chose. For example, every time a network service has to be written, I consider Python (Twisted/Stackless), Erlang and recently Clojure. If the system has to be highly concurrent, probably Erlang has an edge, but also Haskell (with STM and lightweight threads) and Scheme (Gambit/Termite) are strong contenders.

This is essentially about personal projects. In fact, for "serious" stuff, I am still using Python or Java (and C/C++ if more muscle is needed). This is basically because I have far more experience with those technologies. Clojure is probably a viable choice as well, as I can easily interact with Java and I have been using that quite intensively in the past two years (I also used it to extend one of the "serious" projects, though I had to remove it because I had other experimental components and it was tiresome to find out whether bugs were due to the other components or my relative inexperience with clojure). Besides, I have still to find winning debugging strategies for clojure: probably I'm missing something obvious here. I'm also trying to increase my expertise with Erlang.

These are some random thought about developing in the environments.

Editing Tools

The first issue, is to find the right tools. It is not exactly easy to discover the right tools to develop in non mainstream languages. For example, with Java any major IDE is a good enough tool. For Python, both PyCharm and WingIDE are excellent and easy to use tools. Moreover, vim is an excellent tool with only minor tweaking. Oddly enough, I'm still struggling to find a good setup for Emacs.

On the contrary, Emacs is quite easily one of the best environments for Scheme/Common Lisp/Clojure (thanks to slime), Haskell, Erlang and Prolog (thanks to the improved modes). Still, after years of switching back and forth from Emacs to vim and vice versa, I think I'm more comfortable with vim. Unfortunately, it is not always the case that customizing vim for these languages is as easy as it is with Emacs. For example, I found an easy to use Erlang plugin, but I have still to try using advanced plugins for Haskell and Clojure (I know the plugins, still I did not finish the setup). For Clojure it's just easier to fire LaClojure or Emacs+Slime. For Haskell, I'm not serious enough to know my own needs. I wrote software for my bachelor's in Prolog with vim, and I have to say that Emacs is quite superior (especially considering Sicstus custom mode).

Back in the day I used TextMate for Ruby. Right now I guess I'd probably go with RubyMine or vim.

Platform

Now this is a serious point. Many of my "difficulties" with Scheme lie here: chose one interpreter/compiler with libraries to do most things I want to do and some tool to ease the installation of other libraries (I should probably just stick with Racket). For example with Python it is easy: pick the default CPython interpreter, use pip/easy_install for additional libraties.

Common Lisp is also going well (SBCL + Quicklisp here). I was pleasantly surprised by Haskell: the Haskell platform is wonderful. Some years ago it was not completely clear which interpreter to use and external tools (like Haskell) were not completely immediate. Now with the Haskell platform you just have everything under control.

About clojure, I feel rather satisfied. For project oriented stuff there is leiningen, which works fine. My main objection is that most of the time I'm not *starting* with project oriented stuff... which is something which so much remembers me of the Java world, where first you start a project (as opposed to unix, where you just start with a file). Luckily enough in the clojure community there are also guys like me, and so there is cljr which just fills the area of "before" something becomes a project.

Cljr is very nice with emacs/swank/slime. Unfortunately I've not yet found a way to make it interact with vim.

Erlang already comes bundled with an interesting platform and rebar does lots of nice stuff too. Erlang/OTP tends to be a bit too project oriented but it quite makes sense. Basically all of the times you are setting up systems with many processes and all and it just makes sense to do it that way.

Prolog is essentially a complete mess. I advise just using SWI-Prolog and forget the rest even exists, unless you need some of the advanced stuff Sicstus offers. In this case you pay and enjoy.

Thursday, July 21, 2011

Is state really bad?

Prologue

Actually this post was being written in March, when some facts referred in the body of the article actually happened. I am resuming the post today, after months of extensive (and rather unbloggable) work.

Intro

Stateful programming is somewhat the default strategy in the industry nowadays and it has been in the last 60 years. If we consider the 10 more widespread languages in the tiobe index (a statistic is worth another), they are all imperative languages strongly based on stateful programming. This month Lisp is has enormously improved (Land of Lisp anyone?), but even if we would consider Common Lisp and Scheme together, it would not go in the first 10 positions (even if just for a few points).

The Haskell case

In fact, in the last years we have witness an increase of interest in functional languages. As far as I remember, about 5 years ago there was a lot of hype about Haskell (which was in its 30's or something like that). It was related, as far as I remember, in a famous user-friendly linux distro having written some tools in Haskell and in the Darcs project. Darcs has almost disappeared with Git (Perl+C) and Mercurial/Bazaar (Python, Python+C) sharing the market of distributed versioning tools.

The case is rather interesting: Darcs was built with a very strong "theory" behind, the algebra of patches. The problem is that the merge process is still exponential in the worse case and that it is rather buggy. It is interesting that the software is both slow and bug ridden. It is tempting to infer something about Haskell, at least to counter the hypothesis that pure functional programming makes it relatively easy to write bug-free programs. Perhaps this should be taken into account the next time someone looks down on setf. Well, I do like Haskell, just not as much as I love Lisp.

The last thing I would like to mention is that I like the idea to insulate imperative code from functional/algorithmic code (but this is something I suggest with every language). However being forced to do that is not necessarily a good idea. In fact, it makes Haskell quite harder to pick up and has the paradoxical effect that if you are a developer good enough to code in Haskell, you probably already know how to separate side-effected code from side-effect free code. Besides, although I like purity (to some extent), I'm not sure whether state monads should be considered stateless. I mean, a state monad implements state in a nice functional construct, mathematically sound and pure. In fact they are almost seen as an executable transaltion of the declarative semantics of a stateful program. Consequently, I'm not sure whether frequent use of state monads is really an improvement over carefully used stateful programming.

In other words, although I admit my limited experience of Haskell in real world projects, I believe that if we think functionally the code is going to be clear (but it will be as clear in Haskell as in Lisp). On the other hand, if we think in a heavily stateful way, our code may be less clear in Lisp and quite messy in Haskell, where we would implement our (wrong) thinking having state monads pop out everywhere. Feel free to correct me, possibly with real experience and examples.

Erlang and Clojure

Erlang is different from Haskell in that functional stateless programming is required for practical purposes. In order to allow shared-nothing process based architecture (and the actor model), state is essentially banned. Of course, there are solutions which bring back state (ETS, DTS, plus various libraries such as mnesia). It is worth noting that this kind of state is generally different from usual imperative state.

In imperative languages everything is stateful by default. On the other hand, in this case, we basically have only "db like" solutions. This does not encourage real stateful programming, and in fact, usual Erlang programs are pretty much state free. The essential different is that they are not side-effect free.

Being state free and side effect free are two very different things. Having no side effects is pure functional programming. And is extremely hard to do. In fact, it would not even made sense in a programming language built around the idea of passing messages between processes. If you send a message, you are not side-effect free anymore.

Somewhat in the same sense, Clojure is stateless but not side effect free. Most clojure coding is performed without explicit state change and there are a few explicit ways to deal with state. This is done in transactional way, so that essentially state change is allowed if explicitly required. State change should not mingled with stuff which has effect outside the clojure process. You can "unset" a variable and recover the old value, but you cannot unsend a message.

At the moment I feel that I can easily tolerate (and like) the kind of state change insulation provided by clojure and the pragmatics of avoiding side-effected stuff for as long as possible typical of all functional languages. On the other hand, I find really hard to accept absolute stateless-ness.

Lisp and Languages with FOFs

On the other hand of the spectrum of "functional languages" we have Common Lisp and the various freedom languages where functions are first order objects (Python, Ruby, ...), with Scheme leaning a bit more towards the functional side. Technically speaking Python is not even a functional language. Surely it is not stateless (but Lisp is neither). In fact, in Python recursion is frowned in favor of iteration (but iteration is often built around generators, which are an user-friendly/dumbed-down[0] instance of anamorphism -- unfold --, which is strongly functionally flavored). On the other hand, some call Ruby the Matz-Lisp.
In these languages there is no explicit restriction towards stateful programming. This means that usual algorithms and way of thinking are easy to implement (especially in Lisp, both very functional and very stateful algorithms are easy to implement). On the other hand, restriction of state change is left to the sense of the programmer (which not always is a good thing, but I don't really like languages which tell me exactly what to do... they just have to make the better way obvious -- I'm not Dutch, sorry --).
To be sincere, there are just things that are so much easier in stateful programming than in stateless programming. And for other stuff the converse applies. Consequently, the language should not force me too much towards one style or the other. Moreover, stateless-only languages tend to be harder to pick up for beginners (on the other hand Python and Ruby are extremely easy to start with and I believe that scheme is a wonderful first language for computer scientists). Eventually, stuff like GUIs are really hard to implement in fully stateless settings (clojure essentially relies on Java underlying classes, and I actually have never used Erlang for guis -- not that I am a strong GUI developer --).

On performance

One of the consequences is that lots of algorithms, data structures and ideas are just developed with stateful programming in mind. This is the reason books suck as Okasaki's Purely Functional Data Structures have been written: just to bridge the gap between mainstream stateful programming and functional reasoning.

Unfortunately many algorithms have been created with imperative languages in mind, and the data structures supporting the algorithms strongly reflect the imperative setting. Implementing such algorithms in functional settings is usually inefficient to say the least. Much theory (and not only the practice) is built around state change. The Art of Computer Programming uses a pseudo assembly language which essentially manipulates a Von Neumann machine.

Something as easy as "modify an array" may be a source of inefficiency in many languages. E.g., clojure provides transients just to make it easier to express such operations. On the other hand functional languages have usually some troubles in providing a data structure that is immutable, offers O(1) random element access and allows element modifications without copying the whole data structure.

Books


"Purely Functional Data Structures" (Chris Okasaki)


"Art of Computer Programming, The, Volumes 1-3 Boxed Set (3rd Edition) (Vol 1-3)" (Donald E. Knuth)



Notes

[0] depends on whether you are a python or a scheme programmer: python programmers usually say user-friendly

Thursday, January 27, 2011

Cleanup Strategies semantics for different languages

A couple of days ago, I was reading a nice Puzzle in Java Puzzles.

The book is full of interesting information regarding gotchas of the Java language and VM and also contains some useful insight for language developers (in the sense of "get right what Java designers got wrong").

The puzzle was about the return value of a function such as:

boolean f() {
  try {
    return true;
  } finally {
    return false;
  }
}


Of course, the function returns false according to Java specifics. The authors however argued that this kind of programs should be forbidden by language desigers as their semantics is rather counterintuitive. Personally, I'm not sure if a language has to become more complicated to avoid these kind of problems. I rather believe that this kind of stuff is under the responsability of the programmer.

Nonetheless, I decided to see what happened with different languages. Unsurprisingly, in Python it has the same semantics than in Java"

In [4]: def f():
...:     try:
...:         return True
...:     finally:
...:         return False
...:

In [5]: f()
Out[5]: False


Essentially, either you bane such programs (e.g., return is not allowed in a finally clause) or you can't avoid the problems: returning True would be far worse. Ruby does the very same thing:

def f()
  begin
    return true
  ensure
    return false
  end
end

irb(main):020:0% f
false


Essentially, the problem is with finally (well, ensure, in Ruby). On the other hand, if a language does not provide any cleanup mechanism error management is seriously more complicated. In fact, in Ruby it is not uncommon to use blocks for this purpose. In Python, we have the with statement. Considering that the with statement associates a block code with a context and cleanup happens in the __exit__ method of the context object, there is essentially no way that such unsurprising behaviour happens (the return value of the __exit__ block is not the return value of the function).

In [1]: class ContextExample(object):
...:     def __enter__(self):
...:         pass
...:     def __exit__(self, *stuff):
...:         return False
...:
...:
In [4]: def f():
...:     with ContextExample() as c:
...:         return True
...:
...:

In [5]: f()
Out[5]: True


However, before moving to other kind of error management strategies (RAII, with), we should notice that things in clojure are different:

(defn f[]
  (try
    true
    (finally
      (println "FOO")
       false)))

(println (f))


prints "FOO" and then true. Essentially the finally block is executed, but the value returned is not the one of the finally block. Surprising? Not really. In Clojure documentation is crystal-clear on this point:


(try expr* catch-clause* finally-clause?)
catch-clause -> (catch classname name expr*)
finally-clause -> (finally expr*)

The exprs are evaluated and, if no exceptions occur, the value of the last is returned. If an exception occurs and catch clauses are provided, each is examined in turn and the first for which the thrown exception is an instance of the named class is considered a matching catch clause. If there is a matching catch clause, its exprs are evaluated in a context in which name is bound to the thrown exception, and the value of the last is the return value of the function. If there is no matching catch clause, the exception propagates out of the function. Before returning, normally or abnormally, any finally exprs will be evaluated for their side effects.


Considering the Java heritage of Clojure, this may be surprising for Java programmaers (at least those crazy enough to use code resembling the one at the beginning of this page). However, such behaviour is exepected and welcome for Lisp programmers. Indeed the Lisp equivalent of "finally" is the lovely unwind-protect. And the doc of unwind-protect states that:


unwind-protect evaluates protected-form and guarantees that cleanup-forms are executed before unwind-protect exits, whether it terminates normally or is aborted by a control transfer of some kind. unwind-protect is intended to be used to make sure that certain side effects take place after the evaluation of protected-form.


Once again: the cleanup stuff can be used only for side effect. The return value is the one of the main expression.

Tuesday, January 18, 2011

Why learning not-so-mainstream-languages pays

I was reading Ruby ng and I stumbled in this. Basically the article says that in Chicago there are far less Ruby programmers than the industry requires. Which basically make it rather easy to get a job (if you know Ruby). Companies are even trying to relocate people and to teach Java/.Net developers Ruby (well, scout the good ones and teach them Ruby: bad developers would remain bad, perhaps in freedom languages they would look even worse by comparison).

This is happening right now in Chicago. But I continuously hear about such stories: knowing less widespread and niche technologies is a huge competitive advantage, even for newcomers. On the other hand, competing with thousands of developers of more mainstream languages is much harder and often leads to less interesting jobs.


Tuesday, January 4, 2011

Seven Languages in Seven Weeks

Today I eventually received my own copy of "Seven Languages in Seven Weeks". To be sincere, I started reading the electronic version some time ago (Pragmatic Programmers had a huge discount some time ago, just after the "Programming Ruby" at 10$).

Seven Languages in Seven Weeks


I'm not going to criticize the language choice. In fact, I think that the languages are a wise selection (Ruby, Io, Scala, Clojure, Prolog, Haskell, Erlang). They are all interesting languages and have something other languages do not have. Although I'm quite into Python, I'm not going to complain for its exclusion: the author is far more confident with Ruby (as far as he tells) and that means that his explanations are surely more accurate.

I love the idea of the seven languages in seven weeks: beware, this is not a "Teach yourself C++ in 21 bloody hours". The author is well aware that you could not possibly learn seven languages in seven weeks, but you can understand what those languages are about in seven weeks. I'm thinking about the potential this book has when read by people grown up in closed Microsoft or Java contexts (or perhaps even C and C++). If after reading this book he is still convinced that all the languages are the same he is either a compiler or a very distract reader (and probably hasn't understood a thing about the book).

Just seeing the languages is a wonderful enlightening experience. Realizing how much useless boilerplate compiler-friendly code some languages force developers to read is the first step towards better ways of programming.

And what about me? Well... I already knew 5 of the 7 languages quite well. I have known Ruby and Haskell for 5 years or so, a couple of years later I learned Erlang as well. Besides, I also wrote some thousand of lines in Prolog for my BSc and my MSc dissertation was on logic programming (specifically on building an efficient "interpreter" for a given logic programming language not too dissimilar from Prolog itself). I started studying Clojure basically when the word of mouth started spreading, which makes it about 2 good years. So what's it for me? For example, I am sorry to say that I found the part on Prolog rather unsatisfactory, but hey... I don't think that the goal of the book is to teach me Prolog. However, it gave me a pleasant introduction to Io (which I would have probably never learned) and convinced my that my first impressions on Scala were wrong and perhaps I have to give it a second chance.

So definitively worth reading. And here a free chapter!



Saturday, November 13, 2010

Have you got enought Fiber?

I recently bought last edition of the Pickaxe and started reading through. The "Fibers, Threads and Processes" chapter caught my attention immediately. I'm not on par with latest ruby features (especially, I have never used 1.9), so I decided to understand what fibers are.

The example in the book closely resembles the one presented in the Pickaxe when explaining Fibers. However, I performed some slight modifications are I prefer "filter" programs, reading from stdin and printing to stdout, than the ones which require a command line argument (or worse, have a fixed constant in the program code). Apparently this strategy is very poorly supported by IDEs but well... shit happens. Afterall I'm already tolerating that the environment is not usable before 2 whole minutes... ah, Netbooks!

Anyway, this is the code:
require 'fiber'
require 'fiber'

words = Fiber.new do
  STDIN.each_line do |line|
    line.scan(/\w+/) do |word|
      Fiber.yield word
    end
  end
  STDIN.close
end

counts = Hash.new(0)
while word = words.resume
  counts[word] += 1
end

counts.keys.sort.each {|k| print "#{k}: #{counts[k]}\n"}


So, the idea is that basically the block passed to the fiber is not executed.
When the resume message is sent to the fiber, the control is transferred inside the fiber. The fiber is executed up to a yield message; at this point the control is transferred back to the code which called the Fiber and the value returned by the resume message are the arguments of the yield message.

Ok, rather easy. This is basically equivalent to Python generators. As it happens most of the times, in Ruby you pass a block so to someone, in Python you define a function.

So I decided to provide a rather faithful Python version:
import re
import sys
import collections

def yield_words(iterable):
    for line in iterable:
        for word in re.finditer('\w+', line):
            yield word.group(0)
    
count = collections.defaultdict(lambda: 0)
for word in yield_words(sys.stdin):
    count[word] += 1
 
for word, occurrencies in count.iteritems():
    print word, ':', occurrencies


The structure is essentially the same. The last component in Python and Ruby is extremely similar. Of course in Ruby you pass a block, in Python you have a for loop on an iterable.

The second component is also quite similar. However, in Python we simply iterate over a for loop. We don't have to call explicitly a "resume" command/method (although we could). I think that the essential difference is that Python generators are iterators. On the other hand Ruby Fibers are something slightly different

I decided to keep the structure of the first block as similar as possible. Chaining Python iterators with functions in functools and intertools, the yield_words function could have been written like:

import itertools as it
import functools as ft

def yield_words(iterable):
    return (word.group(0) for word in
            ft.reduce(it.chain, 
                      (re.finditer('\w+', line) for line in iterable)))


Not really sure that chaining all that stuff increases readability, though. As a side note, all the presented versions are really interactive. If you use stdin instead of piping a file (you were not typing lots of text in, were you?), the program is fully interactive.

That is to say, for example, that is, each time you read a line it is immediately processed, as if the two program parts (the "producer", which asks input and the "consumer" which puts it in the dictionary) were mingled. However, the logical separation is quite evident and the code clarity is greatly improved.


IntelliJ Ruby Plugin

As I promised... more stuff on Ruby! This is about the installation.
OS X and Linux mostly have Ruby installed. However, you may want to install JRuby as well. On windows, I installed them both.

As a development environment, I choose IntelliJ, which I already use profitably for Java. Probably there are better choices (TextMate on OS X springs to mind, gvim/emacs). However, I want to see what can a "traditional IDE" (and a good one) offer for developing with a very dynamic language like Ruby. Unfortunately Python support does not seem as mature (besides, Ruby plugin is supported by IntelliJ developers and they also offer a Ruby IDE -- whose features should be offered by the Ruby plugin as well --).

As a side note, for Python I already bought WingIDE and I'm happy with that. However, since I don't plan to work with Ruby anytime soon, I only consider free (as free f*ckin' beer) solutions.





Here some screenshots from the setup of a Ruby project

So here some stuff on what the plugin can do. It's lots of interesting stuff.

However, I would like to point out that Ruby is a dynamic language; and the first things you are going to do are simple scripts to automate some repetitive task unless you are going to do Rails development. Since I'm not interested in Rails, I just point out that setting up a Rails environment seems very easy and well supported.

On the other hand I'm mostly interested in the "scripting" part, as it's the first you are going to meet if you don't do rails, like I said.

IRB is well supported. But I don't think its integration with the IDE is sufficient. I can open an IRB console and put Ruby commands inside. Good. A REPL is a very important part of dynamic languages development. I can also load a Ruby script directly in IRB (alt-shift-l -- btw, I suppose it will be a PITA on OS X).

However, since that command only 'requires' the file in IRB, successive invocations have no effect, unless you close and reopen IRB. It would be nice if modified versions of the script could be run without closing and opening IRB. It is something I would expect from a Ruby IDE. E.g., in TextMate it is very easy to do; and at the beginning it is just what you need.

The other options is creating a "runner". Which is easy, there is a menu entry that automagically creates one. This is good to run a script (but remember... you already created a project, and then create runners for every -- logically unrelated -- script in the project). This is a lot of useless work.

Things work slightly better if you just select the text and load (the selected text) in IRB. This way you can run the code more than once. Moreover, you can also have functions defined in IRB and than play with them. I think this is far more useful than 'requiring' stuff, especially because you can't reload.

Ok... the nice things another day. Maybe. However, the "environment" support seems really javish. Not happy. :(


Friday, November 12, 2010

Pickaxe (almost) for free [Ruby]

Although here in Italy there is lots of talking about Ruby, they are not quite referring to the programming language. However, there are some very interesting news about the programming language as well.

These days the new version of Programming Ruby (also known as the Pickaxe) has a huge discount: both the printed version and the electronic version cost $10. Buying both costs 20$.

I believe that publishers should really reconsider charging extra money for those who want also an electronic version of a book they already bought. They should reconsider this (as I'm afraid piracy will just become a serious problem as ipad/ebook riders and similar device are going to spread). However, in this case I don't care.

Why? 20$ to have a full book (electronic & paper) is a very convenient price and I'm happy with it that way. I just bought them so expect some more ruby related posts in the future. ;)





Thursday, March 22, 2007

Execute saved Synaptic markings

It happens quite often that I use synaptic to manage packages on my debian.However, sometime I save the markings in order to perform the installations another time.For example I need to apt-get something quickly without waiting for the whole thing to be downloaded and installed.

The standard procedure would be running synaptic again and then loading the markings.However, in this cases I don't feel like I need to start the whole synaptic thing. I'd prefer a small command line utility that processes the saved markings.

I wrote one. It is very simple. It uses sudo, so every now and then it asks the password.Of course one could do a better job, but I had not time to do something better.

#!/usr/bin/env ruby

args = $*
if args.size == 0
    puts "You should provide a file to process"
    exit 0
end

dict = Hash.new
File.open(args[0]) do |f|
    f.each_line do |line|
        key, action = *line.split
        dict[key] = action
    end
end

# sudo apt-get #{v} #{k}

dict.each do |k, v|
    exec("sudo apt-get -y #{v} #{k}") if fork.nil?
    Process.wait
end

Wednesday, March 21, 2007

Scripting languages

What is a scripting language?

From Wikipedia we read that:

Scripting languages (commonly called scripting programming languages or script languages) are computer programming languages that are typically interpreted and can be typed directly from a keyboard. Thus, scripts are often distinguished from programs, because programs are converted permanently into binary executable files (i.e., zeros and ones) before they are run. Scripts remain in their original form and are interpreted command-by-command each time they are run. Scripts were created to shorten the traditional edit-compile-link-run process.

Of course any self respecting computer scientist knows that definition is meaningless, because a language is a mathematical constructand is not tied to its implementation. You can write a C interpreter, for example (and there are some). You can also write a compiler for any 'interpreted language' (of course the term 'interpreted language is also meaningless). And there are theoretical constructs (Futamura projections) that given any interpreter are able to build a compiler from it (you could implement them even in practice, though it would be terribly inefficient).

However, any other definition would be misleading as well: if you define a scripting language as a language you can use to "script" (as in "bash script"), then you've got definition that's even more stupid. bash is a scripting language, and so it is Python. However, if someone writes an application that is scripted in C, C becomes a 'scripting language').

Both definitions have an additional problem: scripting languages are considered somewhat inferior to 'non-scripting languages'. Some even use the term 'true programming languages' (and this 'true programming languages' are usually considered to be C and C++, for example).

Lisp, Haskell, OCaml, Prolog

In this dissertation on 'scripting languages', Lisp is quite emblematic. Lisp can be compiled (there are some Lisp compilers around). But Lisp can also be interpreted. This is one of the most widespread Lisp environments (and it is an interpreter). Moreover, in Emacs you can just run some Lisp snippets. And Emacs itself is scripted in Lisp (thus Lisp would be a scripting language according to the second definition). However, no one can assert that it is not a 'true' programming language. Emacs itself is a beautiful (and complex) piece of software, and a lot of 'real' (and extremely difficult) stuff in the AI field has been written in Lisp.

Haskell can be another example. Hugs is an interpreter, ghc is both an interpreter and a compiler. And Haskell is even statically typed (so you see, being dynamic is not necessary ). The very same applies for OCaml or Prolog. And all thislanguages have been used by the most theory-oriented computer scientist toimplement real programs.

I suppose nobody would say that Lisp or Haskell are 'scripting languages' (even if according to the definitions they are -- Haskell is used in many configuration tools by Linspire programmers).

Bash, Perl, Python, Ruby.

All this languages have been labeled as 'scripting languages'. And in fact according to definitions, they are. However, they are very different languages.

Bash is a very simple language designed to do simple things. Unix system administrators used it intensively (along with awk and sed and other utilities) to automate many repetitive tasks. Although this is surely 'programming', in some sense it's different from programming an application from scratch. Some even consider it a 'lower level' kind of programming (and surely we must recognize that skills involved in writing a boot script are different from skills used to write a compiler)

Perl was born in this environment: its goal was textual manipulations and interactions between processes in a system. It is a nicer alternative to bash + awk in many situations. Later it has been added a fully fledged object model, but in the while it has been used to write very complex applications that go outside the 'lower level programming domain' that is usually associated with 'scripting'. Even though I don't like Perl anymore, it is a general purpose language, with the same dignity of C or C++.

The 'scripting language' monicker is not fitting anymore. And it is even less fitting for Python. Python has been an object oriented programming language from the beginning. Good software engineering practices have always been employed. However, many consider it just another scripting language. And of course Python makes a great scripting language.

The domains in which Python excels are the same in which Java is used, for example. However, Python can be used for scripting, too. That is to say... some (and I'd be tempted to say 'most' ) 'scripting languages' can be used both as general purpose languages and automation/scripting.

The reason why they can be used for automation/scripting and that they are easier to use and we can write programs faster. The development cycle is faster, too. And to me, they all seem good properties.

I think that the very same features that make Python (or Ruby) great for scripting, make it even greater for general purpose programming. That is to say we should consider a 'scripting language' not a poorer language, but a better one (yeah, of course this is exaggerated, since there are languages suited for scripting that are not suited for general purpose programming -- AppleScript and bash, for example).

Emacs and emacsclient (Ruby script to call them both)

I usually call one single emacs server (I've got (server-start) at the very beginning of my .emacs), then connect to it with some emacsclient.

Unfortunately enough emacsclient just quits if there is no active emacs server.

I need a process that tries to run emacsclient: if there is no active server, it runs emacs.Moreover, emacsclient has a -n switch that makes it return ASAP, so the terminal is available for more commands.emacs has not such a switch, but that behaviour is the one I want.

So I decided to write a small ruby script that does just this:
  1. Tries to run emacsclient with the -n option.
  2. If it succeeds, we are done. Otherwise we run Emacs doing some standard posix process manipulation in order to return to the shell as soon as possible.

This is the script:

#!/usr/bin/env ruby

fork do
    exec('emacsclient', '-n', *$*)
end

Process.wait
    if $?.exitstatus != 0
        fork do
        Process.setsid
        Signal.trap('HUP', 'SIG_IGN')
        exec('emacs', *$*) if fork.nil?
        exit!(0)
    end
    
    Process.wait
end

Sunday, March 18, 2007

Ruby Cookbook: review

I recently bought the Ruby Cookbook. I bought the italian version (whose title is 'Ruby Cookbook con elementi di Rails' which roughly translates to 'Ruby Cookbook with elements of Rails'). However, the book itself is not different.

Although I prefer to read technical books in English, I often buy books in Italian in order to show the publisher interest on that particular technology. In fact, in a country where most people avoid buying book in English because they feel they are 'too' difficult (like in Italy), good technologies do not spread if there are no good books in the local language.

The first impression with the book has been terribly negative. Actually if instead of buying the book online, I found it in a shop and leafed through it, I suppose I would have put it down.

Strings in Ruby are much like strings in other dynamic languages like Perl, Python

and PHP. They’re not too much different from strings in Java and C. Ruby strings are dynamic, mutable, and flexible.

In this paragraph you learn that "Ruby strings are dynamic, mutable, and flexible." And that is true. However, you get another impression: the authors do not know what they are talking about.

They say that Ruby strings are 'much like' the strings in Perl. This is almost true (well, Perl unicode support is much better than Ruby, and Perl deals natively with unicode strings. However, saying that Ruby strings are like Python strings is plainly wrong: Python strings are immutable and are somewhat more akin to Ruby symbols (in fact if you call intern on a Python string you get something semantically very similar to a Ruby symbol). Moreover, Python deals with unicode natively.

Again, the comparison with Java strings is plainly wrong: in Java strings are immutable. The comparison with C is terrible: in C, strings are not even a primitive data type.

As I said before, at this point I was tempted to put the book on a shelf and never open it again. Luckily enough I went on and soon enough I found out I bought one of the best books on Ruby available.

The impression that the authors are not competent (or at least they speak of something they do not know) is plainly wrong. A few chapters later, there are some chapters that quite accurately confront Ruby pragmatic with Python one. They are poignant and precise: definitely the authors know both languages quite well. I suppose the 'bad' paragraph at the beginning was a tentative to be didactical.

The book in fact is quite didactical. You can read it with almost no previous knowledge of Ruby. The reader is guided through Ruby syntactical conventions (for example when dealing with strings, you learn that parentheses are optional, which is known to everybody who coded a bit in Ruby).

In the later chapters (most notably the ones on modules and objects), the reader learns the nature of Ruby power, and how to reason and develop in order to unleash that power. This book is a cookbook, but every single receipt does more than teaching a way to achieve its goal: it teaches something about the way Ruby programmers should think and code *in general*. In fact you can consider this cookbook a 'beginner' book that teaches by examples (and that is a very effective way in a language such as Ruby). Of course, there is also plenty of intermediate and advanced stuff, or subjects not covered elsewhere (for example the ones about image manipulation).

This is a precious book and the ideal companion for everyone who's seriously motivated in learning Ruby. But it is also a book that a Ruby programmer may want to keep on her desk to find out how to do things without reinventing the wheel.

Tuesday, March 13, 2007

Duck hyping and Ruby

Introduction

Ruby is the new boy in town. Until a couple of years ago, nobody reallyspoke about Ruby. It was really popular in Japan, but outside it was justone of the many 'scripting' languages that the open source world has developed over the years.

The big names were using Python or Perl. Well, most of them were using PHP,but in fact this does not matter: while Perl, Python and Ruby are excellent languages (even if it is almost impossible someone really likes both Perland Python, nonetheless Perl has its merits), PHP plainly sucks. And then of coursethere was that Java everybody was talking about and C# (but the open sourceguys usually said positive things about it only if in the same sentence the word 'mono' occurred).

In the last few years Rails changed things. Now a lot of people are talkingabout Ruby and dynamic languages. A lot of Java developers discovered thepower of dynamic languages and dynamic typing, after years spent sayingthat the only saviour was static typing. In fact it seems to me that thereis kind of a revolution in the IT world.

Python and Ruby and Lisp and ...

Rails is a pretty good framework. The documentation is acceptable even forthose who grew up with Sun's bloated documentation (I still prefer to readthe code if the language itself is readable enough).

Ruby is a really nice language. In fact you can see it as a (Perl--)++.It kept almost all nice features from Perl, and dropped some of the worse.Of course a Perl Monger would disagree, but I'm a pythonist after all.

One of the most interesting things, in my opinion, is that Ruby and Pythonare quite similar (even if they start from different points of view). I feelquite comfortable with both languages, and even their pragmatic is notreally different. Moreover differences tend to depend on different syntax, rather than on different semantics.

For example in Ruby is quite frequent to 'open' classes and add methods.This is something you can do in Python, even if there isn't a specialsyntax.

>> class A(object): pass
>> a = A()
>> a.foo()
Traceback (most recent call last)
...
<type 'exceptions.AttributeError'>: 'A' object has no attribute 'foo'

>> def ext_foo(self): print 'foo'
>> A.foo = ext_foo
>> a.foo()
foo

Of course this is far less elegant, and that's way it's something less frequently done in Python.

Ruby has another 'advantage' over Python. It's syntax is less rigid, and in fact the most typical thing that is in Ruby pragmatic is to write a DSL in the language itself and program in that DSL.

There are a lot of examples of this strategy in Rails itself. However, thisapproach is not new at all. Lisp programmers have been using it since thebeginning, that is to say it's almost forty years they code DLS in Lisp anduse them to write the application.

Duck typing vs. duck hyping.

Unfortunately I hear people saying quite often that 'Ruby invented duck typing'. People that just discovered Ruby, seem quite certain about it. Some of them even told me thatin Python you 'were not really duck typing' and that it was something peculiar to Ruby. But let's look at the definition (from Wikipedia):

Duck typing is a form of dynamic typing in which a variable's value itself implicitly determines what the variable can do. This implies that an object is interchangeable with any other object that implements the same interface, regardless of whether the objects have a related inheritance hierarchy. Duck typing is a feature of programming languages such as Smalltalk, Python, Ruby, and ColdFusion.

Of course this is something that you can do in Python. And you can also do it in Objective C, by the way. And in Python it is something plainly obvious, too. Everybody does it, everybody likes it. But nobody thought about using a fancy name when describing the practice in books and blogs.

Amazingly, the term 'duck typing' (that some think it's a Ruby peculiar feature) was probably used for the first time by Alex Martelli when speaking about Python typing system. It was Jul 26 2000, and the english language Ruby newsgroup had been active since the first days of may. There was a mailing list of course, but nonetheless Ruby was relatively unknown outside Japan.

In other words, don't check whether it IS-a duck: check whether it QUACKS-like-a duck, WALKS-like-a duck, etc, etc, depending on exactly what subset of duck-like behaviour you need to play your language-games with. If the argument fails this specific-ducklyhood-subset-test, then you can shrug, ask "why a duck?" (at least, you can if you're a Marx Brothers fan and have memorized "Cocoanuts"' script; Monty Python one-true-wayists will have to find their own simile here), and move on to the next set of tests (why-a-no- chicken immediately comes to mind, but then one would have to ask why it crosses the road, so I think we'd better snip it).

Alex's original post

That is the reason why I say that Ruby supports 'duck hyping'. Ruby is a very good language. I suppose that if I learnt Ruby before Python, I'd probably like Ruby more than Python (because the languages are quite equivalent, it's my head that now works in a somewhat more pythonic way). However, there are a lot of people that are really *good* at selling Ruby. An excellent publisher based his early success on Ruby books, the creator of Rails has lots of marketing skills, and so on.

However, I was wondering: why Ruby and not Python? I don't believe in fortune. To discover the answer (that in this particular case I guarantee it' s not 42) we must analyze in which ways syntactical features of Ruby (since semantically they are quite interchangeable) influence the language pragmatic, and in which ways the pragmatic contributed to build Ruby success.

And when we are into pragmatic, we are not in the world of the compiler: we are in the world of the programmers. That is to say: we must understand why Ruby has appeal even where Python has not. We must understand in which way the language influenced the way of thinking of so many people, and why Python did not.

Monday, September 11, 2006

Rails: Loading fixtures to development with a specified order

Background
My development style is heavily test driven. One of the very first things I do write are fixtures, in order to write tests on them. For this reason the very first database I use in a Rails projects is the test database, rather than the development one.
When I have to populate the development db, I already have plenty of fixtures: if they aren't enough to try the user interface (that is what is left to do), they weren't enough to test the models and the controllers.
Of course this should be no problem, there is the rake task db:load:fixtures that plays well with this kind of issues. However, I tend to use db constraints rules such as
ALTER TABLE bars ADD FOREIGN KEY(`foo_id`)  REFERENCES foos  (`id`) ON DELETE CASCADE;
if you use MySQL or
ALTER TABLE bars ADD CONSTRAINT valid_foo FOREIGN KEY (foo_id) REFERENCES foos (id) MATCH FULL;
if you use Postgres.
Solution
Of course, in this case you can't load fixtures in any order and you must supply correct fixtures loading order.
After some searching I found this solution.
However, it does not work. In fact it builds a Hash inserting fixture names in the specified order, than builds an array with other fixtures that had not been specified as needing some particular order.
Eventually, it sums the keys of the hash and the array, and loads fixtures in this order. I don't understand how the poster got this code working, since Ruby Hashes are not ordered in any way and the documentation explicitly says that iterators and methods return values in arbitrary order and do not rely on insertion order.
This meant I had to change the code. Now it uses arrays everywhere (which seems the most reasonable thing to do, since this rake task it's about order). I also added namespaces.
You still have to define something like

ENV["FIXTURE_ORDER"] = 
    %w( entities interaction_sources interaction_devices 
        payments interactions accounts employments 
        enrollments payables receivables tenures wards ).join(' ')

My code is:

require File.expand_path(File.dirname(__FILE__) + "/../../config/environment")
ENV["FIXTURE_ORDER"] ||= ""

def print_separator_line(n=80)
    puts "\n" + '='*n
end

desc "Load fixtures into #{ENV['RAILS_ENV']} database"

namespace :db do
    namespace :fixtures do
        task :load_ordered => :environment do
            require 'active_record/fixtures'
            print_separator_line
            puts "Collecting specified ordered fixtures\n"
            ordered_fixtures = ENV["FIXTURE_ORDER"].split
            fixture_files = Dir.glob(
                File.join(RAILS_ROOT, 'test', 'fixtures', '*.{yml,csv}'))
            other_fixtures = fixture_files.collect
                { |file| File.basename(file, '.*') }.reject 
                    {|fx| ordered_fixtures.include? fx }
            ActiveRecord::Base.establish_connection(ENV['RAILS_ENV'])
            all_fixtures = ordered_fixtures + other_fixtures
            print_separator_line
            puts "Fixtures will be loaded in following order\n"
            all_fixtures.each_with_index do |fx, i|
                puts "#{i+1}. #{fx}"
            end
        
            print_separator_line
            puts "Actually loading fixtures to #{ENV['RAILS_ENV']} db..."
    
            all_fixtures.each do |fixture|
                puts "Loading #{fixture}..."
                Fixtures.create_fixtures('test/fixtures',  fixture)
            end unless :environment == 'production' 
            # You really don't want to load your *fixtures* 
            # into your production database, do you?  
        end
    end
end

Saturday, June 24, 2006

Ruby on Rails: make LoginEngine fixtures dynamic

admin:
id: 1
login: admin
salted_password: 
salt: 
email: admin@company.com
verified: 1
This way you always generate fixtures that behave correctly according to your salt and such. Otherwise I had problems when doing "rake load_fixture" in the development db (the login failed).

Thursday, June 22, 2006

Rendering a chosen RJS

Of course to render a rjs that has a name different from the controller method, we must use the :action specifier. For example we could have something like:
respond_to do |wants|
    wants.html {render  :partial=>"post", :object=>@post, :layout=>'posts'}
    wants.js   {render  :action=>"remote_show"}
end
Although this is pretty obvious if you reason about it, you may need some time to get it. And on the net there aren't easily accessible examples about it (or at least I found none).
It's just a dirty trick.

Wednesday, June 21, 2006

Pattern Matching in Ruby

Inspired by a discussion on the Italian Ruby mailing list, I decided to write (probably another) pattern matching implementation for ruby. In the short term I want to be able to define something like:

func :qsort, [] { [] } 
func :qsort do | list | 
    qsort( list.select {|a| a <  list[0]} )  + 
        list.select {|a| a == list[0]}    + 
        qsort( list.select {|a| a >  list[0]} ) 
end 

and if I find time it could become even some kind of "declarative like" unification algorithm... who knows. The point is I don't even know if I have enough time for the "toy" pattern matching.

[from the future: I did not find time!]