What is the current status of named arguments (named method parameters, keyword arguments) in Ruby?
Update: Here's a great 6mins screencast by Peter Cooper on Keyword Arguments in Ruby 2.0.
Old: Have a look at this blog post about Keyword Arguments in Ruby 2.0 from yesterday.
Is there a way to do recursion with keyword arguments in ruby 2 without re-specifying each argument?
Not sure if a built-in method exists to do so, but it's evidently possible using local_variables
and some eval-fu:
def foo(bar: :baz)
Hash[local_variables.map { |k| [k, eval("#{k}")] }]
end
foo # {:bar=>:baz}
Related question:
How do I dynamically create a local variable in Ruby?
How not to mix hash and keywordArgument in a Ruby function?
The tutorial is not saying that using =>
(AKA "hash-rocket") is bad, it's saying the use of Strings or other objects besides symbols (:foo
) uses more memory.
{ :foo => 'bar' }
is the original way of defining a symbol as a key. Compare these two definitions:
{ :foo => 'bar' } # => {:foo=>"bar"}
{ foo: 'bar' } # => {:foo=>"bar"}
We tend to use foo:
because we're lazy.
Symbols don't cost as much, but that's a different subject and why can be found with a little searching.
As developers we need to understand the cost of using one algorithm or object versus another. Using Strings or whatever as a key has its time and place and knowing those can save a lot of memory or development time.
Finally, style guides are useful; Read several of them periodically and consider what they're suggesting. The guides are aimed at teams to help them write in a common and consistent manner following good coding practices adapted for Ruby, however they're not cast in stone. Knowing why they're recommended is important, because occasionally we have to ignore or bend the rules, but, when we do, we better be ready to explain why in a code-review.
And, if you're not familiar with Ruby's coding styles, I'd recommend learning about Rubocop, which is a nice tool for checking for consistent and accepted programming style and catching errors.
Avoid repeating named argument defaults when calling superclass initializer in Ruby (2.1+)
In Ruby 2.0+, you can use the double splat operator.
def initialize(bar: 456, **args)
super(**args)
@bar = bar
end
An example:
[1] pry(main)> class Parent
[1] pry(main)* def initialize(a: 456)
[1] pry(main)* @a = a
[1] pry(main)* end
[1] pry(main)* end
=> :initialize
[2] pry(main)> class Child < Parent
[2] pry(main)* def initialize(b: 789, **args)
[2] pry(main)* super(**args)
[2] pry(main)* @b = b
[2] pry(main)* end
[2] pry(main)* end
=> :initialize
[3] pry(main)> ch = Child.new(b: 3)
=> #<Child:0x007fc00513b128 @a=456, @b=3>
[4] pry(main)> ch = Child.new(b: 3, a: 6829)
=> #<Child:0x007fc00524a550 @a=6829, @b=3>
The double splat operator is similar to the single splat operator, but instead of capturing all of the extra args into an array, it captures them into a hash. Then when used as an argument to super, the double splat flattens the hash into named parameters, kind of like the single splat does for arrays.
Passing a hash as an initial value when creating an object
Your initialize
method is looking for two parameters, but your input contains only one, the hash. Here's how you can handle a hash containing Fahrenheit:
def initialize(temp)
@f = temp[:f]
end
If you want to handle input in either F or C, I'll leave that as an exercise for you.
Positional argument vs keyword argument
That text you quote seems to be confused about two totally different things:
- Positional and keyword arguments are a feature of calls to a function (see Python reference section
5.3.4 Calls
). - Default values are a feature of function definitions, as per section
7.6 Function definitions
I suspect the people who put together that course-ware weren't totally familiar with Python :-) Hence that link you provide is not a very good quality one.
In your call to your function, you're using the "keyword argument" feature (where the argument is named rather than relying on its position). Without that, values are bound to names based on order alone. So, in this example, the two calls below are equivalent:
def process_a_and_b(a, b):
blah_blah_blah()
process_a_and_b(1, 2)
process_a_and_b(b=2, a=1)
By further way of example, refer to the following definition and calls:
def fn(a, b, c=1): # a/b required, c optional.
return a * b + c
print(fn(1, 2)) # returns 3, positional and default.
print(fn(1, 2, 3)) # returns 5, positional.
print(fn(c=5, b=2, a=2)) # returns 9, named.
print(fn(b=2, a=2)) # returns 5, named and default.
print(fn(5, c=2, b=1)) # returns 7, positional and named.
print(fn(8, b=0)) # returns 1, positional, named and default.
Related Topics
State MAChine, Model Validations and Rspec
Why Can't I Create an Array as a Column in a Table in Rails
Detect Similar Sounding Words in Ruby
Rails 4 Error with Every Command "'Load': No Implicit Conversion of Nil into String" (MAC Os X 10.9)
Ruby 'Gets' That Works Over Multiple Lines
Encoding Issues in JavaScript Files Using Rails Asset Pipeline
How Are Respond_To and Respond_To_Missing Different
Ssl_Connect Error When Accessing Shopify API with Rubygem
Ruby -- Capitalize First Letter of Every Sentence in a Paragraph
Selenium Webdriver Getting a Cookie Value
Scraping an Angularjs Application
What's Does the [5.0] in Rails 5's Activerecord::Migration Mean