From: Timothy Hunter Date: 2006-12-28T05:03:03+09:00 Subject: Re: Handling of arbitrary length arrays in arguments to printf builtin Nick Pavey wrote: > Hi Folks, > > I'm porting an error reporting system from Perl to Ruby as a way of > getting up the Ruby learning curve. Apologies in advance if my > question has already been answered - I did a cursory search and got no > hits. > > I'm running up against my lack of detailed Ruby knowledge, and I was > wondering if someone could provide some advice - I'm sure that Ruby > supports what I want to do. > > In the Perl world, I had a system where I could specify an error > message and a set of parameters to that message, as follows: > > do_error(message, [parameters]); > > for example: > > do_error("param 1: '%s', param 2 : '%s', param 3 : '%s'", > "detail1", "detail2", "detail3"); > > would give the result: > > param 1: 'detail1', param 2 : 'detail2', param 3 : 'detail3' > > The perl implementation looks like this: > > sub do_error { > my ($message, @params) = @_; > > printf($message, @params); > } > > As you can see, the idea is that the user is able to specify both > their error message and where in their message string various > parameters appear. > > In this case, Perl was very obliging because parameter lists are > simply arrays. Passing an array into printf became equivalent to > passing the appropriate number of parameters. > > So, in Ruby, I have the following code: > > printf "#{@message}\n", @params > > Where class instance variable @params is an array. I have verified > that it really is an array and not getting mangled somewhere in my > class by using '@params.inspect'. > > Unfortunately, it seems that Ruby is treating the array in what Perl > folks would call a "scalar context". The printf is getting a mangled > version of the array contents and this is triggering a runtime error > from Ruby. > > For example: > > @params = ["foo", "bar"] > print @params.inspect > >>> ["foo", "bar"] > > printf("%s %s", @params) > >>> ErrorClasses.rb:32:in `printf': too few arguments (ArgumentError) > > I did some experiments, and it appears that printf is actually seeing: > "foobar" > instead of the array of 2 elements. If I have the right number of '%s' > conversion codes in the format string, I get this message because Ruby > thinks I've only passed on parameter, not many. > > For the record, here's the Ruby version I'm using > > BigWhite:nick> ruby -v > ruby 1.8.4 (2005-12-24) [i686-darwin8.8.1] > > > What would Ruby's code look like to achieve what I want? > > Thanks in advance, > > > Nick > > > > Welcome to Ruby! Use the "*" (splat) operator to turn the array into a list of arguments. printf "%s %s", *@params The unary asterisk is often called the "unary unarray" operator because it has this effect on an array.