2

I'm trying to remove all the - from the strings in an array using map(&:gsub('-','')), but I'm having some difficulty to understand why it is not working:

2.2.2 (main)> my_array = [ 'a-b-c', 'd-e-f', 'g-h-i']
=> [
    [0] "a-b-c",
    [1] "d-e-f",
    [2] "g-h-i"
]
2.2.2 (main)> my_array.map(&:gsub('-',''))
SyntaxError: unexpected ',', expecting end-of-input
my_array.map(&:gsub('-',''))
                        ^

But, when I try these, they work

2.2.2 (main)> my_array.map!(&:upcase)
=> [
    [0] "A-B-C",
    [1] "D-E-F",
    [2] "G-H-I"
]

2.2.2 (main)> my_array.map!(&:downcase)
=> [
    [0] "a-b-c",
    [1] "d-e-f",
    [2] "g-h-i"
]

2.2.2 (main)> my_array.map(&:class)
=> [
    [0] String < Object,
    [1] String < Object,
    [2] String < Object
]

2.2.2 (main)> my_array.map{ | element | element.gsub("-", "") }
=> [
    [0] "abc",
    [1] "def",
    [2] "ghi"
]

Does anyone know why I'm getting this error with map(&:gsub( "-", ""))?

Matthew Schuchard
  • 25,172
  • 3
  • 47
  • 67

2 Answers2

3

You can't pass a method that way. You should do the following:

my_array.map{ |a| a.gsub('-','') }

About a proper usage of ampersand you can read here: Ruby ampersand colon shortcut

Community
  • 1
  • 1
fl00r
  • 82,987
  • 33
  • 217
  • 237
1

As fl00r has already pointed out, you can't pass arguments to the method through &:method like that. However, you can use a lambda if your logic is more than "call this method without any arguments". For example:

remove_hyphens = ->(s) { s.gsub('-', '') }
my_array.map(&remove_hyphens)

You could also use the method method if it makes sense to put the mapping logic in a separate non-String method:

def remove_hyphens(s)
  s.gsub('-', '')
end

my_array.map(&method(:remove_hyphens))

or even a method that returns a lambda:

def remove(char)
  ->(s) { s.gsub(char, '') }
end

my_array.map(&remove('-'))

There's not much point to all this extra machinery for a short one-off block but these are useful technique if the blocks are bigger or more complicated and you want to give it a name to better express your intent or if you want to use the same logic in multiple places. Giving each bit of logic a name is also useful if you're chaining several Enumerable methods together and you want to make the overall logic easier to read:

my_array.select(&the_ones_i_want)
        .map(&to_clean_values)
        .sort_by(&standard_accounting_practices)
        .take(11)
        ...
Community
  • 1
  • 1
mu is too short
  • 426,620
  • 70
  • 833
  • 800