What is the standalone splat operator (*) used for in Ruby?
In a parameter list, *args
means "gobble up all the remaining arguments in an array and bind them to the parameter named args
". *
means "gobble up all the remaining arguments and bind them to nothing", or put more simply "ignore all remaining arguments".
And that's exactly when you would use this: when you want to ignore all the remaining arguments. Either because you don't care about them, or because you don't care about them (but someone else might):
def foo(*)
# do something
super
end
Remember: super
without an argument list passes the arguments along unmodified. So, even though this override of foo
ignored the arguments, they are still available to the superclass's implementations of the method; yet, the definition makes it clear that this implementation doesn't care.
Why is the splat used inside an array definition here?
It creates a single flat array for catch
I'm not sure anyone completely understands the splat operator. Many times it removes one level of "arrayness", but it won't remove the last level.
It is possible to get it in this one case, at least. It creates a single level of array for the catch parameter regardless of whether catch
is a single number or an array of numbers.
>> t = [*404]
=> [404]
>> t = [*[404,405,406]]
=> [404, 405, 406]
Is it possible to invert a splat in Ruby?
Regarding
*(inverse_splat(foo))
, it does not make sense. The result of splatting is in general a sequence of objects, which is not an object. Such thing cannot exist in Ruby.And at this point, the assumption you seem to making, i.e., that the order of
inverse_splat
and*
are interchangable, turns out to be false.Regarding
inverse_splat(*(foo))
There cannot be such inverse. That is because the splat
*
internally callsto_a
, which is not a one-to-one mapping.[[:a, 1], [:b, 2]].to_a
# => [[:a, 1], [:b, 2]]
{a: 1, b: 2}.to_a
# => [[:a, 1], [:b, 2]]An inverse can only be defined on a one-to-one map.
If you disregard such cases and want to still explore if there is something close to it, then a close thing is the
[
...]
literal.
Using splat operator with when
But the splat operator is about assignment, not comparison.
In this case, *
converts an array into an argument list:
when *[2, 3, 4]
is equivalent to:
when 2, 3, 4
Just like in a method call:
foo(*[2, 3, 4])
is equivalent to:
foo(2, 3, 4)
Ruby String end_with? Array
You're just missing the splat operator (*):
filetypes = %w(.flac .wv)
Dir.open(Dir.pwd).each do |filename|
pp(filename) if filename.end_with?(*filetypes)
end
Why is ❨╯°□°❩╯︵┻━┻ with such an encoding used for a method name?
If you really do not understand the sense of the method name, that is a (Japanese-style) facemark. Whereas English facemarks are rotated 90 degrees counter-clockwise and are long in the vertical direction of the actual face, Japanese facemarks are to be read in the direction as is, and are long in the horizontal direction. The author of this is likely to be either a Japanese, or someone who is influenced by Japanese culture like anime.
In this particular case, each character expresses a certain part. From left to right:
❨
The right edge of the face╯
The right arm raised°
The right eye□
The mouth°
The left eye❩
The left edge of the face╯
The left arm raised︵
An imaginary curve expressing the trace of a thrown table┻━┻
A thrown upside-down table (most likely a chabudai that used to be seen typically in Japanese homes until some decades ago)
Chabudai gaeshi used to happen often at some feudal Japanese homes until some decades ago. The father had the absolute monarchic right at home, and whenever he was frustrated over something, he would flip the chabudai during dinner to show his anger, and the family (especially the mother) had to prepare the dinner again.
Here are more variations.
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
How to Strip Leading and Trailing Quote from String, in Ruby
Why Doesn't Relative_Require Work on Ruby 1.8.6
Using Bsearch to Find Index for Inserting New Element into Sorted Array
Add Existing Classes into a Module
Check to See If an Array Is Already Sorted
How to Get Long Filename from Argv
Rails/Ruby Error When Creating Database: Unable to Load the Eventmachine C Extension
Paperclip Error: Model Missing Required Attr_Accessor for 'Avatar_File_Name'
Uploading Files in Ruby on Rails
How to Setup a Local Ssl Certificate and a Rails Application
Ruby Puts Not Outputting in Real Time
How Does Inheritance Work in Ruby
Switch to Popup Windows in Cucumber, Capybara