From: Nick Pavey Date: 2006-12-28T07:47:40+09:00 Subject: Re: Handling of arbitrary length arrays in arguments to printf builtin --Apple-Mail-17--25979594 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed Hi Everyone, Thanks very much for your fast responses - the "unary unarray" operator works great! Thanks also for the kind welcome you've given me - it makes a big difference. Best wishes, Nick On Dec 27, 2006, at 3:03 PM, Timothy Hunter wrote: > 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. -- Nick Pavey nick@skatingloons.com --Apple-Mail-17--25979594--