{ |one, step, back| } 151 to 160 of 180 articles WikiSyndicate: full/short

Unlimited Undo   10 Sep 03
[ print link all ]
Charles Miller writes about user interfaces and the trend to put up klunky dialog boxes to confirm "dangerous" actions. The dialogs rarely stop anyone from making a mistake. Folks will just click on them automatically without thinking about them. I know I do.

Charles writes: "Make your actions undo-able. Make your deletions un-deletable." Then the user always has the ability to undo any accidents that may have slipped past his fingers.

This is a great idea. I know that when I started using Emacs as my main editor, it changed the way I editted text. Emacs has an unlimited undo feature, where you can undo the file all the way back to the beginning of the edit session. Suddenly I was no longer afraid to try out new features in the editor. Sure, it might screw up the file, but savlation was only a few keystrokes away.

Let’s start a campaign to rid the world of those annoying confirmation queries!

"Using Ruby" Now Available   31 Aug 03
[ print link all ]
I did a presentation on using Ruby at work last week. It is meant to be a quick intro into using Ruby, targeted mainly at Java Programmers. The talk was constrained to one hour so there are a lot of things that got glossed over. I expect to update the talk as time goes on, so feedback is welcome.

You can find it here.

Feedback on Line Noise (and other stuff)   26 Aug 03
[ print link all ]
Wow, there were lots of responses to the LineNoise and PythonAndRuby postings last week. Here’s some of the feed back.

On Line Noise

First of all, let me remind everyone that a line noise score is for entertainment purposes only, and trying to derive something deep or serious about a language from its line noise score is counterproductive.

Brian Marick reminded me of a signature survey that Ward Cunningham had done. Ward throws out all but a few characters to generate a signature for a Java file. Surprisingly, you can tell a great deal about a file from the signature. Check it out here.

James Robertson wonders how Smalltalk would fare against the line noise filter. There is some question how to exactly count Smalltalk code, since there is no standard text representation for Smalltalk. I tried the fileout format from Squeak and removed all the extra puctuation that is added during fileout. Here is my results for Smalltalk …

  animal.st (45): :#:'':'':'':'':''.:#:'':'':'':'':''.:=:.:[:|]

James came up with a score of 35, but on his own source code running on a different version of Smalltalk. A lot of the Smalltalk score came from the class declarations, and if VisualWorks differs from Squeak significantly in the way classes are declared, that could easily account for the difference.

Ted Leung would like to see a larger sample. He suspects that the Ruby line noise ratio would be higher. Perhaps, but I haven’t seen it. From the very little research I’ve done, Ruby and Python get roughly the same line noise score on larger files.

On Python and Ruby Mindsets

Richard comments on the PythonAndRuby posting and complains about my characterization of the Python "." operator. He says

"x[y]" is a dictionary lookup. "x.y" is an attribute lookup that can have nothing at all to do with a dictionary.

He mentions that the __ getattr __ and __ getattribute __ hooks in Python may redirect the "." operator so that no actual dictionary is used. He suggests "attribute lookup" would be more accurate.

His terminology is probably more accurate, and I was delibrately glossing over the details. But the main point that Python programmers view the "." as some type of lookup is still very pertinent.

The Right Attitude

In the midst of all these Python and Ruby comparisons, I would like to wrap up with a posting from Mauricio Fernandez’s blog. Mauricio recounts a conversation with a stranger on a plane where they discuss design patterns and dynamic languages.

It was only much later that I remembered that he told me he was a Pythonist. This means (obviously) that we should have fought to death. Too bad we forgot it ;)

I like that attitude!

Thanks to everyone for the feedback.

Python and Ruby   22 Aug 03
[ print link all ]
Recently there has been a spat of Ruby VS Python threads, both in ruby-talk and in comp.lang.python. I don’t recommend reading the threads, they are repetive, filled with misunderstandings (from both sides) and more personal attacks than technical content.

However, one thing I have noticed is that Rubyists and Pythonistas bring different assumptions to the table. What is intuitive to one group seems ad hoc and downright weird to the other.

Here’s one example that I noticed.

In Python, the construct "x.y" means lookup the name "y" in the dictionary of "x". (Ok, that’s simplified, but you get the picture). The result of that lookup may be a value (instance data), or may be a function that can be called (member functions). In other words, "." is basically a lookup operation.

In Ruby, the construct "x.y" means send a message named "y" to the object represented by "x". All operations on an object must be done through the sending of a message.

This leads to all kinds of non-intuitive behavior if you are expecting the wrong thing. For example, one Pythonista commenting on the fact that "x.y" and "x.y()" are equivalent asks the question: "How do you get access to the y function inside x?".

