Understanding of the Block concept in Ruby:
In this paper, we give a comparison between JavaScript code block and Ruby code block, the need of friends can refer to the following
The block in Ruby is generally translated into blocks of code, which seems a bit strange at first because there is no such thing in many languages. Actually, it's not bad.
First-class function and Higher-order function
The first-class function and the Higher-order function are concepts in functional programming languages that sound like high-end, but very simple.
First-class functions refers to that in some languages, functions are first-class citizens, and functions can be passed as arguments.
Can return a function, can assign a function to a variable and so on, anyway is normal value can do the thing function can do. That's how JavaScript is. For example, in all of the following examples, when I mentioned
JavaScript, sample code is used in Coffeescript):
|
Greet = (name)-> return-> console.log "Hello, #{name}" greettomike = Greet ("Mike") Greettomike () # => output ' Hel Lo, Mike "a = Greettomike A () # => Output" Hello, Mike " |
In line fourth above, greet ("Mike") returns a function, so the fifth line can invoke the Greettomike () output "Hello, Mike". Line six assigns a function to a, so this function can be called on line seventh.
Higher-order function is generally translated into higher order functions, which are functions that accept functions as arguments or return functions.
Give a very common example (in JavaScript):
|
A = ["A", "B", "C", "D"] A.map ((x)-> x + '! ') #=> ["a!", "b!", "c!", "d!"] |
In the example above, map accepts an anonymous function as an argument. Many of the methods in Array.prototype, such as reduce, filter,every, some, and so on, are high-order functions because they all accept functions as arguments.
High-order functions are very powerful and expressive and can avoid a lot of repetitive code. On the whole, it's a good thing.
The nature of block
Let's look at a set of Ruby and Coffeescript code comparisons.
|
A = ["A", "B", "C", "D"] A.map {|x| x + "!" # => ["a!", "b!", "c!", "d!"] a.reduce {|ACC, x| acc + x} # => "AB" cd "A = [" A "," B "," C "," D "] A.map ((x)-> x + '! ')) # => [" a! "," b! "," c! "," d! "] a.reduce ((ACC, x)-> ACC + x ) # => "ABCD" |
These two sets of code really look super like. I think it also exposes the nature of the block of Ruby: a variant of the function parameters of a higher order function.
The map function in JavaScript takes a function as an argument, but the map in Ruby accepts a
Block as an argument.
In fact, Matz early in a book "Sumbon's Program World" said:
The code is as follows:
In the end, what is the block?
...
Blocks can also be viewed as a special form of syntax for higher-order functions.
...
Higher-order functions are the same as blocks
...
In Ruby, a function is not a first-class citizen, and there is no first-class functions. But in Ruby
How do you use higher-order functions? The answer is to use block. You can use block directly, or you can use lambda
or proc The block into an instance of the Proc class.
I've found that when using block in Ruby, you can use JavaScript in almost every case
Substitution of higher order functions.
All the methods in the enumerable module are typical examples. Actually, there's a JavaScript version.
Enumerable, like Prototype.js, has a enumerable that is almost the same as the Ruby version. Of course it is achieved by higher order functions.
What is the difference between a higher order function
In addition to the grammatical appearance of a little different, there are very important two points.
Control flow Operations
You can use break, next, and so on in the block to control flow operations that are in general circulation, these
is not used in higher-order functions. For example, you could try using ForEach in JavaScript instead of looping.
It's quite awkward to implement a take_while function. For example, before the Cnode on the post asked: Nodejs's foreach does not support the break? In fact, this post reply with return is basically wrong,
Some and every this use short-circuit evaluation of the characteristics can indeed be hack, but obviously not natural and greatly increase the difficulty of others understand the code.
From this point of view block is really good.
Higher order function with only one function parameter
In Ruby, a method can only accept a block as a parameter, presumably similar to a higher order with only one function parameter
Function. It seems to be limited. In fact, the "Sumbon of the program World" on this also a little explanation.
Probably a survey, in the standard library of OCaml, which tends to use higher-order functions, 94%
The higher order function has only one function parameter. So it's not a problem to limit that. As far as my own experience is concerned, in JavaScript, we have never used higher-order functions that require two function parameters.
Not stated.
Well, this article looks a little too long, so I'm not going to write it down. In fact, there are some important places not to say. Like what
Block can actually be used as a closure package. It's a bit of a tragedy when Ruby defines a method with Def, because it's not a closure, contact
Not to the variables outside it.
|
Name = "Mike" def Greet puts "Hello, #{name}" end Hello # => in ' greet ': undefined local variable or method ' name ' for Main:object (Nameerror) |
But it's OK to use block.
|
Name = "Mike" Define_method (: Greet) do puts "Hello, #{name}" end greet # => "Hello, Mike" |
There is no problem with JavaScript.
|
Name = "Mike" greet =-> console.log "Hello, #{name}" greet () # => "Hello, Mike" |
Similarly, the class and module keywords create new scopes in which the outside variables are not exposed.
You can also use block to solve.
And the difference between that proc and the lambda. Actually, I never understood why anyone would use a lambda.
and run to use proc, obviously proc return behavior is too inconsistent with common sense. But in the end it turns out
The behavior of blocks is the same as the behavior of objects created by proc, such as
|
def hello (1..10). Each {|e| return e} return "Hello" End Hello # => 1 |
It was a bit of a sad feeling.
Conclusion
So much, because in Ruby the function is not a first-class citizen and wants to get the convenience of functional programming.