A detailed explanation of the use of Ruby anonymous functions

Source: Internet
Author: User
Tags anonymous bind closure

The main callable object in Ruby is the Proc object, the Lambdas, the method object. Proc is a separate sequence of code that you can create, store, and use as a parameter to the method, or you can execute it using the call method if you wish. Lambdas is similar to Proc object, Lambda is actually Proc object, but slightly different.

Proc objects

Create a Proc instance with proc.new:

PR = proc.new {puts "inside a Proc ' s Block"}
The code block above is the body of the Proc, and when you call Proc, you execute something in the code block:

Pr.call
The result:

Inside a proc ' s block
Give the Proc method a code block that will give you a Proc object to return.

Proc {puts "hi!"}
Procs and Blocks

Not all code blocks are the same as Proc.

[1,2,3].each {|x| puts X * 10}
A code block was used, but no proc was created.

A method can capture a block of code:

def call_a_proc (&block)
Block.call
End

Call_a_proc {puts "I m" Block ... or proc ... or someting. "}
The output is:

I ' m The block ... or Proc ... or someting.
Use proc to do the same:

p = proc.new {|x| puts x.upcase}
%w{Matt Damon}.each (&p)
The input is:

MATT
DAMON
Syntax (blocks) and objects (procs)

Ruby's code block is not an object.

[1,2,3].each {|x| puts X * 10}
The receiver is an object, and the code block is not. A code block is part of the calling method syntax. Think of the code block as a list of parameters.

Puts c2f (100)
In the method called above, the argument is an object, but the overall argument list is not an object: (100). There are no argumentlist classes and no Codeblock classes.

Block and proc Conversion

def capture_block (&block)
Block.call
End

Capture_block {puts "inside"}
The proc.new is implicitly invoked, using the same block.

Explain:

1 invokes the Capture_block method and gives it a block of code:

Capture_block {puts "inside"}
2 creates a Proc object using the same block:

Proc.new {puts "inside"}
The 3 block parameter binds the Proc object.

def capture_block (&block)
Puts "got block as proc"
Block.call
End
Proc as a block of code

p = proc.new {puts "This Proc argument'll serve as a code block}"
Capture_block (&P)
The output is:

This proc argument would serve as a code block
The proc marked with the & symbol will act as a block of code, so you can't give the same method a block of code. Execute the following code to make an error:

Capture_block (&p) {puts "This are the explicit block"}
Tip: "Both block Arg and actual block given." Ruby can't tell you whether you want to use proc or block as code blocks. You can only choose one.

The & in &p is the packaging of the To_proc method. Calling To_proc on a Proc object returns the Proc object itself.

You still need to, if you want to do:

Capture_block (P)
Or:

Capture_block (P.to_proc)
This way you pass only the general parameters. The proc parameter is not allowed as a block of code. In other words, in Capture_block (&p), this & has two meanings, it triggers the To_proc method on p, and it makes Ruby the proc object that executes To_proc return as a block of code.

Symbol#to_proc

>>%w{a B}.map (&:capitalize)
=> ["A", "B"]
: Capitalize this symbol will be interpreted as sending information to each item in the array. Equivalent:

%w{a b}.map {|str| str.capitalize}
Also corresponds to:

%w{a b}.map {|str| str.send (: Capitalize)}
You can remove parentheses:

%w{a B}.map &:capitalize
Procs as closures

The local variables used in the method body are different from the local variables used when the method is invoked.

Def talk
A = "Hello"
Puts a
End

A = "Goodbye"
# The output is Hello
Talk

# The output is goodbye
Puts a
A This identifier was assigned two times, but there was no connection between the two allocations.

To use a variable that already exists in a block of code:

>> m = 10
=> 10
>> [1,2,3].each {|x| puts x * m}
10
20
30
=> [1, 2, 3]
Multiply_by returns a proc, when the Multiply_by method is invoked, the arguments passed to the method are retained in the proc:

def multiply_by (M)
proc.new {|x| puts x * m}
End
mult = multiply_by (10)

# Output 120
Mult.call (12)
Do another experiment and note the following two variable a:

def call_some_proc (PR)
A = "' A ' in the scope of the method"
Puts a
Pr.call
End

A = "The use of ' a ' in the Proc block
PR = proc.new {puts a}
Pr.call
Call_some_proc (PR)
The result of the output is:

The ' a ' used in the Proc block
' A ' in the scope of the method
The ' a ' used in the Proc block
The Proc object will carry its context. In the example above, A is a part of the context in which a will always exist in the Proc. A piece of code like this, always with the context it creates, is a closure (closure). When you call the closure, you open the closure, which contains what you put in when you created it. Closures retain part of the state in which the program is running.

Creating a closure is sort of like packing luggage, and wherever you open the bag, it will contain the stuff you put in when you pack it.
Take a look at the counter example, the value of its variable will be incremented each time the proc is invoked:

def Make_counter
n = 0
return proc.new {n + + 1}
End

c = Make_counter
Puts C.call
Puts C.call
D = Make_counter
Puts D.call
Puts C.call
The output is:

1
2
1
3
Proc parameters

A Proc, with a block, with a parameter in the block:

PR = proc.new {|x| puts parameter when called: #{x} "}
Pr.call (100)
The output is:

Parameter at call: 100
The Proc parameters are not the same as the method processing parameters. It does not depend on the correct number of arguments used when invoking. Supports one parameter:

>> PR = proc.new {|x| p x}
=> #<proc:0x007faf7aa016e0@ (IRB):27>
Parameters are not used when called:

>> Pr.call
Nil
The invocation uses more than one argument, takes only the first argument, and discards the rest:

>> Pr.call (1,2,3)
1
Creating functions with Lambda and->

The lambda method returns a Proc object. The supplied code block becomes the body of the function:

>> Lam = lambda {puts "a lambda!"}
=> #<proc:0x007faf7a8afd28@ (IRB): (lambda) >
>> Lam.call
A lambda!
=> Nil
Lambda-flavored proc are three different from the usual proc. The lambda needs to be explicitly created, and the implicit creation is not a lambda, like this:

def m (&block)
Lambda treats return keywords differently from ordinary proc.

def return_test
L = lambda {return}
L.call
Puts "still here!"
p = proc.new {return}
P.call
Puts "You won ' t-you-message!"
End

Return_test
The output is "still here!" and does not see the second message. Because invoking the Proc object triggers a return from return_test. However, the invocation of the lambda triggers the return (exit) of the lambda body, and the execution of the method continues.

Lambda-flavored proc, use the normal number of arguments when called:

>> Lam = lambda {|x| p x}
=> #<proc:0x007faf7a998c58@ (IRB): A (lambda) >
>> Lam.call (1)
1
=> 1
>> Lam.call
Argumenterror:wrong Number of arguments (given 0, expected 1)
From (IRB): 105:in ' blocks in irb_binding '
From (IRB): 107
From/usr/local/bin/irb:11:in ' <main> '
>> Lam.call (1,2,3)
Argumenterror:wrong Number of arguments (given 3, expected 1)
From (IRB): 105:in ' blocks in irb_binding '
From (IRB): 108
From/usr/local/bin/irb:11:in ' <main> '
->

>> Lam =-> {puts "HI"}
=> #<proc:0x007faf7a903400@ (IRB): 109 (lambda) >
>> Lam.call
Hi
=> Nil
The arguments are placed in parentheses:

>> mult =-> (x,y) {x * y}
=> #<proc:0x007faf7a980720@ (IRB): (lambda) >
>> Mult.call (3,4)
=> 12
The method as an object

Methods are not objects, but you can object (objectify) them to become objects.

Capturing method objects

Using method methods, the name of the method is used as its argument.

Class C
Def talk
Puts "Gets the method object, self is #{self}. "
End
End

c = c.new
Meth = C.method (: talk)
Meth is a method object that binds the talk method of a C object. Call it:

>> Meth.call
Gets the method object, self is #<c:0x007faf7a950f48>.
Re-bind:

Class D < C
End

D = d.new
unbound = Meth.unbind
Unbound.bind (d). Call
The result:

Gets the method object, self is #<d:0x007faf7a84c430>.
You can also rebind this way:

unbound = C.instance_method (: talk)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.