Ruby method with maximum number of parameters
You have several alternatives, depending on how much you want the method to be verbose and strict.
# force max 2 args
def foo(*args)
raise ArgumentError, "Too many arguments" if args.length > 2
end
# silently ignore other args
def foo(*args)
one, two = *args
# use local vars one and two
end
# let the interpreter do its job
def foo(one, two)
end
# let the interpreter do its job
# with defaults
def foo(one, two = "default")
end
Refactoring a method to find the max of any number of arguments RUBY
Assuming you're not allowed to use Array#max
, you can do the following:
def maxx *args
args.reduce { |memo, obj|
obj > memo ? obj : memo
}
end
p maxx 2,3,9,5,4,3,10,8
#=> 10
Explanation
Here's a slightly more verbose, un-refactored version which may be easier to read. *args
catches all your arguments into an array args
. In the example args = [2, 3, 9, 5, 4, 3, 10, 8]
.
def maxx(*args)
args.reduce {|memo, obj|
if obj > memo
memo = obj
else
memo = memo
end
}
end
p maxx(2,3,9,5,4,3,10,8)
#=> 10
reduce
goes through each element obj
from your args
array storing it as the new memo
only if obj
is bigger than the current memo
. By default memo
starts with args[0]
, 2
in this case. And obj
starts with args[1]
, namely 3
.
Step one:
memo
is2
; obj is 3;- new
memo
is3
because 3 > 2
Step two:
memo
is3
;obj
is9
;- new
memo
is9
because 9 > 3
Step three:
memo
is9
;obj
is5
;- new
memo
is9
because 9 > 5
Step four:
memo
is9
;obj
is4
;- new
memo
is9
because 9 > 4
.
.
.
Step seven:
memo
is10
;obj
is 8;- new
memo
is10
because 10 > 8
The final new memo
is what's returned by reduce
, which is of course the maximum 10
. For more information on Array#reduce
. In the refactored original answer I've used a ternary operator
which is basically a short way of writing a simple if-expression
.
Ruby Function with Unlimited Number of Parameters
Use *rest
. here's a nice little tutorial.
is there a way limit the arguments passed to a Ruby method in the method signature?
No, there is nothing like that.
You can, of course, have if
statements inside your method to check the arguments, and then if you find a problem raise an ArgumentError
exception:
raise ArgumentError, "Number must be 1, 2, or 3."
Is there a way to know how many parameters are needed for a method?
You can use the method Method#arity
:
"string".method(:strip).arity
# => 0
From the Ruby documentation:
Returns an indication of the number of arguments accepted by a method.
Returns a nonnegative integer for methods that take a fixed number of
arguments. For Ruby methods that take a variable number of arguments,
returns -n-1, where n is the number of required arguments. For methods
written in C, returns -1 if the call takes a variable number of
arguments.
So, for example:
# Variable number of arguments, one is required
def foo(a, *b); end
method(:foo).arity
# => -2
# Variable number of arguments, none required
def bar(*a); end
method(:bar).arity
# => -1
# Accepts no argument, implemented in C
"0".method(:to_f).arity
# => 0
# Variable number of arguments (0 or 1), implemented in C
"0".method(:to_i).arity
# => -1
Update I've just discovered the exitence of Method#parameters
, it could be quite useful:
def foo(a, *b); end
method(:foo).parameters
# => [[:req, :a], [:rest, :b]]
Ruby - How to write a method that accepts a proc with varying numbers of params?
You can always find out how many arguments that Proc takes:
def map!(&block)
case block.arity
when 1
# Takes 1 argument
when 2
# Takes 2 arguments
else
# etc.
end
end
This is a common pattern if you need to handle different argument counts in a particular way.
It's worth noting that unless you need to shuffle up the order of the arguments passed in you can always pass in too many and the excess will be ignored:
def example(&block)
block.call(1,2,3)
end
example { |v| p v }
# => 1
ruby method - how to reduce the number of params in a method?
I suppose if you wanna go all out strict with the Sandi Metz rules then the OOP way is the way to go.
class Sequence
attr_reader :start, :step
initialize(start, step)
@start = start
@step = step
end
end
sequence_1 = Sequence.new(seq1_start, seq1_step)
sequence_2 = Sequence.new(seq2_start, seq2_step)
class DoubleSeries
def self.generate_sequences(sequence_1, sequence_2, iterations)
item_1, item_2 = sequence_1.start, sequence_2.start
result=[]
iterations.times do
result << item_1 << item_2
item_1 += sequence_1.step
item_2 += sequence_2.step
end
result
end
end
[My code (michael):
How can I know how many parameters a method passes to a block?
A straightforward way is:
a.each{|e| p [*e].length}
# => 1 1 1
h.each{|e| p [*e].length}
# => 2 2 2
Ruby programmatically calling method, with variable number of args
Try this
def foo(a, b)
puts a
puts b
end
array = ['bar', 'qux']
send(:foo, *array) # using send
foo(*array) # using the method name
Both print
bar
qux
The splat operator *
packs or unpacks an array.
Related Topics
Array Attribute for Ruby Model
Get Today's Date in Jekyll with Liquid Markup
What Is the Send() Method Used For
Rails 5.2 Active Storage Add Custom Attributes
Getting Attribute's Value in Nokogiri to Extract Link Urls
How to Check If a Gem Is Installed
How to Get Request.Uri in Model in Rails
Ruby Array Each_Slice_With_Index
Carrierwave: Create the Same, Unique Filename for All Versioned Files
Should I Use Class Method or Instance Method, and Why
Rails How to Switch Between Dev and Production Mode
Is There a Good Admin Generator for Ruby on Rails
Postgresql Gem Pg Was Unable to Install
Ruby: What Does the Asterisk in "P *1..10" Mean