[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Help convert a Perl user to the Ruby Way.

Sebastian Reid

11/12/2006 5:09:00 PM

Hi all.

I've been working on some Ruby projects using the Rails framework
and getting on well, however recently I've started on some projects
using Ruby alone and have run into some issues as the task gets a
little more complicated.

One particular script is giving me trouble and I suspect it is due
to my Perly ways. Below is a pastebin of the code. As some I'm sure
can tell, it is an rbot plugin that right now doesn't do a whole lot.

http://pastebin....

The highlighted line is flagging up the error:

TypeError: no implicit conversion from nil to integer

on line 18 (highlighted).

Now this is looking to me like a variable instantiation issue which
brings us back to Perl. In Perl that line would be perfectly legal
(though some would debate its elegance) and hashes and arrays would
be created as and when required.


I'm willing to accept that this may not be the best way to do things
in Ruby, thus I come to you to ask for a quick rundown on best
practices in these situations.

I've played around with default procs and the like in the
initialisation routine to no avail. There is an implicit dump
somewhere which causes problems. What would be the best way to deal
with this type of thing?

Many thanks,
Seb

11 Answers

David Vallner

11/12/2006 5:18:00 PM

0

Sebastian Reid wrote:
> Hi all.
>
> I've been working on some Ruby projects using the Rails framework
> and getting on well, however recently I've started on some projects
> using Ruby alone and have run into some issues as the task gets a little
> more complicated.
>
> One particular script is giving me trouble and I suspect it is due
> to my Perly ways. Below is a pastebin of the code. As some I'm sure
> can tell, it is an rbot plugin that right now doesn't do a whole lot.
>
> http://pastebin....
>
> The highlighted line is flagging up the error:
>
> TypeError: no implicit conversion from nil to integer
>
> on line 18 (highlighted).
>
> Now this is looking to me like a variable instantiation issue which
> brings us back to Perl. In Perl that line would be perfectly legal
> (though some would debate its elegance) and hashes and arrays would be
> created as and when required.
>

In Ruby, only instance variables are autovivified to nil, and that by
itself is a behaviour that gets on my nerves (typo-prone).

From the code it looks @registry should be an object (maybe use a
Struct) instead of a Hash, and you should preinitialise its contents to
empty arrays and whatnot in its initialize method.

>
> I'm willing to accept that this may not be the best way to do things
> in Ruby, thus I come to you to ask for a quick rundown on best practices
> in these situations.
>
> I've played around with default procs and the like in the
> initialisation routine to no avail.

Using blocks to initialize hashes / arrays is fine when not nested,
otherwise things get messy. Clean up your data structure initialisation
to be explicit?

David Vallner

James Gray

11/12/2006 5:25:00 PM

0

On Nov 12, 2006, at 11:18 AM, David Vallner wrote:

> In Ruby, only instance variables are autovivified to nil, and that by
> itself is a behaviour that gets on my nerves (typo-prone).

This shouldn't be an issue, if you turn on warnings:

$ ruby warning.rb
warning.rb:4: warning: instance variable @brand_new not initialized
nil
$ cat warning.rb
#!/usr/bin/env ruby -w

# use an unassigned instance variable
p @brand_new

__END__

James Edward Gray II


dblack

11/12/2006 5:37:00 PM

0

Sebastian Reid

11/12/2006 5:38:00 PM

0

@registry unfortunately is not within my command, though yes I did
consider using objects for its contents. I'd rather use simpler
(though nested) structures first if I can.

The problem with being explicit when initialising the nested
structures is that they're going to be pretty dynamic throughout, not
to mention the structure itself being changed as I go along.

That said, how would I go about initialising a hash in a hash value
that doesn't exist yet and won't until runtime? Unfortunately this
is something I've gotten well used to not needing to know these days.


On 12 Nov 2006, at 17:18, David Vallner wrote:

> Sebastian Reid wrote:
>> Hi all.
>>
>> I've been working on some Ruby projects using the Rails framework
>> and getting on well, however recently I've started on some projects
>> using Ruby alone and have run into some issues as the task gets a
>> little
>> more complicated.
>>
>> One particular script is giving me trouble and I suspect it is
>> due
>> to my Perly ways. Below is a pastebin of the code. As some I'm sure
>> can tell, it is an rbot plugin that right now doesn't do a whole lot.
>>
>> http://pastebin....
>>
>> The highlighted line is flagging up the error:
>>
>> TypeError: no implicit conversion from nil to integer
>>
>> on line 18 (highlighted).
>>
>> Now this is looking to me like a variable instantiation issue
>> which
>> brings us back to Perl. In Perl that line would be perfectly legal
>> (though some would debate its elegance) and hashes and arrays
>> would be
>> created as and when required.
>>
>
> In Ruby, only instance variables are autovivified to nil, and that by
> itself is a behaviour that gets on my nerves (typo-prone).
>
> From the code it looks @registry should be an object (maybe use a
> Struct) instead of a Hash, and you should preinitialise its
> contents to
> empty arrays and whatnot in its initialize method.
>
>>
>> I'm willing to accept that this may not be the best way to do
>> things
>> in Ruby, thus I come to you to ask for a quick rundown on best
>> practices
>> in these situations.
>>
>> I've played around with default procs and the like in the
>> initialisation routine to no avail.
>
> Using blocks to initialize hashes / arrays is fine when not nested,
> otherwise things get messy. Clean up your data structure
> initialisation
> to be explicit?
>
> David Vallner
>


Sebastian Reid

11/12/2006 6:13:00 PM

0


On 12 Nov 2006, at 17:37, dblack@wobblini.net wrote:

> Hi --
>
> On Mon, 13 Nov 2006, Sebastian Reid wrote:
>
>> Hi all.
>>
>> I've been working on some Ruby projects using the Rails framework
>> and getting on well, however recently I've started on some
>> projects using Ruby alone and have run into some issues as the
>> task gets a little more complicated.
>>
>> One particular script is giving me trouble and I suspect it is
>> due to my Perly ways. Below is a pastebin of the code. As some
>> I'm sure can tell, it is an rbot plugin that right now doesn't do
>> a whole lot.
>>
>> http://pastebin....
>>
>> The highlighted line is flagging up the error:
>>
>> TypeError: no implicit conversion from nil to integer
>>
>> on line 18 (highlighted).
>>
>> Now this is looking to me like a variable instantiation issue
>> which brings us back to Perl. In Perl that line would be
>> perfectly legal (though some would debate its elegance) and hashes
>> and arrays would be created as and when required.
>
> In Ruby that won't work (as you've seen), specifically because [] is a
> method. When you do:
>
> x["y"]
>
> you're really doing:
>
> x.[]("y")
>
> Arrays and hashes have a [] method, but so can any object; so the
> presence of [] doesn't narrow down the field.
>
>> I'm willing to accept that this may not be the best way to do
>> things in Ruby, thus I come to you to ask for a quick rundown on
>> best practices in these situations.
>>
>> I've played around with default procs and the like in the
>> initialisation routine to no avail. There is an implicit dump
>> somewhere which causes problems. What would be the best way to
>> deal with this type of thing?
>
> You'd probably be likely to see @registry initialized in the
> initialize method, and then its elements initialized conditionally
> along the way:
>
> (@registry["content"] ||= []).push(m.message)
>
> You can certainly economize on this if you do:
>
> @registry = Hash.new {|h,k| h[k] = [] }
>
> though this approach might be less slick as you get into deeper
> nesting.
>
> You might want to encapsulate the behavior in a class or module, and
> even perhaps have a class representing @registry["context"].
>
>
> David

