Dom Lizarraga

dominiclizarraga@hotmail.com

Positional vs Keyword arguments

When I began programming, I was puzzled by why some parameters were named and others not.
Seeing *argument_name or **argument_name threw me for a loop. 😳

Here you’ll find the definitive guide to understand both!

Positional arguments

# This method takes any number of user names as positional arguments. 🙋🙋‍♀️
def greet_users(*users)
  users.each { |user| puts "Hello, #{user}!" }
end

# Passing individual user names to the method, which are packed into an array.
greet_users("Alice", "Bob", "Carlos")
# Outputs:
# Hello, Alice!
# Hello, Bob!
# Hello, Carlos!

# This method can take a variable number of fruit names. 🍎🍌
def list_fruits(*fruits)
  fruits.join(', ')
end

# Passing a list of fruits to the method.
puts list_fruits("Apple", "Banana", "Cherry")
# Outputs: Apple, Banana, Cherry

Keyword arguments

# Usage of ** for keyword arguments: 🙋🙋‍♀️
def greet_users(**users)
  users.each do |identifier, user_info|
    puts "Hello, #{user_info[:name]}!"
  end
end

# Passing user details as keyword arguments.
# The keys `:user1`, `:user2`, and `:user3` are identifiers for each user's hash.
greet_users(
  user1: { name: "Alice", age: 30 },
  user2: { name: "Bob", age: 22 },
  user3: { name: "Carlos", age: 25 }
)

# Outputs:
# Hello, Alice!
# Hello, Bob!
# Hello, Carlos!

# This method takes a variable number of fruit names with details. 🍎🍌
def list_fruits(**fruits_with_details)
  fruits_with_details.map { |fruit, color| "#{fruit}: #{color}" }.join(', ')
end

# Passing a hash of fruits with details to the method.
puts list_fruits(Apple: "Green", Banana: "Yellow", Cherry: "Red")
# Outputs: Apple: Green, Banana: Yellow, Cherry: Red

# More real example of user attributes as keyword arguments.🙋🙋‍♀️
def create_user_profile(**attributes)
  puts "Creating a profile for: #{attributes[:name]}"
  puts "Email: #{attributes[:email]}" if attributes[:email]
  puts "Signup Date: #{attributes[:signup_date]}" if attributes[:signup_date]
end

# Passing attributes as a hash, packed with a double splat.
create_user_profile(name: "Jane Doe", email: "jane.doe@example.com", signup_date: "2023-04-01")
# Outputs:
# Creating a profile for: Jane Doe
# Email: jane.doe@example.com
# Signup Date: 2023-04-01

Passing objects 🙋🙋‍♀️

class User
  attr_reader :name

  def initialize(name)
    @name = name
  end
end

# Create an array of User instances
users = [
  User.new("Alice"),
  User.new("Bob"),
  User.new("Carlos")
]

# Define the greet_users method to accept multiple user objects
def greet_users(*users)
  users.each { |user| puts "Hello, #{user.name}!" }
end

# Call greet_users with the array of User instances
greet_users(*users)

# Outputs:
# Hello, Alice!
# Hello, Bob!
# Hello, Carlos

If you already have a hash with the appropriate keys, you can pass it to the method using the double splat operator **, which will convert the hash into keyword arguments.

Docs for reference:

*positional_argument

**keyword_argument

November 2, 2023   @domlizarraga_