Absolutely. You are passing something different to methodabc
than method jkl
.
For simplicity consider the code:
def foo(x) x end
def bar(a:, b:) [a, b] end
p foo(a: 100, b: 200)
p bar a: 100, b: 200
# p bar a: 100 # ArgumentError
So, in foo, a and b are mandatory keywords. You can’t omit them. Also, you are passing the values of the hash to a and b. And the type has to be a hash, where the keys are symbols. So, following code after the above code raises an error:
p bar 'a' => 100, 'b' => 200
=begin
/tmp/p.rb:5:in `bar': wrong number of arguments (given 1, expected 0; required keywords: a, b) (ArgumentError)
from /tmp/p.rb:12:in `<main>'
=end
On the other hand foo takes one argument, be it a hash or an array or a string or anything.
It’s not much confusing. You define method with the def
keyword or Kernel#define_method
method. So you know which one is a method. Just to avoid confusion, use parentheses around the arguments, though that’s my personal opinion.
When you call the method, there are several ways, but you call it as a function in general (it’s possible because the top level methods are defined on the main object). If you still find method calls with hashes confusing, you can call them in various ways. For example:
define_method(:bar) { |a:, b:| [a, b] }
p bar({a: 100, b: 200})
# the send method is as fast as the above
p send(:bar, a: 100, b: 200)
# This is a bit slower than send, if you do it a million times
p method(:bar).(a: 100, b: 200)
# This even is slower than the method(...).call(...), and not recommended at all!
p Object.instance_method(:bar).bind(self).(a: 100, b: 200)
Hope this helps!