Noitidart
Noitidart

Reputation: 37238

Why is this using concat operator

I'm new to ruby but am pretty sure these things are equivalent. But I'm making a chance to an important script and just wanted to be sure please.

This is what they have now:

def generate_names options
  names = []

  name = options.name
  sen = options.sen
  ari = options.ari

  options.targets.each do |target|
    names << "#{name}" + " Test " + "#{target}"
  end

  names
end

This is what I want to change it to, notice on the line names << I removed the +'s. This is exactly the same right? I even did a test on equality but just want to make sure.

def generate_names options
  names = []

  name = options.name
  sen = options.sen
  ari = options.ari

  options.targets.each do |target|
    names << "#{name} Test #{target}"
  end

  names
end

Aside I tried this in irb but its giving error:

"#{name}" + " Test " + "#{target}".eql?("#{name} Test #{target}") ? "equal" : "not"

Error given is:

TypeError: no implicit conversion of false into String
    from (irb):20:in `+'
    from (irb):20
    from /usr/bin/irb:12:in `<main>'

Upvotes: 0

Views: 45

Answers (1)

tadman
tadman

Reputation: 211560

Look at this individually:

names << "#{name}" + " Test " + "#{target}"

This is really irregular code. "#{name}" is going to be equivalent to name if that's a string value, so the quotes are extraneous, and worse, create another string that gets thrown out immediately. This one line creates four strings alone.

The other is better:

names << "#{name} Test #{target}"

This creates one string and inserts it. Interpolation is almost always better than concatenation because it creates less garbage.

Your irb test is flawed:

"#{name}" + " Test " + "#{target}".eql?("#{name} Test #{target}") ? "equal" : "not"

This evaluates the .eql? part first on just target which is obviously not a match so it evaluates to:

("#{name}" + " Test " + false) ? "equal" : "not"

Which is going to fail because you can't combine false and a string.

The way to test this is to force a particular evaluation order:

("#{name}" + " Test " + "#{target}").eql?("#{name} Test #{target}") ? "equal" : "not"

Upvotes: 2

Related Questions