Named Parameters: What's a Nice Keyword Argument Like You Doing in a Place Like This?

In one of the labs from a few weeks ago, my Ruby class was introduced to named parameters, also known as keyword arguments. These parameters are defined in the method signature with a default value in the format (named_parameter: default_value).

Because their behavior appears similar to standard arguments with default values, most of us were mystified about their purpose. In Ruby, standard arguments with default values appear in the format (standard_argument=default_value). Take a look at the similarities:

1
2
3
4
5
6
7
8
9
10
11
12
13
  def drink(spirit: "whiskey") # spirit = named parameter
    "Another #{spirit} for my friend here, barkeep."
  end

  drink
  #=> "Another #{spirit} for my friend here, barkeep."

  def eat(snacks="pretzels") # snacks = standard argument with default value
    "And some #{snacks} - I'm famished!"
  end

  eat
  #=> "And some pretzels - I'm famished!" 

As beginners, was there some use for them we just weren’t grasping? Or were these named parameters just another option bestowed by the Ruby gods in order afford us more options when coding?

Looking at this in another perspective, if you try to call a standard method with arguments without using any, you get an error:

1
2
3
4
5
6
7
8
9
  def drink(container)
    "Pour me a #{container}, willya?"
  end

  drink("glass")
  #=> "Pour me a glass, willya?"

  drink
  #=> ArgumentError: wrong number of arguments (0 for 1)

It’s logical to assume that named parameters would work the same way. Yet if you try this with a method with named parameters, it still runs – just like how standard parameters use default values for missing arguments!

While this is helpful to have, it’s nothing that we can’t do through default parameters.

Then we learned that named parameters don’t care about the order in which you call them.

On one hand, neat trick!

1
2
3
4
5
6
  def bootlegger(distillery: location, source: location)
    "We smuggled the bourbon from #{source}, but we brewed this moonshine in #{distillery}. Dee-licious!"
  end

  bootlegger(source: "Canada", distillery: "Grandma's old bathtub")
  #=> "We smuggled the bourbon from Canada, but we brewed this moonshine in Grandma's old bathtub. Dee-licious!" 

On the other hand, who cares? This feature is a nice wrinkle, but it doesn’t really seem like it warrants the existence of the function.

After a little digging and experimentation, I finally found a reason why named parameters are worth the trouble: They allow methods to require specifically-named parameters when being invoked, for an added measure of security!

Source: Flickr

1
2
3
4
5
6
7
8
9
  def speakeasy_knock(password: )
    "'#{password}'? Good enough for me, come on in!"
  end

  speakeasy_knock
  #=> ArgumentError: missing keyword: password

  speakeasy_knock(password: "Open up, chump!")
  #=> "'Open up, chump'? Good enough for me, come on in!" 

Of course, you’ll need added security measures beyond just requiring the named parameter. But suddenly, having named parameters available as a tool starts to make sense.

Because standard arguments take input regardless of typing or designation, and because default arguments are fine not taking any input from the method call at all, requiring a named parameter for a method to function gives it a measure of protection against reckless usage.

To strain an already-exhausted metaphor, in certain use cases, named parameters can act exactly like locked doors that require code words in order to grant entry.

Source: Speakeasy216

For more gory details about this and other functions introduced in Ruby 2.0.0, check out this substantial post by Marc-Andre Lafortune: http://blog.marc-andre.ca/2013/02/23/ruby-2-by-example/

Comments