I think we actually tried @registry = Hash.new {|h,k| h[k] = [] }
which was where the problem with the dump came in.

Desperately trying not to turn this into a set of classes since it
should be fairly simple otherwise, but I can see it drifting that way.

>
>


Paul Lutus

11/12/2006 7:36:00 PM

0

Sebastian Reid wrote:

> @registry unfortunately is not within my command, though yes I did
> consider using objects for its contents. I'd rather use simpler
> (though nested) structures first if I can.
>
> The problem with being explicit when initialising the nested
> structures is that they're going to be pretty dynamic throughout, not
> to mention the structure itself being changed as I go along.
>
> That said, how would I go about initialising a hash in a hash value
> that doesn't exist yet and won't until runtime?

Let's say we have an instance variable named "hash" that we are not sure has
been initialized at runtime, and we want to create a new hash where there
is none, but only then. Add this line:

hash ||= {}

Means "if 'hash' is a hash, do nothing, otherwise create a hash".

--
Paul Lutus
http://www.ara...

Tom Pollard

11/12/2006 7:58:00 PM

0


On Nov 12, 2006, at 2:40 PM, Paul Lutus wrote:
> Let's say we have an instance variable named "hash" that we are not
> sure has
> been initialized at runtime, and we want to create a new hash where
> there
> is none, but only then. Add this line:
>
> hash ||= {}
>
> Means "if 'hash' is a hash, do nothing, otherwise create a hash".

