Ruby’s Operator Expressions and Message Expressions using Operator Methods Yield Different Results

February 21st, 2008 by Koen

In pure object-oriented languages, such as Smalltalk, numerical and boolean expressions are expressed as message expressions. Non-pure object-oriented languages typically provide operators like +, -, *, /, &&, || to write numerical and boolean expressions, and they have precedence rules for operators, so that a numerical expression has the same semantics as in mathematics.

Interestingly, Ruby includes operators and some of them are implemented as methods, so-called operator methods. Let’s try some examples.

irb(main):001:0> 3 + 4 * 6
=> 27

That is what we expect. It shows that Ruby implements operator precedence. * has precedence over +.

* and + are implemented as operator methods. The pickaxe book states that: “If the operator in an operator expression corresponds to a redefinable method, Ruby will execute the operator expression expr1 operator expr2 as if it had been written (expr1).operator(expr2).” This means that the previous example can also be written as:

irb(main):002:0> 3.+(4).*(6)
=> 42

The result is what we expect. Messages are sent from left to right in an expression like this. The precedence rules do not apply when using the message passing form.

But according to the book, the two forms should yield the same result. They don’t.

Classes can implement operator methods as well, as shown in this example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Number
  def initialize(initialValue = 0)
    @value = initialValue
  end
  def  value
    @value
  end
  def +(other)
    self.class.new(self.value + other.value)
  end
  def *(other)
    self.class.new(self.value * other.value)
  end
end

Let’s try some expressions:

irb(main):003:0> (Number.new(3) + Number.new(4) * Number.new(6)).value
=> 27

This is consistent the precedence rules of the operators. When this expression is rewritten with messages, this is the result:

irb(main):004:0> Number.new(3).+(Number.new(4)).*(Number.new(6)).value
=> 42

Again, this shows that the precedence rules do not apply.

Although I expect that, consistent with other object-oriented languages, no precedence rules apply when messages are sent in sequence, Ruby states that using the operator form and the message passing form should be equivalent, but they clearly are not. That is very confusing and error-prone.

Distributed User Acceptance Test Session

January 25th, 2008 by Koen

Nick and I are working on a web application (of which we will blog later). Yesterday evening we organized the first user acceptance test session.
Instead of getting together in one location, we set up a distributed user acceptance test session, using web technology and tools. All participants were at home. We used Skype to set up a communication channel. Skype supports conference calls upto 5 people and that was enough for yesterday’s session. We used Google Docs to share a document where the participants could record issues, suggestions and new features. A Google spreadsheet allows multiple users to edit the spreadsheet simultaneously. It shows which cells are being edited, so that it is clear where another contributor should not change the document. And of course, the participants also opened the web application in a web browser.
When all participants were online with Skype and they had the spreadsheet and the web application open in their browsers, the session started. The conference call enabled us to have discussions about features and issues. The shared spreadsheet enabled us to quickly write down issues and suggestions. All the participants saw the changes to the spreadsheet and could immediately review what was written down. Often this gave rise to new discussions to clarify what was written down and it often resulted in short brainstorms about new features.
The session was fun. We had lively discussions and we laughed with ideas that built on other ideas about extra functionality. The feedback flowed easily into the spreadsheet. We had interesting discussions about end-user and technical aspects of the application. One participant’s girlfriend joined the conversation and gave very good feedback from an end-user standpoint.
From this session I learned that the right tools are available to set up distributed work sessions. I really enjoyed it and I hope to do it again soon. I like to thank the participants for their contribution. We owe them a beer.

Installing Ruby In Your Home Folder On Dreamhost

November 22nd, 2007 by Nick

I wanted to install a more recent ruby on my dreamhost hosting, with more recent gems then provided standard, so I decided to install ruby in my home directory. Below the steps I took to get it working. It worked out of the box for me, so now, I have full control over which exact gems and versions I use, independent of what dreamhost provides.

First, download the ruby tar ball:
wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6-p110.tar.gz
(note: be sure to check on the ruby site to get the latest stable sources, in the mean time, newer patchlevels might be available)

untar the tar ball:

tar -xvf ../ruby-1.8.6-p110.tar.gz

In your home folder, create a ruby directory to hold the installation:

mkdir ~/ruby

Change directory to the untarred directory. In that directory, run configure pointing to your local ruby directory:

./configure –prefix=/home/username/ruby

Then run:

make
make install

You now should have a ruby installation in /home/username/ruby.

In your home folder, edit your .bash_profile file and add the ruby bin folder to your path:

export PATH=”$HOME/ruby/bin:$PATH”

Source this file and run ruby -v

source ~/.bash_profile
ruby -v

SUCCESS:
ruby 1.8.6 (2007-09-23 patchlevel 110) [i686-linux]

Next, install ruby gem, the ruby package manager. Ruby gems can be found here

Get the latest version:

wget http://rubyforge.org/frs/download.php/28174/rubygems-0.9.5.tgz

untar:

tar -xvzf rubygems-0.9.5.tgz

cd rubygems-0.9.5

ruby setup.rb (note, be sure that you have your home backed ruby in your path!!)

Install rake:

gem install –remote rake

gem install fcgi

Do not forget to update the shebang in the dispatcher.fcgi file to the correct path

#!/home/username/ruby/bin/ruby

Then, install rails:

gem install rails

And you are rolling!!!

Note that in order to deploy in production mode, you need to uncomment the ENV[’RAILS_ENV’] ||= ‘production’ line in environment.rb.

Below the deployment recipe I used:


ssh_options[:paranoid] = false
set :user, 'user'
set :password, 'passwd'
set :application, "app"
set :repository, "http://url_to_svn_repository"
set :deploy_to, "/home/username/www.killerapp.com"

role :app, "www.killerapp.com"
role :web, "www.killerapp.com"
role :db, "www.killerdb.com", :primary => true

set :checkout, "export"

namespace :deploy do
desc "Restart the FCGI processes on the app server as a regular user."
task :restart, :roles => :app do
run "#{current_path}/script/process/reaper --dispatcher=dispatch.fcgi"
end

end

Thanks to Geoffrey Grosenbach for getting the inspiration for this recipe.

Hope this helps.

Multi-lingual site in Drupal

September 20th, 2007 by Nick

Some time ago a friend of mine asked if I could build a website for him. The requirements were simple: it had to be easy to add content for my non-technical savvy friend, the look and feel should be in line of his record store (he owns and runs 2 records stores specialized in jazz and classical music) and it had to be multilingual, Dutch, French and English. Last requirement was relatively cheap and easy hosting.

After some initial looking around on the web, I thought I’d give drupal a go. I was looking for an excuse to get to know some drupal basics anyway :)

In this post, I’ll describe how I’m setting up this site, especially the multilingual part. I’m still a complete drupal newby, so all suggestions are welcome.

So without further ado, this is what I did. I started with a fresh copy of drupal on the drupal site. I then installed and enabled the following modules:

  • Internationalization
  • CCK
  • Views

In the drupal handbook for the internationalization project, I found an elaborate how-to on getting the whole internationalization thing to work. Key things I learned where:

  • Menus: with the internationalization module, it is possible to have different menus for different languages. This is typically not what you want. You rather want one menu structure with text that changes if you switch languages. Therefor, use the “manage strings” functionality found in Administer -> Site Configuration -> Localization.
  • The menu items should link to node_name, not to en/node. The internationalization module will rewrite the link to en/node_name at runtime when you have the language set to English.
  • Nodes: Make sure to add a language to each individual node, this avoids an occasional piece of content in another language popping up.
  • Enable the path module under the core-optional family of modules. You will need to change the default path of a node to e.g. en/node_name for an English page.
  • Be sure to enable multilingual support for all content types you are using.
  • Do not forget to add the language switcher block to your site ;)

All in all setting up these basic things went smooth, I do have a couple of remarks/questions:

  • Is it possible to automatically set the correct path name e.g. en/node_name, rather then to have to do this manually for each individual node?
  • How can I theme/style the language switcher so that I only have the little flags, not the language name?
  • Are there other tips and tricks, obvious things or deeply hidden features I should be aware about?

All suggestions welcome, thanks in advance!

Transcending CSS

September 11th, 2007 by Koen

I read the book Transcending CSS and I am very impressed. It is not a book, like so many, that goes into all the details of CSS. Instead it is about design and creating beautiful things. And it also states that a web designer should look at the future (CSS3 for instance) instead of accepting the shortcomings of the (still) most popular browser.

I learned a lot from this book. In particular I learned how to build a web page from the content out: first write the content and then do the styling. I did some exercises to apply that way of working and the results are astonishing.

I recommend this book to everybody who likes to improve his/her web design skills.

Announcing JyDT 1.5.0

June 9th, 2007 by Koen

After nearly a year of inactivity, I found the time to add new functionality to JyDT, the Jython Development Tools for Eclipse. I added a PyUnit runner, very similar in look and feel to the JUnit runner. The screenshot below shows the PyUnit runner in action.