A Rubyist’s response to the question is "Huh?". You see, there are no "functions" in Ruby. At least not in the way the question assumes. Ruby’s unit of execution is a method, and methods are not first class objects in Ruby. If you wish to have a callable object that references a method on a particular object, then that is easily accomplished by asking the object for a Method object.

  o = Object.new
  m = o.method(:to_s)
  m.class              # => Method

Note the difference between a method (an internal Ruby construct) and a Method object (an object that represents the internal method bound to an instance). To "call" a method object (or any callable object in Ruby), you send the object the "call" message. So, the result of calling m should be identical to the result of sending to_s to o directly. And we see that it is.

  m.call               # => "#<Object:0x401c8618>"
  o.to_s               # => "#<Object:0x401c8618>"

Although Python and Ruby are similar in many ways, their basis for computation is quite different in some fundamental ways. Python follows C++ and Java in using "." as a structure selector operation, while Ruby is more closely attuned to Smalltalk’s message sending paradigm. Both approaches work and are interally consistent, but be prepared for surprises if you try to interpret one using the assumptions of the other.

The Simplest Unit Test Framework That Could Possibly Work   22 Aug 03
[ print link all ]
I was helping a friend in C++ the other day. While I religiously use a test framework in my day to day work (e.g. JUnit for Java or Test::Unit for Ruby), I haven’t used C++ for over three years and didn’t have C++ Unit handy.

Then I remembered the C/C++ assert macro. We wrote a a series of small functions that looked something like this:

  void TestCanRun () {
      assert(   CanRun( ... ) );
      assert( ! CanRun( ... ) );
      // and so on ...
   }

I made a TestAll() function that called all my little test functions and arranged to have TestAll() called as the first thing in main(). If all the assertions worked, the program completed normally. If an assertion failed, the program would abort with an informative error message.

It worked great. I wouldn’t leave production code like that, but it was a great way to introduce Test Driven Design to someone who had not seen it before, without getting into all the nitty-gritty details of setting up a full blown test suite.

I guess my motto is that friends shouldn’t let friends program without tests.

Line Noise   22 Aug 03
[ print link all ]
There is a thread on the ruby-talk list on punctuation as noise. Hal Fulton wrote a short program to analyze the symbol to puncuation ratio of a program and then compared the results on several programs in different languages.

I did something similar a while back. A Java programmer had taken a look at Ruby and declare that he didn’t like all that "line noise" in the language. He was refering to the "@" and "$" characters used to mark instance variables and globals. I pointed out that Ruby actually uses quite a bit less punctuation than Java, and wrote the following linenoise program do demonstrate.

    #!/usr/bin/env ruby
    ARGV.each { |fn|
      noise = open(fn) { |file| file.read }.gsub(/[A-Za-z0-9_ \t\n]/m, "")
      puts "#{fn} (#{noise.size}): #{noise}"
    }

