How does Ruby's .() operator work?
The dot-parentheses notation is a shorthand way for passing arguments to the implicit call
method on a Ruby object:
foo = lambda {|bar| puts bar}
foo.call('baz')
#=> baz
foo.('baz')
foo.call('baz') === foo.('baz')
#=> true
Also note that the following notations are also valid (and equivalent) invocations of the call
method:
foo['baz']
#=> baz
foo::('baz')
#=> baz
In your example, you're explicitly overriding the call
method on the TestServiceObject
class such that it returns the string 'method'
when called. Accordingly, you can explicitly override the the call
method to accept arguments:
class TestServiceObject
def call(foo=nil)
foo || 'method'
end
end
TestServiceObject.new.()
#=> method
TestServicesObject.new.('bar')
#=> bar
UPDATE:
As commenter @LoganSerman duly notes, the shorthand operator appears to work on anything that responds to call
, which is validated in part by the following example:
m = 12.method("+")
m.call(3)
#=> 15
m.(3)
#=> 15
UPDATE 2:
As commenter @Stefan also points out from the documentation on Proc#call
:
prc.() invokes prc.call() with the parameters given. It’s a syntax sugar to hide “call”.
Ruby: bracket notation for immediate call of returned procedure
But I've never seen the syntax before,
I would advise you to get a better tutorial. Most tutorials teach arrays and hashes very early on, where this exact syntax is explained.
and I can't seem to find it documented anywhere.
The documentation for the Proc#[]
method is in the documentation of the Proc
class, just like all other methods.
Is this just syntax sugar for using
#call
No, it is not syntactic sugar for #call
. It is syntactic sugar for #[]
.
Again, this really should have been explained very early on in any tutorial:
foo[bar, baz, quux]
# is syntactic sugar for
foo.[](bar, baz, quux)
or is there more to it?
No, there is nothing more to it.
And I can't seem to find any doc on it. Is there some somewhere?
That fact that foo[bar]
is syntactic sugar for foo.[](bar)
is generally explained in any introductory tutorial either in the chapter about message sends or in the chapter about operators, maybe also in the chapter about arrays or hashes (because that is the most common use case).
[Again, I am quite surprised that you have encountered higher-order programming with Proc
s, yet have never seen an array or hash before, or basic Ruby syntax. That seems a really strange way to order teaching / learning of concepts.]
It is described very clearly in the ISO/IEC 30170:2012 Information technology — Programming languages — Ruby specification chapter 11.3 Method invocation expressions, subchapter 11.3.1 General description, section Semantics, clause b):
An indexing-method-invocation is evaluated as follows:
- Evaluate the primary-expression. Let O be the resulting value.
- If the indexing-argument-list is present, construct a list of arguments from the indexing-argument-list as described in 11.3.2. Let L be the resulting list.
- If the indexing-argument-list is omitted, Create an empty list of arguments L.
- Invoke the method
[]
on O with L as the list of arguments. The value of the indexing-method-invocation is the resulting value.
Of particular interest here is subclause 4) which explains how the syntactic sugar is desugared, namely that O[L]
means invoking the method []
on O
with L
as arguments, or in other words that O[L]
is syntactic sugar for O.[](L)
.
The ruby/spec is unfortunately not quite as clear.
And the YARV documentation hides it away in a paragraph without an explicit heading:
Additionally, methods for element reference and assignment may be defined:
[]
and[]=
respectively. Both can take one or more arguments, and element reference can take none.class C
def [](a, b)
puts a + b
end
def []=(a, b, c)
puts a * b + c
end
end
obj = C.new
obj[2, 3] # prints "5"
obj[2, 3] = 4 # prints "10"
It is documented in the first edition of Programming Ruby by "PragDave" Dave Thomas and Andy Hunt in the chapter on Operator Expressions:
More useful is the fact that classes that you write can participate in operator expressions just as if they were built-in objects. For example, we might want to be able to extract a number of seconds of music from the middle of a song. We could using the indexing operator ```[]`'' to specify the music to be extracted.
class Song
def [](fromTime, toTime)
result = Song.new(self.title + " [extract]",
self.artist,
toTime - fromTime)
result.setStartTime(fromTime)
result
end
endThis code fragment extends class
Song
with the method ```[]`'', which takes two parameters (a start time and an end time). It returns a new song, with the music clipped to the given interval. We could then play the introduction to a song with code such as:aSong[0, 0.15].play
This exact same chapter is also present in the second edition on page 82, except the names of the method parameters now follow standard Ruby naming conventions.
I don't have access to my paper copy of the 4th edition at the moment, but I know it is in there as well.
I am also sure it is documented in The Ruby Programming Language by David Flanagan and Yukihiro "matz" Matsumoto, but I don't have that copy handy either.
If you prefer looking at source code, here is the source code of Proc#[]
in Rubinius, it is as simple as it gets:
alias_method :[], :call
Similarly, here is the code in TruffleRuby:
@CoreMethod(names = { "call", "[]", "yield" }, rest = true, needsBlock = true, alwaysInlined = true)
public abstract static class CallNode extends AlwaysInlinedMethodNode {
// …
}
And the code in JRuby:
@JRubyMethod(name = {"call", "[]", "yield", "==="}, rest = true, omit = true)
public final IRubyObject call(ThreadContext context, IRubyObject[] args, Block blockCallArg) {
// …
}
Is this just syntax sugar for using
#call
As explained above, it is not, but it might be interesting to know that there is syntactic sugar for #call
, namely .()
. So,
foo.(bar, baz, quux)
is syntactic sugar for
foo.call(bar, baz, quux)
Why isn't the Ruby 1.9 lambda call possible without the dot in front of the parentheses ?
AFAIK it's because ruby doesn't let you define the ()
method for an object. The reason it doesn't let you define the ()
method is probably due to the fact that parentheses are optional in method calls.
And for what it's worth, here's a hack to let you invoke lambdas using ()
http://github.com/coderrr/parenthesis_hacks/blob/master/lib/lambda.rb
How the '.call' method be triggered by a returning integer in Ruby?
.()
is just a shortcut for .call()
Yes, the call method is usually used to run proc objects, but that doesn't make it anything special, just a regular method that a proc object has implemented. If you define it to do something else, the shortcut still works as normal
What does the dot mean in this line of code: 65.+rand(10)
You can notice, that in original code there are 2 method calls - +
and chr
. I can show it by equivalent code:
65.send(:+, rand(10)).send(:chr) # is the equal to following line:
65.+(rand(10)).chr
This trick produces method chain, that allows to skip parentheses. With parentheses, 65.+(rand(10)).chr
could be written like this:
(65 + rand(10)).chr
Without this trick, chr
will apply on rand(10)
and the result string will try to be added to 65. It'll produce TypeError:
65+(rand(25)).chr
TypeError: String can't be coerced into Fixnum
Invocation in ruby without a method name
Try:
foo = "Foo"
foo.("a")
# NoMethodError: undefined method `call' for "Foo":String
routine = Proc.new { |arg| puts "Hello #{arg}!" }
routine.("world")
# Hello world!
What do you call the - operator in Ruby?
In Ruby Programming Language ("Methods, Procs, Lambdas, and Closures"), a lambda defined using ->
is called lambda literal.
succ = ->(x){ x+1 }
succ.call(2)
The code is equivalent to the following one.
succ = lambda { |x| x + 1 }
succ.call(2)
Informally, I have heard it being called stabby lambda or stabby literal.
What do the different brackets in Ruby mean?
It depends on the context:
When on their own, or assigning to a variable,
[]
creates arrays, and{}
creates hashes. e.g.a = [1,2,3] # an array
b = {1 => 2} # a hash[]
can be overridden as a custom method, and is generally used to fetch things from hashes (the standard library sets up[]
as a method on hashes which is the same asfetch
)
There is also a convention that it is used as a class method in the same way you might use astatic Create
method in C# or Java. e.g.a = {1 => 2} # create a hash for example
puts a[1] # same as a.fetch(1), will print 2
Hash[1,2,3,4] # this is a custom class method which creates a new hashSee the Ruby Hash docs for that last example.
This is probably the most tricky one -
{}
is also syntax for blocks, but only when passed to a method OUTSIDE the arguments parens.When you invoke methods without parens, Ruby looks at where you put the commas to figure out where the arguments end (where the parens would have been, had you typed them)
1.upto(2) { puts 'hello' } # it's a block
1.upto 2 { puts 'hello' } # syntax error, ruby can't figure out where the function args end
1.upto 2, { puts 'hello' } # the comma means "argument", so ruby sees it as a hash - this won't work because puts 'hello' isn't a valid hash
What are all the different uses of the [square brackets] in Ruby?
Okay, just for my own notes I have gone and had a closer look at this and, building on Holger Just's answer, come up with the following: the use of square brackets in Ruby can be divided into 6 uses, 3 of them a part of Ruby's method definitions and 3 of them semantic constructs.
Method definition
Object creation via class methods Array::[], Hash::[]
Array.[](1,2,3) #=> [1,2,3] #Un-sugared notation
Array["a","b","c"] #=> ["a","b","c"] #Sugared equivalent
Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200}
Nothing to do with literal constructors, although it does the same thing.
Element reference via instance methods Array#[], Bignum#[], Continuation#[], Fixnum#[], Hash#[], MatchData#[], Method#[], Proc#[], String#[], Struct#[], Symbol#[], Thread#[], and class methods Dir::[], ENV::[]
ary = [1,2,"abc", [15,16,[26,27]]]
ary.[](2) #=> "abc" #Un-sugared notation
ary[2] #=> "abc" #Sugared equivalent
ary[0,2] #=> [1,2]
ary[3][2][1] #=> 26
[1,2,3][0] #=> 1
"Is a string"[7,3] #=> "rin"
Element assignment via instance methods Array#[]=, Hash#[]=, String#[]=, Struct#[]=, Thread#[]=, and class method ENV::[]=
ary = [1,2,3]
ary.[]=(1,"abc") #=> [1,"abc",3] #un-sugared notation
ary[2] = "def" #=> [1,"abc","def"] #Sugared equivalent
hash = {"a"=>1, "b"=>2}
hash["a"] = 3 #=> {"a"=>3, "b"=>2}
Semantic constructs
Object creation via the array literal constructor
ary = []
There are a bunch of literal constructors in Ruby that create an object of the relevant class via the use of (usually) a simple symbol pair, square brackets being the literal constructor for array objects: Array []
, Hash {}
, Proc ->(){}
, Range ..
and ...
, Regexp //
, String ""
and ''
, Symbol :
and :""
.
Object creation via the % notation
%q[hello there you] #=> "hello there you" # String % notation
%w[hello there you] #=> ["hello", "there", "you"] # Array % notation
It is not, strictly speaking, square-bracket notation, but rather two-symbol-pair notation of which you can use square brackets if you wish. So %q@hello there you@
is equally valid.
Ruby's regular expressions
/[^A-Fa-f0-9]/
Square brackets indicate character classes in Ruby regular expressions.
I did find another use of the []
, as a pattern for use in the Dir::glob method, but its supposed to act exactly as it does in regular expressions. Still, it indicates that there are possibly more uses hidden away in Ruby's 1500+ methods.
Related Topics
In Ruby How to Use Class Level Local Variable? (A Ruby Newbie's Question)
Tcp Socket Communication Between Processes on Heroku Worker Dyno
How to Use Functions Like Concat(), etc. in Arel
Ruby Indented Multiline Strings
Using Bsearch to Find Index for Inserting New Element into Sorted Array
How to Click on a Specific Coordinates of an Element
How to Convert a Ruby String with Brackets to an Array
Ruby on Rails 4 Select Multiple
Authlogic and Multiple Sessions for the Same User
Using Nokogiri to Split Content on Br Tags
Ruby What Class Gets a Method When There Is No Explicit Receiver
Param Is Missing or the Value Is Empty
How Does Activerecord Define Methods Compared to Attr_Accessor
How to Setup a Local Ssl Certificate and a Rails Application