Ruby Method with Maximum Number of Parameters

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 is 2; obj is 3;
  • new memo is 3 because 3 > 2

Step two:

  • memo is 3; obj is 9;
  • new memo is 9 because 9 > 3

Step three:

  • memo is 9; obj is 5;
  • new memo is 9 because 9 > 5

Step four:

  • memo is 9; obj is 4;
  • new memo is 9 because 9 > 4

.
.
.

Step seven:

  • memo is 10; obj is 8;
  • new memo is 10 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):

Sample Image

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



Leave a reply



Submit