Ruby: What Does the Asterisk in "P *1..10" Mean

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

Difference between '..' (double-dot) and '...' (triple-dot) in range generation?

The documentation for Range says this:

Ranges constructed using .. run from the beginning to the end inclusively. Those created using ... exclude the end value.

So a..b is like a <= x <= b, whereas a...b is like a <= x < b.


Note that, while to_a on a Range of integers gives a collection of integers, a Range is not a set of values, but simply a pair of start/end values:

(1..5).include?(5)           #=> true
(1...5).include?(5) #=> false

(1..4).include?(4.1) #=> false
(1...5).include?(4.1) #=> true
(1..4).to_a == (1...5).to_a #=> true
(1..4) == (1...5) #=> false



The docs used to not include this, instead requiring reading the Pickaxe’s section on Ranges. Thanks to @MarkAmery (see below) for noting this update.

What does to_proc method mean in Ruby?

Some methods take a block, and this pattern frequently appears for a block:

{|x| x.foo}

and people would like to write that in a more concise way. In order to do that they use a combination of: a symbol, the method Symbol#to_proc, implicit class casting, and & operator. If you put & in front of a Proc instance in the argument position, that will be interpreted as a block. If you combine something other than a Proc instance with &, then implicit class casting will try to convert that to a Proc instance using to_proc method defined on that object if there is any. In case of a Symbol instance, to_proc works in this way:

:foo.to_proc # => ->x{x.foo}

For example, suppose you write:

bar(&:foo)

The & operator is combined with :foo, which is not a Proc instance, so implicit class cast applies Symbol#to_proc to it, which gives ->x{x.foo}. The & now applies to this and is interpreted as a block, which gives:

bar{|x| x.foo}

What is Ruby Coverage.c is and what is it for?

The "number of line execution" is, as you might expect, the number of times a line has been executed by the interpreter during execution of the program.

Let's look at the example in the documentation with the results added to the original code as comments.

[foo.rb]
s = 0 # executed once
10.times do |x| # once
s += x # ten times
end # not analyzed
# not analyzed
if s == 45 # once
p :ok # once
else # not analyzed
p :ng # not executed
end # not analyzed
[EOF]

require "coverage.so"
Coverage.start
require "foo.rb"
p Coverage.result #=> {"foo.rb"=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]}

The "coverage" is the analysis of how many times each line is executed.

I assume that this module would be useful to see if you have decent "code coverage" with your tests, i.e. check if the tests actually go through all the code or if there are parts that are never executed.

Using the same example in that context, this coverage analysis tells you that the else p :ng part is not exectued and might not be tested.

What does Ruby have that Python doesn't, and vice versa?

You can have code in the class definition in both Ruby and Python. However, in Ruby you have a reference to the class (self). In Python you don't have a reference to the class, as the class isn't defined yet.

An example:

class Kaka
puts self
end

self in this case is the class, and this code would print out "Kaka". There is no way to print out the class name or in other ways access the class from the class definition body in Python.

What does ** (double star/asterisk) and * (star/asterisk) do for parameters?

The *args and **kwargs is a common idiom to allow arbitrary number of arguments to functions as described in the section more on defining functions in the Python documentation.

The *args will give you all function parameters as a tuple:

def foo(*args):
for a in args:
print(a)

foo(1)
# 1

foo(1,2,3)
# 1
# 2
# 3

The **kwargs will give you all
keyword arguments except for those corresponding to a formal parameter as a dictionary.

def bar(**kwargs):
for a in kwargs:
print(a, kwargs[a])

bar(name='one', age=27)
# name one
# age 27

Both idioms can be mixed with normal arguments to allow a set of fixed and some variable arguments:

def foo(kind, *args, **kwargs):
pass

It is also possible to use this the other way around:

def foo(a, b, c):
print(a, b, c)

obj = {'b':10, 'c':'lee'}

foo(100,**obj)
# 100 10 lee

Another usage of the *l idiom is to unpack argument lists when calling a function.

def foo(bar, lee):
print(bar, lee)

l = [1,2]

foo(*l)
# 1 2

In Python 3 it is possible to use *l on the left side of an assignment (Extended Iterable Unpacking), though it gives a list instead of a tuple in this context:

first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]

Also Python 3 adds new semantic (refer PEP 3102):

def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
pass

For example the following works in python 3 but not python 2:

>>> x = [1, 2]
>>> [*x]
[1, 2]
>>> [*x, 3, 4]
[1, 2, 3, 4]

>>> x = {1:1, 2:2}
>>> x
{1: 1, 2: 2}
>>> {**x, 3:3, 4:4}
{1: 1, 2: 2, 3: 3, 4: 4}

Such function accepts only 3 positional arguments, and everything after * can only be passed as keyword arguments.

Note:

  • A Python dict, semantically used for keyword argument passing, are arbitrarily ordered. However, in Python 3.6, keyword arguments are guaranteed to remember insertion order.
  • "The order of elements in **kwargs now corresponds to the order in which keyword arguments were passed to the function." - What’s New In Python 3.6
  • In fact, all dicts in CPython 3.6 will remember insertion order as an implementation detail, this becomes standard in Python 3.7.


Related Topics



Leave a reply



Submit