What Does a Single Splat/Asterisk in a Ruby Argument List Mean

What does a single splat/asterisk in a Ruby argument list mean?

It means it can have any number of arguments (including zero) and it discards all those arguments.

What does the * (asterisk) symbol do near a function argument and how to use that in others scenarios?

This is the splat operator, which comes from ruby (and is thus not rails specific). It can be applied in two ways depending on where it is used:

  • to "pack" a number of arguments into an array
  • to split up an array into an argument list

In your function, you see the splat operator used in the function definition. The result is that the function accepts any number of arguments. The complete argument list will be put into args as an array.

def foo(*args)
args.each_with_index{ |arg, i| puts "#{i+1}. #{arg}" }
end

foo("a", "b", "c")
# 1. a <== this is the output
# 2. b
# 3. c

The second variant would be when you consider the following method:

def bar(a, b, c)
a + b + c
end

It requires exactly three arguments. You can now call this method like follows

my_array = [1, 2, 3]
bar(*my_array)
# returns 6

The splat applied in this case to the array will split it and pass each element of the array as an individual parameter to the method. You could do the same even by calling foo:

foo(*my_array)
# 1. 1 <== this is the output
# 2. 2
# 3. 3

As you can see in your example method, these rules do apply to block parameters in the same way.

What does the * (star) mean in Ruby?

Variable Length Argument List, Asterisk Operator

The last parameter of a method may be preceded by an asterisk(*), which is sometimes called the 'splat' operator. This indicates that more parameters may be passed to the function. Those parameters are collected up and an array is created.

The asterisk operator may also precede an Array argument in a method call. In this case the Array will be expanded and the values passed in as if they were separated by commas.

What does the (unary) * operator do in this Ruby code?

The * is the splat operator.

It expands an Array into a list of arguments, in this case a list of arguments to the Hash.[] method. (To be more precise, it expands any object that responds to to_ary/to_a, or to_a in Ruby 1.9.)

To illustrate, the following two statements are equal:

method arg1, arg2, arg3
method *[arg1, arg2, arg3]

It can also be used in a different context, to catch all remaining method arguments in a method definition. In that case, it does not expand, but combine:

def method2(*args)  # args will hold Array of all arguments
end

Some more detailed information here.

ruby: what does the asterisk in p *1..10 mean

It's the splat operator. You'll often see it used to split an array into parameters to a function.

def my_function(param1, param2, param3)
param1 + param2 + param3
end

my_values = [2, 3, 5]

my_function(*my_values) # returns 10

More commonly it is used to accept an arbitrary number of arguments

def my_other_function(to_add, *other_args)
other_args.map { |arg| arg + to_add }
end

my_other_function(1, 6, 7, 8) # returns [7, 8, 9]

It also works for multiple assignment (although both of these statements will work without the splat):

first, second, third = *my_values
*my_new_array = 7, 11, 13

For your example, these two would be equivalent:

p *1..10
p 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

The meaning of `*` when using as a param(not like *arg, just *)

In this specific case, save doesn't take any arguments. That's what happens with a naked splat. But, as you may be aware, calling save on an ActiveRecord model accepts options because this method gets overridden by ActiveRecord::Validations here:

https://github.com/rails/rails/blob/v3.1.3/activerecord/lib/active_record/validations.rb#L47

# The validation process on save can be skipped by passing <tt>:validate => false</tt>. The regular Base#save method is
# replaced with this when the validations module is mixed in, which it is by default.
def save(options={})
perform_validations(options) ? super : false
end

What does the asterisk before the variable mean in the named_scope argument list?

*items means that the function accepts variable number of arguments. In other words, if you call it like this:

Order.by_items(item0, item1, item2)

the variable items inside the named scope lambda function will be an array with 3 items.

To answer your real question, you should call it like this:

Order.by_items(*Item.find(:all, ...))

What does an asterisk in front of a constant mean?

I hope that it actually expanded to permit(:name, :a_field, :another_field) :) But yeah, basically that's what it does when used on an array, it takes the values of the array and expands them out as if they were provided as individual arguments. So then you can take those array elements and send them into a method that's expecting individual arguments.

You can also use it in the inverse, you can define a method like:

def foo *args
end

...and when it's called with individual arguments:

foo 'a', 'b', 'c'

...those end up inside the foo method in the array args - this is very handy for wrapping another method, eg.

def some_method *args
do_something args.first
super *args # call the superclass's `some_method` with whatever args it would have received
end

Update

Btw, here's the official docs about this operator.

naked asterisk as parameter in method definition: def f(*)

def f(*) has the same effect as def f(*args), except that it does not name the globbed argument array. You might use it if you want the function to accept any number of arguments but don't actually need to refer to them within the function -- for example, if you are overriding a method but calling super without passing an explicit argument list, which results in the original arguments being passed to super.

You can write def f(a, b, *) as well.

Passing a hash to a function ( *args ) and its meaning

The * is the splat (or asterisk) operator. In the context of a method, it specifies a variable length argument list. In your case, all arguments passed to func will be putting into an array called args. You could also specify specific arguments before a variable-length argument like so:

def func2(arg1, arg2, *other_args)
# ...
end

Let's say we call this method:

func2(1, 2, 3, 4, 5)

If you inspect arg1, arg2 and other_args within func2 now, you will get the following results:

def func2(arg1, arg2, *other_args)
p arg1.inspect # => 1
p arg2.inspect # => 2
p other_args.inspect # => [3, 4, 5]
end

In your case, you seem to be passing a hash as an argument to your func, in which case, args[0] will contain the hash, as you are observing.

Resources:

  • Variable Length Argument List, Asterisk Operator
  • What is the * operator doing

Update based on OP's comments

If you want to pass a Hash as an argument, you should not use the splat operator. Ruby lets you omit brackets, including those that specify a Hash (with a caveat, keep reading), in your method calls. Therefore:

my_func arg1, arg2, :html_arg => value, :html_arg2 => value2

is equivalent to

my_func(arg1, arg2, {:html_arg => value, :html_arg2 => value2})

When Ruby sees the => operator in your argument list, it knows to take the argument as a Hash, even without the explicit {...} notation (note that this only applies if the hash argument is the last one!).

If you want to collect this hash, you don't have to do anything special (though you probably will want to specify an empty hash as the default value in your method definition):

def my_func(arg1, arg2, html_args = {})
# ...
end


Related Topics



Leave a reply



Submit