Thursday, June 9, 2011

Two best programming languages for serious programmers

After working with Java for five years, I thought I knew about OO until I started learning about Smalltalk. Reading "Smalltalk by Example" - a free book that you can download from here - had profound impact on how I think about Object Oriented Programming. Java's procedural and OO mix left me in a half-way schizophrenic state. Despite having read and practice "Clean Code" by Uncle Bob, I still found many if/else, check result and poorly designed classes. The idea that everything I mean literally everything is an Object teaches you the foundation of OO: Message Passing. The only way of getting things done in Smalltalk is via message passing, which supports "Don't ask, tell" and "Put off as much as you can" golden rule. This way of thinking results in very elegant design and code.

Now you might wonder what are the two best programming languages I am talking about? You should know by now that the first one is Smalltalk. The second one is Clojure. Clojure cures the disease of writing hundreds of classes to deal with hundreds of different composite data structures. Why? Because you can't. The power of Clojure's sequence abstraction and provided core functions that operates on them gives you superman powers to manipulate data. For example, following simple function will condense strings by removing extra white spaces:
(ns compact
  "compact a string by removing extra white spaces")

(defn compact [s]
  (reduce #(str %1 " " %2)
   (filter #(seq %) (seq (.split s " ")))))

Usage:
(compact "  Your     uncompact    String  ")
-> "Your uncompact String"

I am not even contemplating the Java implementation of this simple function. This is all good. Why do I mention Smalltalk as the first one, you wonder. Here is why:
You do not need to implement the compact function. You just tell the String Object to compact itself. Here you go:
'  Your     uncompact    String  ' withBlanksCondensed
-> 'Your uncompact String'

You just send the "withBlanksCondensed" message and you are done. Clojure gives you the option of being practically lazy, but Smalltalk makes you one. So learn yourself a little Smalltalk and Clojure if you are really serious about programming with elegance and laziness.

25 comments:

  1. Nice post! I thought I was the crazy one for looking at both Clojure and Smalltalk 8)

    You might be interested in Redline Smalltalk, an image-less Smalltalk for the JVM.

    ReplyDelete
  2. Make me want to read more about Smalltalk
    BTW why #(seq %) instead of seq ?

    ReplyDelete
  3. I am glad that you like Smalltalk. #(seq %) is just an idiomatic way of saying:
    #(not (empty? %)). seq? x returns true if x implements ISeq.

    ReplyDelete
  4. BTW: clojure.string provides some string utilities:

    (trim (replace " Your uncompact String " #"\s+" " "))

    ReplyDelete
  5. Sadly I disagree. Serious programmers create all the new words and syntax of a high level language themselves. They do not use other peoples.

    ReplyDelete
  6. that's pretty funny. smalltalk and clojure are great languages, for certain purposes, but I'd like you to define 'serious programmers' a little more please. there's a long litany of purposes I wouldn't consider either of those languages for, but that doesn't make me ! a 'serious programmer'.

    ReplyDelete
  7. I don't see how the clojure example is "superhuman powers to manipulate data". I mean, in Python the function is even simpler:
    def compact(s):
    return " ".join(s.split())
    (Yes, the "return" should be indented)

    "Superhuman powers"? No, just what one would expect in any modern language.

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. In Ruby, everything is an object and Ruby itself takes ideas from smalltalk. The compact function is a single line. You simply send 2 messages to the string object,

    " Your uncompact String ".strip.squeeze

    ReplyDelete
  10. I like what catcalls said. I'm a serious GWBasic programmer ;) . It would take several lines to write the compactor to be sure. But then, I could make a custom function out of it and call it like:

    S$ = "My uncompacted string."
    S$ = Compact$(S$)
    Print S$
    My uncompacted string.

    Or simply,

    Print Compact$("My uncompacted string.")

    Of course, i must first write some stuff in GWBasic that allows me to program more like Quick Basic without line numbers. The way the function needs to be called in GWBasic is pretty ugly, but it can work, track private and global variables, and pass params by value or reference. Ok, not very practical, but a fun way to learn stuff.

    ReplyDelete
  11. Looks like the comment box has an automatic compactor routine built-in! :)

    ReplyDelete
    Replies
    1. Yeah, that's HTML. Try it yourself: <p>Here's text__spaces?</p> those __'s are compacted. In fact any number of whitespace (including line breaks, tabs, and spaces) are all condensed unless you specifically insert some  's in there.

      Delete
    2. Hahaha- that should say, "some &nbsp;'s in there" but it got converted into its HTML representation.

      Delete
  12. I disagree. What makes a good "serious" programming language isn't just conciseness in somewhat over-specific tasks. It's overall ease of use, extensibilty, and syntactical clarity. (That's VB.NET, IMHO ;-])

    ReplyDelete
  13. "I am not even contemplating the Java implementation of this simple function."

    The Java implementation is actually fairly succinct:
    java.util.regex.Pattern.compile(" +").matcher("String to be compacted").replaceAll(" ")

    Will return the compacted string.

    However I must agree with you on Smalltalk's elegance.

    ReplyDelete
  14. (I(don't(find(it(to(be(very(elegant))))))))

    ReplyDelete
    Replies
    1. (-> thats because you never bothered to learn it)

      Delete
  15. I actually liked all of your comments. If the post made at least one programmer to dive into Smalltalk or Clojure, it is just good enough a result for me.

    ReplyDelete
  16. Good topic but bad example.

    What you demonstrated is common for all modern languages. Someone already posted Python sample. Here is the C# one:

    static string Compress(this string text)
    {
    return string.Join(" ", text.Split(new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
    }

    or with Linq:
    return string.Join(" ", text.Split(' ')
    .Select(x=>x)
    .Where(x=>x!=""));

    And this is how you use it:
    var text = " Hello World ! ".Compress();

    Also I hear a lot from Smalltalk (and Ruby) guys that it is an ultimate OO language. Quite possibly so but the evidence is usually "everything is an object".

    Again, many modern languages share the same concept: everything is an object. Examples: C#, Python...

    Looking forward to more convincing samples.

    ReplyDelete
  17. personally, I like the brainf**k implementation:
    ,>,>++++++++[<-----+><>>.[]-],-,-<------>>-]<<[>[>+>+<<-]>>[<<+>>-]<<<-]>>>++++++[<++++++++>-],<.>.

    ReplyDelete
  18. I liked this article. I'm not going to go into the whole 'serious programmer' discussion. But I will say this. If you're a serious programmer you will have a natural hunger to learn anything that can help advance your skills as a software developer. It does not matter what language you program in. If learning about smalltalk can make you a better programmer do it. And then return to your language of choice and apply the newly obtained knowledge during your software development cycles.

    ReplyDelete
  19. Hi Billy,
    Thanks for the Java implementation. You actually forgot to trim it:
    java.util.regex.Pattern.compile(" +").matcher("String to be compacted").replaceAll(" ").trim()

    You can experiment with your code in Clojure REPL. Just type:
    (-> (.matcher (Pattern/compile " +") "String to be compacted ")
    (.replaceAll " ")
    (.trim ))
    You can use any Java class by importing it:
    (import (java.util.regex Pattern Matcher))

    Enjoy!

    ReplyDelete
  20. the Smalltalk solution relies on the method withBlanksCondensed, which does not exist e.g. in GNU Smalltalk. What I like of Smalltalk (and Objective-C on the compiled-lang side) is its ability to extend classes without the need of the source code of the class... in GNU Smalltalk, I can do

    'this is the string to be condensed' copyReplacingAllRegex: ' +' with: ' '.

    and if I like the withBlanksCondensed or I need to run code written using it for strings, I need just to add something like

    String extend [ withBlanksCondensed [ ^ self copyReplacingAllRegex: ' +' with: ' ' ] ].

    before its usage

    ReplyDelete
  21. Thanks for sharing this great article. It made me understand few things about this concept which I never knew before. Keep posting such great articles so that I gain from it. Java Training in Chennai | J2EE Training in Chennai | Advanced Java Training in Chennai | Core Java Training in Chennai | Java Training institute in Chennai

    ReplyDelete