Linenoise will strip out all alphanumeric characters and white space, leaving only the "line noise" behind. Running linenoise on a series of small programs written in different languages produces this (edited slightly for line breaks) …

  animal.cc   (83):  #<>{:()=;};:{:();};::(){::<<"\";}:{:();};::(){::
                     <<"\";}(){*[]={,};(=;<;++)[]->();;}
  Animal.java (67):  {{();}{(){..("");}}{(){..("");}}([]){[]=[]{(),()}
                     ;(=;<.;++)[].();}}
  animal.pl   (41):  ;{{};}{"\";};{{};}{"\";};$(->,->){$->();}
  animal.py   (23):  :():"":():""[(),()]:.()
  animal.rb   (10):  """"[.,.].

The number in the paranthesis is the number of line noise characters in the file.

What I find interesting is the amount of semantic information that still comes through the "line noise". For example, the "#<>" sequence in the C++ code is obviously an include statement for something in the standard library and the "<<" are output statements using "cout".

It would be interesting to see if you could determine the language given only the line noise. You could tell Java from C++ by the ";}" vs ";};" punctuation. Python is pretty clear from the ’:():"":():’ style patterns.

Before I go, here is the source code to the Animal programs I used in my examples…

Language: C++

  #include <iostream>

  class Animal {
  public:
      virtual void talk() = 0;
  };

  class Dog : public Animal {
  public:
      virtual void talk();
  };

  void Dog::talk() {
      std::cout << "WOOF\n";
  }

  class Cat : public Animal {
  public:
      virtual void talk();
  };

  void Cat::talk() {
      std::cout << "MEOW\n";
  }

  int main() {
      Animal * (a[]) = { new Dog, new Cat };
      for (int i=0; i<2; i++)
          a[i]->talk();
      return 0;
  }

Language: Java

  public class Animal {
      interface IAnimal {
          void talk();
      }

      static class Dog implements IAnimal {
          public void talk () {
              System.out.println("WOOF");
          }
      }

      static class Cat implements IAnimal {
          public void talk() {
              System.out.println ("MEOW");
          }
      }

      public static void main (String args[]) {
          IAnimal[] zoo = new IAnimal[] { new Dog(), new Cat() };
          for (int i=0; i<zoo.length; i++)
             zoo[i].talk();
      }
  }

Language: Perl

  package Dog;

  sub new {
      bless {};
  }

  sub talk {
      print "WOOF\n";
  }

  package Cat;

  sub new {
      bless {};
  }

  sub talk {
      print "MEOW\n";
  }

  package main;

  for $a (Dog->new, Cat->new) {
      $a->talk();
  }

Language: Python

  class Dog:
      def talk(self):
          print "WOOF"

  class Cat:
      def talk(self):
          print "MEOW"

  for a in [Dog(), Cat()]:
      a.talk()

Language: Ruby

  class Dog
    def talk
      puts "WOOF"
    end
  end

  class Cat
    def talk
      puts "MEOW"
    end
  end

  for a in [Dog.new, Cat.new]
    a.talk
  end

Catch Curly Curly   19 Aug 03
[ print link all ]
Java’s checked exceptions are the type of thing that sound good at first glance, but have seriousl drawbacks in productions use. I was pleasantly surprised when Bruce Eckel echoed many of my observations in his checked exceptions essay. More recently, Anders Hejlsberg (the designer of the C# language) has weighed in with his opinions of Java’s checked exceptions.

Here are some quotes from the article

The throws clause […] requires you to either catch declared exceptions or put them in your own throws clause. To work around this requirement, people […] decorate every method with, "throws Exception." That just completely defeats the feature, and you just made the programmer write more gobbledy gunk. […]

Yep, that’s me. I use throws Exception a lot.

Anders goes on to comment that the focus is not generally on handling exceptions, but making your code robust in the presence of thrown exceptions. And that generally means finally blocks. He observers that …

In a well-written application there’s a ratio of ten to one, in my opinion, of try finally to try catch.

Interesting. I wonder how much duplication occurs in all those finally blocks. That’s why I like Ruby’s ability to abstract the finally (ensure in Ruby) to one location.

Finally, here’s where I got the title for this blog entry.

I can’t tell you how many times I’ve seen this — they say, "try, da da da da da, catch curly curly." They think, "Oh I’ll come back and deal with these empty catch clauses later," and then of course they never do.

I"m not guilty of the catch curly curly syndrome, but I’m not surprised that its a common problem. Bruce Eckel says it best when he calls Java’s checked exceptions a failed experiment.

You Say Potato, I Say Potahto   14 Aug 03
[ print link all ]
I came across a reference to the elastiC language in a blog entry by Hans Nowak. Hans starts out his blog entry with this …
elastiC. Quite an interesting language; Pythonic in many ways. At first glance, it seems to combine some good stuff from Python, Perl, Smalltalk, Lisp and C. …

Ok, sounds interesting. I always enjoy new languages. So I clicked over for a quick look at the elastiC site. With the exception of C-Like syntax and small footprint, the list of languages features were very reminiscent of Ruby. I did a quick scan of the language docs and it reminded me a lot of Objective-C, but I didn’t see anything to hold my interest.

As I return to Hans’ blog entry, I noticed his next sentence …

… Yet (again at first glance) it doesn’t seem as kludgy as Ruby.

What!? Ruby? Kludgy? Certainly not!

And yet, Hans seems to think so. Perhaps Hans has given Ruby the same quick once over that I just gave elastiC and didn’t see the unifying principles behind Ruby. If so, I can forgive him the slight.

And then again, maybe Hans just has different tastes in programming languages. After all, my daughter professes that GoldStar Chili is the best in the world, while I maintain that Skyline Chili has no peer — and we are able to live in the same house.

It sounds like Hans is a Gold Star type of guy.

That’s OK, because I going to continue eating at Skyline.

Kata Two Worked (continued) -- Call/CC   26 Jul 03
[ Kata print link all ]
Finally, here is the write up on continuations and callcc that I’ve been promising. This has been a hard one to write. I had the basics written up about the same time as the KataTwoNoTail article, but I felt it needed some refinement. In a lot of ways, writing about and explaining continuations is a lot harder than actually using them.

Recap

Pragmatic Dave is up to Kata number twelve, and I’m still writing about KataTwo. I have a feeling that I’m not going to catch up any time soon.

If you recall from earlier Kata writeups (see KataTwoCps and KataTwoNoTail for details), a continuation is merely the bit of code that needs to be executed after a method returns. We can manually capture continuations as Proc objects and explicitly pass them around.

A simple example is appropriate at this point. In the following factorial function, the result of the fact(n-1) call must be multiplied by n before returning a result. That multiplication is the continuation of the fact(n-1) call.

  def fact(n)
    if n == 0
      1
    else
      n * fact(n-1)
    end
  end

We can manually capture the continuation in a proc …

  proc { |res| n * res }

Once captured, we can pass the continuation code around. In particular, we can pass it to the fact(n-1) call and let it handle its own continuation (where done is the name of the continuation passed into us) …

    fact(n-1, proc{|res| done.call(n * res) })

Rewriting our factorial function to handle its own continuation yields code like this …

  def fact_cps(n, done)
    if n == 0
      done.call(1)
    else
      fact_cps(n-1, proc {|res| done.call(res * n) })
    end
  end

Call with Current Continuation

Our "simulated" continuations are just procs (i.e. anonymous functions). They don’t really cause the function to return when called, they only calculate the return value. We must still arrange for that return value to be properly returned up the calling chain.

Wouldn’t it be nice if we could "grab" the real continuation of the current function. It would act just like our simulated continuations, but when called, it will really cause the function to return immediately.

If we had a mechanism to "grab" that current continuation, we could write a method that looked like this …

  def call_with_current_continuation
    current_continuation = #{magic to get the current continuation}
    yield(current_continuation)
  end

call_with_current_continuation yields to a block, passing in the continuation for itself. If the block ever calls current_continuation, it will immediately return from call_with_current_continuation.

If we could actually write call_with_current_continuation, then code like this is possible.

  call_with_current_continuation { |current_continuation|
    puts "This will be printed"
    current_continuation.call            # [A]
    puts "This will never get printed"
  }
  # Line [A] returns to HERE

Calling current_continuation will cause the program to go to the continuation immediately. The output will look like this …

  This will be printed

and the second puts will never be executed.

Enter Call/CC

Although we don’t have any magic code that will return the current continuation of an arbitrary method, Ruby does provide the functionality of call_with_current_continuation in the form of the callcc method. The continuation is passed to a block, and within the block we can do anything we want to with the continuation. Calling it will immediately cause the callcc call that created the continuation to return the value given to the continuation.

A Simple Example

Here is a fairly pedestrian use of callcc. This use of callcc is similar to the setjump/longjump functions in the C libarary.

  def level3(cont)
    cont.call("RETURN THIS")
  end

  def level2(cont)
    level3(cont)
    return "NEVER RETURNED"
  end

  def top_level_function
    callcc { |cc|
      level2(cc)
    }
  end

  answer = top_level_function
  puts answer        # => "RETURN THIS"

Here we are using continuations to immediately return a value from top_level, even though we are nested 3 levels deep in method calls.

Although callcc can be used to create some really mind-bending control structures, we will stick to using it to return to a point of execution higher up in the call stack in the following examples.

Variation #6: Eliminating Tail Recursion

Starting with recursive CPS version (from KataTwoCps), we replace the proc based continuations with the continuations from callcc. There is only minor differences between the proc based and callcc based versions.

Code

  # Setup the call with the top level continuations.  Notice that we
  # create two continuations in this function.  The outer-most one
  # (+ret+) is the normal return.  The inner continuation (+failed+)
  # is designed to indicate failure by returning a -1 from the top
  # level function

  def chop_with_cc(target, list)
    callcc { |ret|
      callcc { |failed|
        sub_chop_with_cc(target, list, ret, failed)
      }
      -1
    }
  end

  # Recursive helper function with continuations explicitly passed in.

  def sub_chop_with_cc(target, list, found, not_found)
    if list.size <= 1
      (list[0] == target) ? found.call(0) : not_found.call
    else
      mid = list.size/2
      if list[mid] > target
        sub_chop_with_cc(
          target,
          list[0...mid],
          found,
          not_found)
      else
        found.call(
          mid + callcc { |cc|
            sub_chop_with_cc(
              target,
              list[mid..-1],
              cc,
              not_found)
          } )
      end
    end
  end

  class TestChopContinuations < Test::Unit::TestCase
    alias chop chop_with_cc
    include ChopTests
  end

Mixing callcc and proc Based Continuations

One final twist before we are done. In KataTwoCps we wrote sub_chop_recursive_with_cps in a continuation passing style, but using proc based continuations. What would happed if we passed real callcc based continuations to a function expecting proc based ones?

It turns out that it works perfectly. Here’s the test code for it …

  def chop_with_cc_and_cps(target, list)
    callcc { |ret|
      callcc { |failed|
        # This function is defined in KataTwoCps
        sub_chop_recursive_with_cps(target, list, ret, failed)
      }
      -1
    }
  end

  class TestChopContinuations2 < Test::Unit::TestCase
    alias chop chop_with_cc_and_cps
    include ChopTests
  end

Next Time

Only one more variation to go, and this time it has nothing to do with continuations.

No Fluff, Just Stuff (Sunday)   18 Jul 03
[ print link all ]
Its the final day of the Ohio Java Software Symposium, the No Fluff, Just Stuff conference. I must be getting tired because the notes are much sketchier today. But there was still lots of good stuff.

A Word on Organization

The Saturday writeup mentioned a mixup with Hotel venues before the conference and may have left an impression that the conference was unorganized. Quite the contrary. Everything was very well put together. Seminars started on time, ended (more or less) on time, and the break times always had cookies available. As far as I could tell, Jay Zimmerman ran the whole show with the help of one assistant, and did a very fine job. I was very impressed with the little touches. For example, the binders everyone got when they registered was personalized with their name on the front cover, and the summary of the conference schedule on the back.

You should also see ChadFowler's comments on the conference.

Building a Data Persistence Tier — Leveraging Object Relational Bridge (OJB) (John Carnell)

Sunday morning started out with a double session on the OJB Object/Relational mapping tool. OJB uses an XML mapping file to define the relationships between the object model and the relational database. I see the value in the O/R mapping, but it seems to me that the mapping file can be quite complex, and that worries me to some degree. XDoclet can probably help here, but then that’s yet another tool in the mix. (update: Ryan tells me he has download OJB and started looking at the tutorials and was very impressed with them).

John started out the session with an example of code that had a subtle JDBC bug. The code forget to close a prepared statement and the program would receive an "open cursor" error under heavy load. At the break, I couldn’t resist pointing out to John over the break that Dave’s Ruby talk showed how to address that problem in Ruby so it can’t happen by accident.

  • Cool Quote: Beware of refactoring through search and replace.

Lunch Time Quiz (Jay Zimmerman)

After lunch time, we played a little question and answer time with Jay giving prizes. Our table got a J2EE question, but unfortunately we had no J2EE experts sitting with us and we were clueless. Jay was nice enough to give us a second chance with a simpler question on ant. This time we got it right and won a pen.

The next game one where we guessed a phrase that was presented in a Wheel of Fortune style format. We tried to answer as Jay slowly filled in the letters. I actually won a Compuware polo shirt in this game. Great fun.

Applied Ant (Erik Hatcher)

I missed Erik’s intro to Ant, but did catch the follow on session. This talk mainly presented a bunch of different targets and goals that ant was capabile of handling (some with additional jar files).

Some things I came away with …

  • I really dislike reading XML, and especially dislike having to manually maintain XML files.
  • I use a small Ruby script called rake to do a lot of my builds. Although rake is not nearly as mature as ant, it is interesting to compare the design choices. Needless to say, rake does not use XML as input (rakefiles contain normal Ruby code).
  • Ant has a lot of really cool build targets that are well suited for Java development. It would be worth my time to study these (for rake enhancements).
  • Someone said that the native C/C++ compilation in ant is very nicely done. Ok, here’s another thing to look at in ant.

Agile Practices for Code Reuse (Maciej Zaawadzki)

Its getting late and I must confess that my information overload meter was in the red for the past two sessions. I only heard about half of what Maciej had to say. He has some good ideas in this area. I especially like his idea for a code station, a binary artifact repository. It sounds a bit like source control applied at a binary file (e.g. jar file) level.

The Conference Closes

Somehow for me, the end of a conference is rather anti-climatic. The last session is over and everyone just … walks out the door. It is a bit of a let down. But by Sunday afternoon, everyone was dead tired, and I know a couple folk left before the start of the final session.

Was the weekend worthwhile? Absolutely. Few technical conferences ever make it to Cincinnati, so I applaud Jay Zimmerman (the conference organizer) for bringing his road show to the "heartland". It really makes this kind of training more available to your average programmer. If a NoFluffJustStuff conference comes to a city near you, I strongly recommend that you grab everyone in your development organization and take advantage of the situation.

 

Formatted: 04-Jul-08 14:23
Feedback: jim@weirichhouse.org