Choice of methods/implementation (was: Writing a game, trying to make dynamic loops)

Since otherwise I’d be hijacking, I’m starting a new thread on this:

On Mon, Mar 25, 2013 at 6:52 AM, Robert K.
[email protected] wrote:

players = Integer(gets).times.map do |i|
puts “Name of player #{n+1}?”
Player.new(gets.chomp)
end

Could you say why, Robert? Obviously there’s more than one way to do
something, but I am interested in why you’d choose this way?

I don’t very much like the previous Array.new() {} either, although
being 1-based might be easier for some to understand, but breaks my
oh-so-long-established zero-based array mentality. I’d have approached
this with #reduce. I’d appreciate hearing your thoughts on the
trade-offs.

On Mon, Mar 25, 2013 at 7:55 PM, tamouse mailing lists
[email protected] wrote:

Player.new(gets.chomp)
end

I’d rather use #times with #map:

players = Integer(gets).times.map do |i|
puts “Name of player #{n+1}?”
Player.new(gets.chomp)
end

I just notice, there is a typo in the name prompt. Should have been

puts “Name of player #{i+1}?”

Could you say why, Robert? Obviously there’s more than one way to do
something, but I am interested in why you’d choose this way?

Oh, it’s probably rather a matter of taste. When the “automatic”
to_enum was introduced for block methods which were called without a
block I took on the habit of using that feature since I find it
elegant. There’s absolutely nothing wrong with your solution. In
fact, it might be a more efficient.

I’d just point out that using Integer() is more robust than
String#to_i because it will ensure the argument is actually a String
representing an integer.

I don’t very much like the previous Array.new() {} either, although
being 1-based might be easier for some to understand, but breaks my
oh-so-long-established zero-based array mentality. I’d have approached
this with #reduce. I’d appreciate hearing your thoughts on the
trade-offs.

Which previous Array.new {} do you mean? The one with the separate
counter variable?

I don’t think this calls for #inject / #reduce. IMHO #map is a better
choice here since you do not need to explicitly deal with the Array
copied into.

Kind regards

robert

On 26/03/2013, at 11:04 AM, Robert K. [email protected]
wrote:

choice here since you do not need to explicitly deal with the Array
copied into.

I like to think of ‘reduce’ meaning you have several things that you
want to reduce to a single thing whereas with ‘map’ you are mapping one
thing to another thing, e.g. mapping integers to players.

Henry

On Mon, Mar 25, 2013 at 5:04 PM, Robert K.
[email protected] wrote:

Player.new(gets.chomp)

I’d just point out that using Integer() is more robust than
String#to_i because it will ensure the argument is actually a String
representing an integer.

That is interesting – I will probably try that more often.

I don’t very much like the previous Array.new() {} either, although
being 1-based might be easier for some to understand, but breaks my
oh-so-long-established zero-based array mentality. I’d have approached
this with #reduce. I’d appreciate hearing your thoughts on the
trade-offs.

Which previous Array.new {} do you mean? The one with the separate
counter variable?

In this case, it was in the solution proposed by Hans, one message up
from yours.

I don’t think this calls for #inject / #reduce. IMHO #map is a better
choice here since you do not need to explicitly deal with the Array
copied into.

Very good point. I may have started thinking of #reduce as a big
hammer that can be used everywhere. :slight_smile:

Thank you!

On Mon, Mar 25, 2013 at 7:03 PM, Henry M. [email protected]
wrote:

counter variable?

I don’t think this calls for #inject / #reduce. IMHO #map is a better
choice here since you do not need to explicitly deal with the Array
copied into.

I like to think of ‘reduce’ meaning you have several things that you want to
reduce to a single thing whereas with ‘map’ you are mapping one thing to
another thing, e.g. mapping integers to players.

I do probably overuse #reduce, as I find those things elegant. But I
do sometimes forget about the #map part of the Map Reduce pattern. I’m
getting better though! I recently recoded something from this:

names = items.reduce([]) {|m,i| m << i.name}

to this:

names = items.map(&:name)

On Tue, Mar 26, 2013 at 6:11 AM, tamouse mailing lists
[email protected] wrote:

On Mon, Mar 25, 2013 at 5:04 PM, Robert K.
[email protected] wrote:

I don’t think this calls for #inject / #reduce. IMHO #map is a better
choice here since you do not need to explicitly deal with the Array
copied into.

Very good point. I may have started thinking of #reduce as a big
hammer that can be used everywhere. :slight_smile:

A while ago I went through that phase as well… :slight_smile:

On Tue, Mar 26, 2013 at 6:20 AM, tamouse mailing lists
[email protected] wrote:

On Mon, Mar 25, 2013 at 7:03 PM, Henry M. [email protected] wrote:

I like to think of ‘reduce’ meaning you have several things that you want to
reduce to a single thing whereas with ‘map’ you are mapping one thing to
another thing, e.g. mapping integers to players.

Yeah, but in this case mapping one collection onto another one is a
superior abstraction because it forces one to do less mechanics. :slight_smile:

I do probably overuse #reduce, as I find those things elegant.

It is. Basically you can implement almost all methods of Enumerable
with #inject. I think I did this once for fun.

But I
do sometimes forget about the #map part of the Map Reduce pattern. I’m
getting better though! I recently recoded something from this:

names = items.reduce([]) {|m,i| m << i.name}

to this:

names = items.map(&:name)

Thumbs up!

Kind regards

robert