Crystal は配列を展開した引数をメソッドに渡せなくてつらい?

これは「Ruby脳にはCrystalつらい Advent Calendar 2015」の10日目の記事です。

qiita.com

Ruby だと、配列を展開してメソッドの引数にすることができます。

arg = [1, "abc", :foo]
hoge(*arg)   # hoge(1, "abc", :foo) と同じ

Crystal だとこれはできません。Crystal はコンパイル時に引数の数と型が決まってなければいけないからです。 Ruby脳にはちょっとつらいかもしれません。

なお、リテラルでいいのであれば、タプルを使用すればできます。タプルは不変なので、コンパイル時に確定できるからです。

arg = {1, "abc", :foo}
hoge(*arg)   # hoge(1, "abc", :foo) と同じ

引数を動的にできない代わりに Crystal ではメソッドのオーバーロードができます。

def hoge(x : Int)
  :a
end

def hoge(s : String)
  :b
end

def hoge(a, b, c)
  :c
end

hoge(123)     #=> :a
hoge("abc")   #=> :b
hoge(1, 2, 3) #=> :c

これは Ruby よりも便利!(個人の感想です)

Ruby で同じことをしようとすると、次のような感じになると思います。

def hoge(*args)
  if args.size == 1
    case args[0]
    when Integer
      :a
    when String
      :b
    else
      raise ArgumentError
    end
  elsif args.size == 3
    :c
  else
    raise ArgumentError
  end
end

p hoge(123)     #=> :a
p hoge("abc")   #=> :b
p hoge(1, 2, 3) #=> :c

Ruby つらい!