6th - 12th June 2005

Ruby Weekly News is a summary of the week’s activity on the ruby-talk mailing list / the comp.lang.ruby newsgroup, brought to you by Tim Sutherland.

Articles and Announcements

Quote of the Week

Link of the Week

    Lambda the Ultimate, http://lambda-the-ultimate.org/. “The Programming Languages Weblog”.

    Lots of interesting posts, if you’re into that programming language junk ;-)

Threads

duck-typing allows deeper polymorphism

Eric Mahurin posted the advantages he sees of duck-typing over “conventional polymorphism”.

See also the making a duck thread from earlier in the week.

text to images using RMagick

Nick Hayworth wanted to convert a string to an image using RMagick, automatically wrapping at a certain number of pixels.

He already had this working using the convert utility that comes with ImageMagick.
convert -size 200x -font Tahoma -pointsize 20 caption:"My very long caption
which should wrap at 200 pixels" output.gif 

Timothy Hunter released a new version of RMagick (version 1.8.2) and announced that it was indeed possible ;-)

The following code will do it:
require 'RMagick'
include Magick

img = Image.read("caption:My very long caption which should wrap at 200
  pixels") do

  self.size = "200x" 
  self.pointsize = 20
  self.font = "Tahoma" 
end

img[0].display 

Ruby/LDAP on Windows

gregarican was having trouble building Ruby/LDAP on Windows. extconf.rb was complaining that it couldn’t find ‘ldap.h’, ‘lber.h’ or ‘ldap_ssl.h’.

The headers were under ‘c:\openldap-2.2.26’, and gregarican had tried passing in arguments such as --with-ldap-dir="c:\\openldap-2.2.26".

There weren’t yet any replies.

Perhaps using ’—with-ldap-incdir’ to point directly to the header directory may help?

finding Hash subsets based on key value

ee began, “Is there a simple way of searching the keys of a Hash to find a subset. I have a set of keys with two values indicating group and sub-group”, for example “group_1_item_1”, “group_1_item_2”, “group_2_item_2”.

“I’d like to divide them into groups, but without having to loop through the entire collection and having to test each key”.

Martin DeMello said that it isn’t possible to solve this problem without testing each key, but gave a single line using Enumerable#partition that otherwise met the criteria.

“Enumerable#partition divides your collection into two parts, based on whether the block returns true or false, so it doesn’t scale to more than two subsets, but for your example it should work nicely.”

Robert Klemme thought that perhaps we should have a Enumerable#general_partition method that partitions into “several buckets and not just two.” He gave a sample implementation.

James Edward Gray II popped in with the best answer: The standard Set#classify. It can be used as follows,

require 'set'

items = Set[
  'group_1_item_1',
  'group_2_item_2',
  'group_1_item_2',
  'group_1_item_4',
  'group_2_item_3',
]

groups = items.classify { |name|
  name[/^group_\d+/]
}

p(groups)
# { "group_2" => #<Set: {"group_2_item_2", "group_2_item_3"}>,
#   "group_1" => #<Set: {"group_1_item_1", "group_1_item_2", "group_1_item_4"}> }
Set#classify groups items by whatever the block returns for them - in this case the prefix of each item.

problem matching accented chars on OS X

Alex Fenton wrote: “I’m finding words within strings in Western European languages, so I need to account for accented characters, such as ê (e circumflex) and à (a grave).”

He can match them in reguar expressions by including ”\xC0” and so on in the expression – the hex representation of characters in the iso-8859-1 encoding.

This works on Windows, but when he tries to run the same code on Mac OS X, he gets an error about “mismatch multibyte code length in char-class range”.

Axel (now that’s confusing!) replied, saying that a regular expression such as /abc/U can be used to specify that the expression is encoded in UTF-8.

Other character sets, such as EUC and SJIS are supported in a similar way.

Axel later added that the Oniguruma regular expression library supports more encodings. It is the standard engine in Ruby 1.9.

Persistence of Ruby sessions/programs

Renzo Orsini: “I know there are several ways of saving ruby objects on files, but there is a simple way of saving ALL the state of a Ruby program execution (or an irb work session) and then reload it in another execution (or session)?”

gabriele renzi said that a “hackish” solution would be to store the source you entered in irb and eval it back later. “Saving the state of the program would be hard since you can’t serialize closures, singletons and continuations”.

Renzo Orsini noted that he would be “happy just to save classes, objects and global variables that I have defined, or a subset of them, but it seems to me that with Marshal.dump I cannot even save a class”.

Array#nitems and Object#nil?

Matz re-discovered a March post from Bertram Scharpf that proposed adding a block to Array#nitems.

“Today, I happened to re-discover this mail, and found it reasonable. Array#nitems will be able to take a block to count items specified by the block (CVS HEAD).”

python/ruby benchmark

</script> (yes, that was the name) took a look at ‘The Computer Language Shootout Benchmarks’ page comparing the performance of Ruby and Python in various micro-benchmarks. To his disappointment, Python performed better. “So what I’m asking for is a link to some ruby-specific optimisation tips.”

Various people commented that such benchmarks do not mean that Ruby is slow in real-life programs. Austin Ziegler said “At any rate, I consider the Alioth shootout to be harmful to all languages involved. There is no useful value provided by it, especially as it does not permit language-appropriate modifications to the algorithms in use.” Austin also called the benchmarks “bogus”, and some other, less polite, things.

Phil Tomson said that this was blaming the messenger. “If we keep telling ourselves that Ruby is ‘fast enough’ for our application (and it may well be) are we going to be sitting still while other languages improve performance?”

The (sometimes hostile) thread continued for over 60 posts.

Rails on Altix ia64

Adam P. Jenkins was getting “[BUG] Segmentation fault” messages when running Ruby on an Altix IA64.

Tanaka Akira posted a patch which solved Adam’s problem, but noted that issues on IA64 still exist. (Particularly around the way the GC interacts with registers.)

blocks, scope/context confusion

Corey, learning Ruby from PickAxe2, was having trouble in the section on blocks.

“What’s the difference between the two methods below?”

def meth1
  yield
end

def meth2(&b)
  b.call
end
He also asked why meth { return 99 } throws a LocalJumpError. To the last question, Matz said the error was because even the bare return 99 at the top-level causes an exception. He suggesting Corey try
def foo
  meth1 { return 99 }
end
p foo
For the other questions, Gary Wright said that yield and b.call were equivalent. “The first example is syntactic sugar for the second example.” He noted an implementation difference in them; the former is slightly more efficient.

Devin Mullins gave a link to an article on “closures” (another name for blocks).

Could Ruby-doc be better? -- Proposal for a better system

Andrew Thompson thought that ruby-doc.org could use some inspiration from the PHP manual.

“My basic plan is to have a php style manual http://www.php.net/manual/en/ generated from the rdoc comments, with the ability to have the documentation maintained in a wiki based fashion, and have user comments along the lines of the PHP manual. This way we lower the barrier to writing documentation, allow users to comment with code samples or additional info, and hopefully increase and improve the amount of documentation ruby has.”

framework of Ruby/Tk + VNC

Hidetoshi NAGAI announced that he is working on a framework utilising Ruby/Tk and VNC. “Its purpose is to put GUI applications of Ruby/Tk on internet view”, running “on a safe (safe-Tk) based slave interpreter”.

VNC connects to a Tk canvas, with no external window manager. “In the future, it may be expected that Ruby/Tk has RFB server functions and no VNC server is required for this purpose.” (RFB = Remote FrameBuffer.)

He compared this scheme with using the tclplugin web browser plugin to run the Tk client on the user’s computer.

Getting a method object directly from a module

Daniel Berger asked how he could extract a method from a module.
module Foo
  def my_method
  end
end

method = Foo.method(:my_method)
=> NameError: undefined method `my_method' for class `Module'
Matz:
Foo.instance_method(:my_method).bind(obj).call 

Chess Variants (I) (#35)

James Edward Gray II posted this week’s Ruby Quiz. It is reminiscent of the idea behind the 2005 ICFP Functional Programming Contest.

“One of the greatest challenges in programming is modular design. Building code that adapts well to change is a Holy Grail quest for most of us. This two-part Ruby Quiz is designed to put your ability to predict the future to the test.”

The first part of the problem is to build an engine for two player chess.

There is no need to create AI or other features, “just a board and piece interface players can use for games. The game should prevent illegal moves, make sure the right player moves at the right time, declare a winner when a game ends, etc.”

“Next week, in part two of this quiz, I will provide a list of chess variants you are expected to modify your program to support.”

(Aha! The twist.)

Can't see the ground 'cause my chest is so puffed out!

Timothy Hunter:

Following the Rails Day links from /. I was immeasureably pleased to discover that at least 2 Rails Day qualifiers (http://railsday.com/svn/qualifiers) used RMagick!

You might guess that Timothy is the creator of RMagick, the Ruby bindings for the ImageMagick and GraphicsMagick image manipulation libraries.

FXRuby 1.2 with Fox 1.4?

Tom Nakamura knew that FXRuby 1.2 was designed to work with Fox 1.2, but wondered whether it would work with Fox 1.4, since “There’s no FXRuby 1.4 yet”.

Lothar Scholz said that it wouldn’t work, since Fox 1.4 changes the names of many methods in an effort to make them more consistent.

A little Quiz

Dominik Bathon wrote some code that uses method_missing for an unspecified purpose, and challenged the group to figure out what it does.

Later … “As James Britt already figured out, it lets you call one method on all elements of an Array. If no block is given this works like collect.”

Instead of

[-1, -2, -3].collect { |x| x.abs }
=> [1, 2, 3]

you can just write

[-1, -2, -3].abs
=> [1, 2, 3]

Since #abs is not part of the Array interface, method_missing is  
triggered. But it does more than collect, it even works on nested Arrays:

[[-1,-2],[-3,4],-2,5].abs
=> [[1, 2], [3, 4], 2, 5] 

get username of file owner?

John Fry wanted to find the username of whoever owned a particular file. He could get the uid with File.stat("testfile").uid, but how might he retrieve a username such as “smith” instead?

Fredrik Fornwall showed how to use the ‘etc’ library to convert a uid to a username:

require 'etc'
uid = File.stat('testfile').uid
puts 'Owner name: ', Etc.getpwuid(uid).name

Gambit Codefest Postmortem

James Edward Gray II,

We’ve just completed nine solid days of development on Gambit. Now that’s a “Codefest” alright! I thought I would share a little with the curious about how I think it went…

Greg Brown flew out to my home in Oklahoma so we could work on Gambit. It was nice to finally meet face-to-face. We’ve actually programmed together on many projects these last couple of years, but this was the first time we didn’t do it over the Internet. We’re both grateful to the wonderful people at Ruby Central for giving us that opportunity.

Which brings us to what we built. Some of you have expressed interest in Gambit and I’m sure you would like to hear how it came out. The short story is, very good. We met and even exceeded our expectations in many areas.

The longer story: We’ve built a very hand model layer for common game elements like Boards, Cards, and Dice. This is probably our most polished work and has been a real asset to our internal development already.

... with lots and lots of unit tests.

how to extract url's from html source of google search result

sujeet kumar was able to retrieve HTML from a website using Ruby, but was stuck at the next point: how to extract URLs out of the result.

Marcel Molina Jr. suggested the URI.extract method from the ‘uri’ library.
require 'uri'
URI.extract('My favorite site is http://google.com')
# => ["http://google.com"] 

“An optional second argument can limit the schemes that it will match against and return” so, for example, you can tell it only to retrieve ‘http’ links and not ‘mailto’ etc.

Alexey Verkhovsky thought that URI.extract was potentially troublesome because it is implemented using a regular expression – “it can produce false positives (finding things that look like URIs, but aren’t)”.

“If you are sure that the page is a well-formed XHTML (I’m not sure if that’s the case or not with Google), you might instead parse it with REXML, and use XPath to retrieve href attributes of all <a>..</a> elements, selecting only those that start with “http://” (there may also be mailto:, ftp:, JavaScript calls etc).”

As an entirely different solution, Eric Hodel asked why the original poster didn’t juse use the Google API (web-service).

Accessing SVN through Ruby/DL

Jim Morris was wandering through an old thread which discussed the merits of binding Subversion through SWIG or Ruby/DL.

“I cobbled together the following to see how hard it would be to do this in DL.”

“I hope this can be added to the samples, as it involves callbacks, structures and pointer types.”

Takaaki Tateishi thanked him, and added the sample program to the DLCookbook project.

New Releases

Tiddy 0.0.4

Dr Balwinder S Dheeman updated Tiddy, a program for re-formatting Ruby source code. (And Ada, C, C++, Java, C#, Perl, ...)

See also Tiddy 0.0.3-pre3 is released.

FireRuby 0.3.1

Peter Wood enhanced the Connection class in FireRuby 0.3.1, the bindings to the Firebird RDBMS.

It now rolls back outstanding transactions whenever the close method is called.

Ruby Month 0.1.0

Francis Hwang, from “out of murky depths of the Lafcadio codebase”, released a utility library called Ruby Month.

It is used, unsurprisingly, to make it easier to manipulate months.

constraint 0.1 -- ensure that object always satisfy a specified set of constraints

Thomas announced the “first draft” of ‘constraint’, a library that assists in adding constraints to objects. In particular, it is used to implement typed collections.

Ruby/Odeum 0.4: ResultSets, KirbyBase Demo

Zed A. Shaw announced Ruby/Odeum 0.4, a binding to the QDBM Odeum full-text search engine.

This release is 15-20% faster than the last, and includes a KirbyBase wrapper that “indexes records on the fly and allows you to do full text search for them”.

RDoc Dashboard Widget

David Felstead created an RDoc Dashboard widget for Mac OS X Tiger. It reads any RDoc repository and “lets you check your documentation without having to open a Safari/Firefox window.”

“I’m also working on an IRB widget which should be done shortly, if anyone’s interested.”

Gavin Kistner: “Hot damn, that’s awesome! Just what I was looking for and thinking of when Tiger came out.”

ruby2c 1.0.0 beta 3

Ryan Davis released the third beta of ruby2c 1.0.0.

Ruby2C provides a pipeline of SexpProcessor classes to work with  
ParseTree output. Processors included:

Rewriter    - massages the sexp into a more consistent form.
TypeChecker - type inferencer for the above sexps.
RubyToC     - converts a ruby (subset) sexp to C.