[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: Handling of arbitrary length arrays in arguments to printf builtin

Tim Hunter

12/27/2006 8:03:00 PM

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.

7 Answers

Mat Schaffer

12/27/2006 8:36:00 PM

0


On Dec 27, 2006, at 3:17 PM, Jason Mayer wrote:
> Neat! How would you use that to return "bar stuff" with the
> following?
>
> @params = ["foo", "bar", "stuff"]
> print @params.inspect
> printf "%s %s", *@params

irb(main):015:0> printf "%s %s", *@params[1..-1]
bar stuff=> nil

ain't it cool? :)
-Mat

Paulo Köch

12/27/2006 8:38:00 PM

0

I guess you'll have to select the elements from the array.

AFAIK, the Array#* in only used to pack and unpack arrays into
argument lists (and other kinds of lists).
For example:

def multiple_returns
1, 2, 3, 4
end

a = multiple_returns # a=1
a, b = multiple_returns # a=1, b = 2
a, *b = multiple_returns # a=1, b = [2,3,4]

Hope you'll get less n00b =P

cheers!

On 12/27/06, Jason Mayer <slamboy@gmail.com> wrote:
> On 12/27/06, Timothy Hunter <TimHunter@nc.rr.com> wrote:
> >
> > 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.
>
>
> Neat! How would you use that to return "bar stuff" with the following?
>
> @params = ["foo", "bar", "stuff"]
> print @params.inspect
> printf "%s %s", *@params
>
> I'm not sure that Ri Array#* is quite what I meant to look for.
>
>

Tim Hunter

12/27/2006 8:42:00 PM

0

Jason Mayer wrote:
> On 12/27/06, Timothy Hunter <TimHunter@nc.rr.com> wrote:
>>
>> Welcoingme 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.
>
>
> Neat! How would you use that to return "bar stuff" with the following?
>
> @params = ["foo", "bar", "stuff"]
> print @params.inspect
> printf "%s %s", *@params

You can't. That's not what "*" is for. The "unary unarray" operator is
primarily used for exactly the purpose you described, variable-length
argument lists. It has uses in other contexts, too, but they're outside
the scope of your question.

If you want just some of the elements in the Array then you can use the
[] method and specify which elements you're interested in. In your
example, @params[1,2] ("2 elements starting at element 1") would do the
trick.
>
> I'm not sure that Ri Array#* is quite what I meant to look for.

You're right. In this context "*" is a unary operator. Array#* is a method.


dblack

12/27/2006 8:42:00 PM

0

Robert Klemme

12/27/2006 10:31:00 PM

0

On 27.12.2006 21:03, Timothy Hunter wrote:
> Nick Pavey wrote:
>> Hi Folks,
....

I seem to be missing Nick's posting on the news side. I can see it on
the mailing list. Is this the gateway again or my news provider?

Regards

robert

James Gray

12/27/2006 10:51:00 PM

0

On Dec 27, 2006, at 4:35 PM, Robert Klemme wrote:

> On 27.12.2006 21:03, Timothy Hunter wrote:
>> Nick Pavey wrote:
>>> Hi Folks,
> ...
>
> I seem to be missing Nick's posting on the news side. I can see it
> on the mailing list. Is this the gateway again or my news provider?

The message was sent as multipart/alternative. The Gateway does not
currently support this, as explained at:

http://blog.grayproductions.net/articles/2006/12/01/what-is...
talk-gateway

If you want to change this, see:

http://blog.grayproductions.net/articles/2006/12/04/hacking-t...

and:

http://blog.grayproductions.net/articles/2006/12/05/mail_...

You can of course read Nick's message in the mailing list archives:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-t...

Hope this helps.

James Edward Gray II


Robert Klemme

12/28/2006 11:08:00 AM

0

On 27.12.2006 23:50, James Edward Gray II wrote:
> On Dec 27, 2006, at 4:35 PM, Robert Klemme wrote:
>
>> On 27.12.2006 21:03, Timothy Hunter wrote:
>>> Nick Pavey wrote:
>>>> Hi Folks,
>> ...
>>
>> I seem to be missing Nick's posting on the news side. I can see it on
>> the mailing list. Is this the gateway again or my news provider?
>
> The message was sent as multipart/alternative. The Gateway does not
> currently support this, as explained at:
>
> http://blog.grayproductions.net/articles/2006/12/01/what-is-the-ruby-ta...
>
>
> If you want to change this, see:
>
> http://blog.grayproductions.net/articles/2006/12/04/hacking-t...
>
> and:
>
> http://blog.grayproductions.net/articles/2006/12/05/mail_...
>
> You can of course read Nick's message in the mailing list archives:
>
> http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-t...
>
> Hope this helps.
>
> James Edward Gray II

James, thanks for the heads up! I guess you looked at the message and
there was no HTML involved. But before I suggest a change of the
gateway code I'll have to take a look. At the moment I'm imagining that
extracting the first part with "text/plain" would work - at least for
this posting. :-) But I can also see how that would increase the
processing needed per each email...

Kind regards

robert