From: Jason Mayer Date: 2006-12-28T05:08:38+09:00 Subject: Re: Handling of arbitrary length arrays in arguments to printf builtin ------=_Part_92372_19783078.1167250116565 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline On 12/27/06, 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 Blind leading the blind here, (I'm a newbie), but I think I understand what you're trying. Did I completely misunderstand or does this help? @params = ["foo", "bar"] print @params.inspect @params.each { |x| printf x } output: ["foo", "bar"]foobar @params = ["foo", "bar"] print @params.inspect printf("%s %s", @params, @params) output: ["foo", "bar"]foobar foobar ------=_Part_92372_19783078.1167250116565--