Posts about smalltalk

Null in 10 Languages

  • Java, Javascript, C#: null
  • Ruby, Smalltalk, Lisp, OCaml: nil
  • Lisp: ()
  • Python: None
  • Haskell: Nothing
  • C: 0
Posted by Toby 10 months ago about c, c#, haskell, java, javascript, lisp, ocaml, programming, python, ruby and smalltalk (0 comments)

How Safe is Your Programming Language

First, let me define what I mean by safe: the earlier a programming language catches a programming error for you, the safer it is. Haskell is extremely safe, whereas php is extremely unsafe. Some examples:
  • Errors can be caught at compile time, such as mispelling of function names
  • Errors can be caught at runtime, such as NullPointerExceptions, but it may be caught early or later in runtime, there's a continum
  • Errors can be caught a type time if you have a method completion capable IDE, for exmple
  • Errors can be caught a unit test time, but that out of the scope for this article, because I want to talk about languages and not testing practices
  • Errors can be caught at QA testing time vs in production, these are also a bit out of scope
How do you measure the safety of a programming language? One can take specfic classes of errors and see how and when a language catches them. I will use the notation >> to mean safer than. A score is given for each language for each type of error corresponding to how safe they are.

Null Pointers
  • Java, Ruby, Python, C#, Smalltalk, Javascript, LISP - catch at runtime when you try to derefernce the pointer
  • C, C++ - never catches it, they merely core dump, which does not tell you what the specific error was
  • Haskell, OCaml - catches it at compile time, because you cannot have Null values unless you specifically define it in the type, and the compiler requires you to handle the null case
    So in this case: Haskell, OCaml (2) >> Java, Ruby, Python, C#, Smalltalk, Javascript, LISP (1) >> C, C++ (0)

Array Index Out Of Bounds
  • Java, Python, C#, Smalltalk - catch at runtime when you try to index the array
  • Ruby, Javascript - never catches it, merely returns null if you try to index an array with an out of bounds index
  • C, C++ - never catches it, may or may not core dump.
  • Haskell, LISP, OCaml - although you can use Arrays if you really want/need to, in which case the error is caught at runtime like Java, etc. The prefered practice of these languages is to use linked-lists instead, which will never have index out of bounds errors
    So: Haskell, LISP, OCaml (2) >> Java, Python, C#, Smalltalk (1) >> Ruby, Javascript, C, C++ (0)

Type Errors
  • Java, C# - these are caught at compile time if you never use casting in your program. But if you do use casting, these will be caught at runtime as ClassCastExceptions at time of cast.
  • Ruby, Python, Javascript, Smalltalk, LISP - caught at runtime when a method on the object is accessed
  • C, C++ - Compile time if you don't use casting. Never caught and possible core dumps if you do.
  • Haskell, OCaml - Compile time always, casting is not allowed.
    Haskell, OCaml (3) >> Java, C# (2) >> Ruby, Python, Javascript, Smalltalk, LISP (1) >> C, C++ (0)

Mispelled Named Parameters
  • Java, C#, C, C++, Haskell, Javascript - these languages do not have this feature
  • Python, Smalltalk - caught at time of method invocation
  • Ruby - rubists employ a poor-man's named parameters by just passing in a Hash to methods, the languages supports syntactic sugar that make this style of method calling look like named parameters, but mispelled keys are never caught
  • OCaml - caught at compile time
    OCaml (2) >> Python, Smalltalk (1) >> Ruby (0)

Wrong Number of Parameters
  • Python, Smalltalk, LISP - caught at method invocation
  • Javascript - never caught, unsupplied parameters an simple set to null, and it never hurts to use too many parameters
  • Ruby - caught at method invocation time for the normal cases, but blocks are a special type of parameter which is always optional. So if you supply a block to a method that does not require it, ruby does not complain
  • Haskell, Java, C#, C, C++ - compile time
    Haskell, OCaml, Java, C#, C, C++ (3) >> Python, Smalltalk, LISP (2) >> Ruby (1) >> Javascript (0)

So a language can be safer or less safe under different contexts. There obviously are other types of errors that I have not listed, but this will do for a simple comparison. I've already given scores for each language for each error type. Since some languages do not have the named parameters feature, I will average the score for each language over the error types that are relevant to it. So the Tally is:
  1. Haskell - scores: [2, 2, 3, 3], average: 2.5
  2. OCaml - scores: [2,2,3,2,3], average: 2.4
  3. Java, C# - scores: [1,1,2,3], average: 1.75
  4. LISP - scores: [1,2,1,2], average: 1.5
  5. Python, Smalltalk - scores: [1,1,1,1,2], average: 1.2
  6. C, C++ - scores: [0,0,0,3], average: 0.75
  7. Ruby - scores: [1,0,1,0,1], average: 0.6
  8. Javascript - [1,0,1,0], average: 0.5