PyUnit Runner

At the time of writing, almost 75% of the functionality is ready. I expect to release the PyUnit runner by the end of the month, as part of JyDT 1.5.0.

Ruby’s “private”: not as Private as You Expect

April 24th, 2007 by Koen

I expect that, if a language borrows a concept from another language, and if that language even uses the same name for the concept, the concept also has the same semantics. That is not the case for “private” access control in Ruby.

In Java and C++, the sematics of the “private” access modifier for a method is: the method can only be called by methods of the class that declares the private method.

In Ruby, the semantics is (taken from the pickaxe book, page 35): private methods can be called only in the context of the current object. A bit further in the book: The difference between “protected” and “private” is fairly subtle and is different in Ruby than in most common OO languages.

Indeed, the difference is subtle, certainly for C++ and Java developers learning Ruby. As the sematics above already indicate, C++ and Java have a class focus, while Ruby has an instance focus. Private in C++ and Java means: private to the class. In Ruby, it means: private to the instance.

There is another aspect of the semantics that is important. In C++ and Java, a private method can be called on a different instance than the one executing the current method. In Ruby, private methods can only be invoked on the same instance, which is enforced syntactically: private methods can only be invoked without a receiver or with self.

Because in Ruby private methods are private to an instance, they can be invoked by methods in a subclass, illustrated by the following code snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Superclass
    private
        def m1()
            puts "Superclass.m1"
        end
end
 
class Subclass < Superclass
    public
        def m2()
            m1()
            puts "Subclass.m2"
        end
end
 
Subclass.new().m2()

The output of the program is:

irb(main):017:0> Subclass.new().m2()
Superclass.m1
Subclass.m2
=> nil

Private methods can also be overridden, as shown in this code snippet:

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Superclass
    private
        def m()
            puts "Superclass.m"
        end
end
 
class Subclass < Superclass
    public
        def m()
            super()
            puts "Subclass.m"
        end
end
 
Subclass.new.m()

The output of the program is:

irb(main):017:0> Subclass.new.m()
Superclass.m
Subclass.m
=> nil

A singleton method can even override a private method of the class of the instance, as illustrated by this code snippet:

33
34
35
36
37
38
39
40
41
42
43
44
45
class MyClass
    private
        def m()
            puts "MyClass.m"
        end
end
 
object = MyClass.new()
def object.m()
    super()
    puts "object.m"
end
object.m()

The output of the program is:

irb(main):013:0> object.m()
MyClass.m
object.m
=> nil

The conclusion is that Ruby has no way to make methods private in the C++ and Java sense. In my opinion, that is a good thing, because private methods are bad for reusability. But I do not believe that using the word “private” was a good choice.

Stacked Bar Graph in Rails

April 21st, 2007 by Nick

A while ago, I stumbled upon some nice ccs-graphs that did precisely what I needed at work. I wanted to show the evolution of some stats over time, in stacked-bar format. After some googling, I found a simple rails helper for css graphs. I needed some more stuff, but is was definitely a very good starting point.

The final graph I wanted to have looks something like this:

  • 38
  • 29
  • 36
  • 28
  • 34
  • 27
  • 32
  • 26
  • 30
  • 25
  • 28
  • 24
  • 26
  • 23
  • 24
  • 22
  • 22
  • 21
  • 20
  • 20

Read the rest of this entry »

Simplicity, Consistency, Expressiveness and Elegance of Ruby

April 15th, 2007 by Koen

I have grown up as a software developer with Smalltalk and other non-statically typed programming languages like Python and Scheme. I even took part in the development of a prototype-based language called Agora.

Now that Ruby is taking off, and after Nick showed me how to create a small Ruby on Rails application in no time, I am intrigued by the language. I am intrigued because the inventors of Ruby claim to have used some concepts from Smalltalk and I know the ins and outs of Smalltalk fairly well. I am also intrigued because the little time I spent coding the RoR application showed me two things: (1) creating a RoR application requires little real programming, and (2) from the first line of Ruby code I was struck by the ad hoc nature of some Ruby language constructs.

When I learn a new language, I look for qualities such as simplicity, consistency, expressiveness and elegance, qualities that influence my productivity when coding. This post is the first in a row of articles on Ruby to explore how well Ruby scores on these qualities.

Watch this space.

April 4th, 2007 by Nick

Watch this space for occasional postings on different aspects of coding, rails and ruby, python and miscellaneous thoughts on agile in the corporate world.


Close
E-mail It
Socialized through Gregarious 42