4

I'm wanting to use the &method(:method_name) idiom when there's more than one object required by method_name. Can I do this under Ruby 1.9?

For example, if I've got

def move_file(old_filename, new_filename)
  STDERR.puts "Moving #{old_filename.inspect} to #{new_filename.inspect}"
  # Implementation for careful moving goes here
end

old_filenames = ["foo.txt", "bar.txt", "hoge.ja.txt"]
new_filenames = ["foo_20110915.txt", "bar_20110915.txt", "hoge_20110915.ja.txt"]

the code

old_filenames.zip(new_filenames).each(&method(:move_file))

works under Ruby 1.8, but not under Ruby 1.9. Under Ruby 1.9, it's trying to do move_file(["foo.txt", "foo_20110915.txt"]) instead of move_file("foo.txt", "foo_20110915.txt").

How do I splattify it so it has the correct arity?

Workarounds I'm aware of:

  1. Replace def move_file(old_filename, new_filename) with def move_file(*arguments)
  2. Replace each(&method(:move_file)) with
    each{|old_filename, new_filename| move_file(old_filename, new_filename)}
Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338

2 Answers2

1

Instead

each{|old_filename, new_filename| move_file(old_filename, new_filename)}

you should be able to do

each{|pair| move_file(*pair)}

But I don't know how you'd pull off blockless variant (I needed it couple of times as well). I guess &-shorthand was made to make the syntax simpler, and is not meant to be clogged much (whether it will be passed an array as an array, or splatted, for example). :)

Mladen Jablanović
  • 43,461
  • 10
  • 90
  • 113
  • What did you mean by "clogged"? – Andrew Grimm Sep 15 '11 at 05:25
  • Sorry, English is not my native... I meant that you somehow need to pass the information whether you want your array to be splatted or not - i.e. use some additional syntax around your `&method(:name)` argument. At one point once concise `&`-style could become bulky and unreadable so that its benefit become questionable. – Mladen Jablanović Sep 15 '11 at 05:44
0

How do I splattify it so it has the correct arity?

I don't think there is a way to do this while being compatible to both Ruby versions. What you could do is wrap it into a lambda

move_from_to = Proc.new {|*both| move_files(*both) }

The thing is - block and proc arity is something that got addressed in Ruby 1.9 so there might be a difference in behavior there. Also see prc.lambda? here http://www.ruby-doc.org/core/classes/Proc.html for info on what it does to the arity.

This question is also related to what you want to do (the solution there is to resplat and unsplat manually): Inconsistency of arity between Hash.each and lambdas

Community
  • 1
  • 1
Julik
  • 7,676
  • 2
  • 34
  • 48