It's not really fair that OCaml is scoring lower than Haskell, they should be the same, the difference is because Haskell doesn't have named parameters so the average is skewed - my scoring system is not perfect. Haskell is safer than OCaml in one aspect though. Which is that in Haskell, purely functional code is guaranteed to have no side effects and will never throw exceptions.
Posted by Toby about 1 year ago about c, c#, haskell, java, javascript, lisp, ocaml, programming, python, ruby and smalltalk (0 comments)

Debugger Support Considered Harmful

Yum! I love Ruby vs Smalltalk flame wars. This one is about whether TDD renders debuggers useless. Giles Bowkett of Ruby vs James Robertson of Smalltalk. I would have to talk James' side here. Although great TDD/BDD can remove the need for the debugger, it's not easy to do great TDD/BDD. It's an art, and takes a good amount of commitment and effort to do, as well as training(I am sure I still don't know the best ways to test in some situations). Basically, TDD is something you have to go out of your way in order to do well, and to say that everyone should do great TDD is a bit like forcing a religion down someone's throat. I think I do OK TDD/BDD. I don't use the debugger on Ruby projects, but would I use it if there were a good one? Yes.
Posted by Toby over 2 years ago about programming, ruby and smalltalk (0 comments)

Meta-programmming in Ruby vs Smalltalk

Stumbled into Neal Ford's post today which spawn off several other blog posts else where too, including Avi Bryant's new blog. How timely(this was actually one month ago)! I was just musing about this very thing and that's how I found the this blog post. Smalltalk has an adventage over Ruby(an pretty much any other language) because the runtime is always running. Runtime = development time = compile time. This allows for a lot of introspection to occur during development. Things like code completion, for example, are done by inspecting the objects in the runtime, rather than by inspecting the source code like in modern Java IDEs. Of course it can do more than that: things like excuting arbitrary code when you are at a breakpoint, to give another example. You could also query the system for the object class hierarchies to do anything you want with them, including creating new classes and methods on the fly.

Now, one thing about the Ruby metaprogramming techniques some complain about is the fact that they are hard to debug, because you can't see the code that you are executing. In contrast, you can get the source code to any method during runtime, which means you can easily debug through it(yes, but aside from that, debugging in Ruby still sucks anyway). It's the explicit vs implicit thing again. But the advantage of the Ruby approach is that it's more dry - you specify the declaration once, and that's it, the code that's generated is never seen anywhere, it removes the issue that all code generating tools have: that there's a versioning problem between the generated code and the spec that feeds into the generator.

Which way is better? Clearly(how can you argue with "clearly"? you can't), neither one is. Is there a best of both worlds? Hard to say.

It's worth pointing out that Ruby metaprogramming techniques are a very new development. Although it has it's roots in LISP, I think it is a new twist in the ways it is used in the context of OOP. Can these techniques be applicable to other languages? Yes, they are being adopted in many other languages, including Groovy, Python, and Javascript. Also, these techniques are usually used in programming frameworks, in which the ultimate end-user interface is a programming API. And, thus, the goal of all(most?) of these techniques is to automatically generate code that a developer writes code against. From a single programmer's perspective, these are just refactoring techniques, or design patterns, because they don't really give you anything you didn't have before in terms of what you can do(power?), but rather lets you structure your code in a way that's even more dry than what was possible before. As a result you can create very consice APIs with very little code.

Going back to the ActiveRecord has_many example, some have mentioned that this can be done without using code generation. In Smalltalk, apparently this is done by using an annotation. The class code can then presumably query the annotation information when it needs to get an association, I assume using something like method_missing(I'll have to check this), which you could do the exact same thing in Ruby, only in place of the annotation you'd still have the class initializer. In deed, that is how Hibernate does it for Java as well. So why do the Ruby guys like to use code generation in that case? It's just their style! If someone develops a new kung fu style that kicks your ass, are you going to say he's doing it wrong? Also, in Ruby method_missing is slow, so there's an incentive to avoid it.
Posted by Toby over 2 years ago about programming, ruby and smalltalk (0 comments)