In the past, we learned that programming is probably very familiar with how many arguments / methods need to pass, so it will pass as many arguments even when we reuse that function in a different context, some of the arguments Unnecessary in or even some cases where the number of arguments passed back is insufficient. Ruby language is quite flexible in this, maybe in some other languages too, but because of our rigidity, we forget how to use these pretty good arguments.
How to pass standard arguments (Required)
This way, as I said above, is the most familiar way. As much as we ask for it, we don’t need it
1 2 3 4 | <span class="token keyword">def</span> <span class="token function">write</span> <span class="token punctuation">(</span> file <span class="token punctuation">,</span> data <span class="token punctuation">,</span> mode <span class="token punctuation">)</span> <span class="token keyword">end</span> <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token string">"cats.txt"</span> <span class="token punctuation">,</span> <span class="token string">"cats are cool!"</span> <span class="token punctuation">,</span> <span class="token string">"w"</span> <span class="token punctuation">)</span> |
If we don’t pass a sufficient number of arguments, we get the following error message:
1 2 3 | <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token string">"shopping_list.txt"</span> <span class="token punctuation">,</span> <span class="token string">"bacon"</span> <span class="token punctuation">)</span> <span class="token constant">ArgumentError</span> <span class="token punctuation">:</span> wrong number of arguments <span class="token punctuation">(</span> <span class="token number">2</span> <span class="token keyword">for</span> <span class="token number">3</span> <span class="token punctuation">)</span> |
It means we need to pass 3 arguments, not 2.
Use optional arguments (Optional)
In some cases, if you want to call a function that has a few passed arguments, it will have a default value
1 2 3 | <span class="token keyword">def</span> <span class="token function">write</span> <span class="token punctuation">(</span> file <span class="token punctuation">,</span> data <span class="token punctuation">,</span> mode <span class="token operator">=</span> <span class="token string">"w"</span> <span class="token punctuation">)</span> <span class="token keyword">end</span> |
Now you can just pass two file
and data
arguments, and the mode
argument if you forget or try not to pass it will default to = “w”, and if you remember and pass another value then That value will override the default value
Use arguments with keywords (Keyword arguments)
One of the disadvantages between a function and an argument is that in order for the function to run properly, the order of arguments passed must be correct.
If we pass the arguments in the wrong order, the function may fail or the results will be incorrect.
Using arguments with keys will help us change the order of arguments passed
1 2 3 | <span class="token keyword">def</span> <span class="token function">write</span> <span class="token punctuation">(</span> file <span class="token punctuation">:</span> <span class="token punctuation">,</span> data <span class="token punctuation">:</span> <span class="token punctuation">,</span> mode <span class="token punctuation">:</span> <span class="token string">"ascii"</span> <span class="token punctuation">)</span> <span class="token keyword">end</span> |
It helps us to call the function with different argument order:
1 2 | <span class="token function">write</span> <span class="token punctuation">(</span> data <span class="token punctuation">:</span> <span class="token number">123</span> <span class="token punctuation">,</span> file <span class="token punctuation">:</span> <span class="token string">"test.txt"</span> <span class="token punctuation">)</span> |
But more importantly, it helps us know exactly which arguments we pass and how much.
I don’t usually use this type of argument, but it’s quite useful when we want to increase the clarity that in cases of passing a series of values of the same type, for example:
1 2 3 4 5 6 7 | <span class="token keyword">class</span> <span class="token class-name">Point</span> <span class="token keyword">def</span> <span class="token function">initialize</span> <span class="token punctuation">(</span> x <span class="token punctuation">:</span> <span class="token punctuation">,</span> y <span class="token punctuation">:</span> <span class="token punctuation">)</span> <span class="token variable">@x</span> <span class="token punctuation">,</span> <span class="token variable">@y</span> <span class="token operator">=</span> x <span class="token punctuation">,</span> y <span class="token keyword">end</span> <span class="token keyword">end</span> point <span class="token operator">=</span> <span class="token constant">Point</span> <span class="token punctuation">.</span> <span class="token keyword">new</span> <span class="token punctuation">(</span> x <span class="token punctuation">:</span> <span class="token number">10</span> <span class="token punctuation">,</span> y <span class="token punctuation">:</span> <span class="token number">20</span> <span class="token punctuation">)</span> |
We will not be confused with which value of x, which value of y.
That’s one of the main purposes of this type of argument: avoid confusion and misunderstand as much as possible.
Functions that do not limit the number of arguments (variable arguments)
What if you want to pass an unknown number of arguments to a function?
1 2 3 4 | <span class="token keyword">def</span> <span class="token function">print_all</span> <span class="token punctuation">(</span> <span class="token operator">*</span> args <span class="token punctuation">)</span> <span class="token keyword">end</span> <span class="token function">print_all</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">,</span> <span class="token number">3</span> <span class="token punctuation">,</span> <span class="token number">4</span> <span class="token punctuation">,</span> <span class="token number">5</span> <span class="token punctuation">)</span> |
This type of argument allows us to pass as many arguments as we can even without any arguments. And itself is an array containing the values to be passed.
We can combine this type of argument with other types of arguments
1 2 3 | <span class="token keyword">def</span> <span class="token function">print_all</span> <span class="token punctuation">(</span> title <span class="token punctuation">,</span> <span class="token operator">*</span> chapters <span class="token punctuation">)</span> <span class="token keyword">end</span> |
The above function will take the first value passed to the title
, and the next argument will be in the array chapters. Note that this argument type must be after the required argument type (optional) and optional argument (optional), and before the key argument (keyword arguments).
Use the right order
If you want to use a combination of argument types and avoid errors, then you must use the correct argument types in the following order:
required -> optional -> variable -> keyword Here is an example that uses all types of arguments:
1 2 3 4 5 | <span class="token keyword">def</span> <span class="token function">testing</span> <span class="token punctuation">(</span> a <span class="token punctuation">,</span> b <span class="token operator">=</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token operator">*</span> c <span class="token punctuation">,</span> d <span class="token punctuation">:</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token operator">*</span> <span class="token operator">*</span> x <span class="token punctuation">)</span> p a <span class="token punctuation">,</span> b <span class="token punctuation">,</span> c <span class="token punctuation">,</span> d <span class="token punctuation">,</span> x <span class="token keyword">end</span> <span class="token function">testing</span> <span class="token punctuation">(</span> <span class="token string">'a'</span> <span class="token punctuation">,</span> <span class="token string">'b'</span> <span class="token punctuation">,</span> <span class="token string">'c'</span> <span class="token punctuation">,</span> <span class="token string">'d'</span> <span class="token punctuation">,</span> <span class="token string">'e'</span> <span class="token punctuation">,</span> d <span class="token punctuation">:</span> <span class="token number">2</span> <span class="token punctuation">,</span> x <span class="token punctuation">:</span> <span class="token number">1</span> <span class="token punctuation">)</span> |
**x
is similar to variable arguments, but will be stored as a hash instead of an array
The Catch-All argument
1 2 3 | <span class="token keyword">def</span> <span class="token function">print_all</span> <span class="token punctuation">(</span> <span class="token operator">*</span> <span class="token punctuation">)</span> <span class="token keyword">end</span> |
This means that this function accepts all of the arguments passed, but does nothing with all of those arguments, it’s similar to using the _
character in a block to denote unused arguments.
The actual use for this type of argument is with the super
keyword:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token keyword">class</span> <span class="token class-name">Food</span> <span class="token keyword">def</span> <span class="token function">nutrition</span> <span class="token punctuation">(</span> vitamins <span class="token punctuation">,</span> minerals <span class="token punctuation">)</span> puts vitamins puts minerals <span class="token keyword">end</span> <span class="token keyword">end</span> <span class="token keyword">class</span> <span class="token class-name">Bacon</span> <span class="token operator"><</span> <span class="token constant">Food</span> <span class="token keyword">def</span> <span class="token function">nutrition</span> <span class="token punctuation">(</span> <span class="token operator">*</span> <span class="token punctuation">)</span> <span class="token keyword">super</span> <span class="token keyword">end</span> <span class="token keyword">end</span> bacon <span class="token operator">=</span> <span class="token constant">Bacon</span> <span class="token punctuation">.</span> <span class="token keyword">new</span> <span class="token class-name">bacon <span class="token punctuation">.</span> nutrition</span> <span class="token punctuation">(</span> <span class="token string">"B6"</span> <span class="token punctuation">,</span> <span class="token string">"Iron"</span> <span class="token punctuation">)</span> |
Suppose you change the argument list of nutrition
function in class Food
, you do not need to go looking for nutrition
function of class Bacon
to match argument list like class Food
anymore, it will be changed by default. class Food
then
summary
References: https://www.rubyguides.com/2018/06/rubys-method-arguments/