آرگومان های متغیر

با استفاده از دستورات خاص args* و kwargs** می‌توان تعداد دلخواهی از آرگومان‌ها را به متد ارسال کرد. همانطور که در درس‌های قبل ذکر شد، هنگام فراخوانی متد باید به تعداد پارامترهایی که در داخل پرانتز تعریف شده‌اند، آرگومان به متد ارسال کرد. گاهی اوقات در برنامه نویسی ممکن است بخواهید که در هر بار فراخوانی متد تعداد دلخواهی آرگومان به آن ارسال کنید. این کار با استفاده از * و ** ممکن است. به کد زیر توجه کنید :

def varArguments(*args)
    total = 0

    for number in args
      total = total + number
    end

    return total
end

puts "1 + 2 + 3 = #{varArguments(1, 2, 3)}"
puts "1 + 2 + 3 + 4 = #{varArguments(1, 2, 3, 4)}"
puts "1 + 2 + 3 + 4 + 5 = #{varArguments(1, 2, 3, 4, 5)}"
1 + 2 + 3 = 6
1 + 2 + 3 + 4 = 10
1 + 2 + 3 + 4 + 5 = 15

همانطور که در کد بالا مشاهده می‌کنید، با قرار دادن یک علامت ستاره قبل از نام پارامتر، می‌توان هر بار که متد را فراخوانی کرد، تعداد دلخواهی از آرگومانها را به آن ارسال کرد. وجود یک علامت * باعث می‌شود که آرگومانها در یک متغیر از جنس آرایه ذخیره شوند و در نتیجه می‌توان با یک دستور for مقادیر آنها را با هم جمع کرد. این نوع پارامتر را می‌توان با پارامترهای ثابت هم به کار برد. به مثال زیر توجه کنید:

def varArguments(number, *args)
    puts "number = #{number}"
    puts "args = #{args}"
end

varArguments(1, 2, 3)
number =  1
args =  [2, 3]

در کد بالا اولین آرگومان به اولین پارامتر (یعنی 1 به number) و بقیه آرگومانها به args اختصاص داده می‌شوند. وقتی از چندین پارامتر در یک متد استفاده می‌کنید فقط یکی از آنها باید دارای * بوده و همچنین از لحاظ مکانی باید آخرین پارامتر باشد. اگر این پارامتر (پارامتری که دارای علامت * است) در آخر پارامترهای دیگر قرار نگیرد و یا از چندین پارامتر علامت دار استفاده کنید با خطا مواجه می‌شوید. به مثالهای اشتباه و درست زیر توجه کنید :

def someMethod(*args, *args) #ERROR

def someMethod(*args, param1, param2) #ERROR

def someMethod(param1, param2, *args) #Correct

البته می‌توان پارامتر ستاره دار را در ابتدای پارامترهای دیگر قرار داد ولی پارامترهای بعد از این پارامتر یا باید دارای مقدار پیشفرض باشند

def varArguments(*args, number:10)
  puts "args = #{args}"
  puts "number = #{number}"
end

varArguments(1, 3, 5)
args = [1, 3, 5]
number = 10

و یا هنگام فراخوانی متد، باید پارامترهای بعد از این پارامتر را با استفاده از اسمشان مقداردهی کرد. به کد زیر توجه کنید:

def varArguments(*args, number:)
  puts "args = #{args}"
  puts "number = #{number}"
end

varArguments(1, 3, 5, number: 10)
args = (1, 3, 5)
number = 10

حال فرض کنید که می‌خواهید چند آرایه به پارامتر ستاره دار ارسال کنید. به کد زیر توجه نمایید :

def varArguments(number, *args)
  puts "number = #{number}"
  puts "args = #{args}"
end

varArguments(1, *[2,3,4], *[5,6,7,8])
number = 1
args = [2, 3, 4, 5, 6, 7, 8]

همانطور که در کد بالا مشاهده می‌کنید، کافیست که آرگومان‌ها به صورت آرایه ارسال شوند و قبل از آنها علامت * را قرار دهیم. خط آخر کد بالا را به صورت زیر هم می‌توان نوشت :

varArguments(1, *[2,3,4], *[5,6,7,8])

kwargs** هم شبیه args* عمل می‌کند با این تفاوت که هنگام فراخوانی متد می توان آرگومان‌ها را به صورت hash به آن ارسال کرد:

def varArguments(**kwargs)
    puts (kwargs)
end

varArguments(person1: "Jack", person2: "Joe", person3: "Smith")
{:person1=>"Jack", :person2=>"Joe", :person3=>"Smith"}