Strictly speaking, doesn't it mean "if 'hash' is nil (or false),
assign to a newly created empty hash"? You're not testing whether
it's actually a hash already. Also, maybe it's worth reminding the
OP that an empty hash is not treated as 'false' in a logical
expression in Ruby, as it would be in Perl. So, if you were to
repeatedly evaluate

hash ||= {}

you'd only create a new Hash the first time. In Perl, on the other
hand, repeatedly evaluating the similar expression

$hashref ||= {}

would create and assign a new hash repeatedly, until some hash
element was assigned.

Tom


Xavier Noria

11/12/2006 8:22:00 PM

0

On Nov 12, 2006, at 8:58 PM, Tom Pollard wrote:

> On Nov 12, 2006, at 2:40 PM, Paul Lutus wrote:
>> Let's say we have an instance variable named "hash" that we are
>> not sure has
>> been initialized at runtime, and we want to create a new hash
>> where there
>> is none, but only then. Add this line:
>>
>> hash ||= {}
>>
>> Means "if 'hash' is a hash, do nothing, otherwise create a hash".
>
> Strictly speaking, doesn't it mean "if 'hash' is nil (or false),
> assign to a newly created empty hash"? You're not testing whether
> it's actually a hash already. Also, maybe it's worth reminding the
> OP that an empty hash is not treated as 'false' in a logical
> expression in Ruby, as it would be in Perl. So, if you were to
> repeatedly evaluate
>
> hash ||= {}
>
> you'd only create a new Hash the first time. In Perl, on the other
> hand, repeatedly evaluating the similar expression
>
> $hashref ||= {}
>
> would create and assign a new hash repeatedly, until some hash
> element was assigned.

Well, in that case there's only one assignment indeed, because a
hashref is true in Perl as well:

$ perl -wle 'do {$h ||= {}; print $h} for 1..3'
HASH(0x1800e8c)
HASH(0x1800e8c)
HASH(0x1800e8c)

-- fxn




Tom Pollard

11/13/2006 5:03:00 AM

0


On Nov 12, 2006, at 3:22 PM, Xavier Noria wrote:

> On Nov 12, 2006, at 8:58 PM, Tom Pollard wrote:
>> Strictly speaking, doesn't it mean "if 'hash' is nil (or false),
>> assign to a newly created empty hash"? You're not testing whether
>> it's actually a hash already. Also, maybe it's worth reminding
>> the OP that an empty hash is not treated as 'false' in a logical
>> expression in Ruby, as it would be in Perl. So, if you were to
>> repeatedly evaluate
>>
>> hash ||= {}
>>
>> you'd only create a new Hash the first time. In Perl, on the
>> other hand, repeatedly evaluating the similar expression
>>
>> $hashref ||= {}
>>
>> would create and assign a new hash repeatedly, until some hash
>> element was assigned.
>
> Well, in that case there's only one assignment indeed, because a
> hashref is true in Perl as well:
>
> $ perl -wle 'do {$h ||= {}; print $h} for 1..3'
> HASH(0x1800e8c)
> HASH(0x1800e8c)
> HASH(0x1800e8c)

Good point. I confused the ref with the hash. I'll shut up again,
now...

Tom


Paul Lutus

11/13/2006 8:02:00 AM

0

Tom Pollard wrote:

>> Add this line:
>>
>> hash ||= {}
>>
>> Means "if 'hash' is a hash, do nothing, otherwise create a hash".
>
> Strictly speaking, doesn't it mean "if 'hash' is nil (or false),
> assign to a newly created empty hash"?

Yes, and a good clarification. I was addressing the intent of the line, not
its true basis.

--
Paul Lutus
http://www.ara...