Ruby: exit inside a block

Here is an example scan:

"abcdeabcabc".scan("a")

Thus, it returns an array of 3 a. Another scan example:

"abcdeabcabc".scan("a") {|x| puts x}

which only prints each "a", but still outputs an array, and this time it is actually the original string that it returns.

So, from the documentation and the above behavior, scanning returns an array (without a block) or returns the original string, before which some side effects occur. The fact is that both cases return something.

Then what happens if I put an "exit" inside the block? What will be returned? Or not? What will be the type of return value?

"abcdeabcabc".scan("a") {|x| yield x}

The above will not work as Ruby complains that the block is not specified. That makes sense to me. But if it is part of a class method, say, self-applicable "everyone", then the following works:

class Test
  def my_each
    "abcdeabcabc".scan("a") {|x| yield x}
  end
end
# => :my_each

t = Test.new
# => #<Test:0x007ff00a8d79b0>

t.my_each {|x| puts "so this is #{x}"}
# it works. Outpus 3 a then return the original string.

So what is the return value of the my_each method of the Test class? Is it a crop list or something else? But as previously discussed, "abcdeabcabc" .scan ("a") {| x | yield x} will complain to Ruby until a block is specified. What happened internally to provide my_each block to a segment inside my_each implementation?

+4
source share
3 answers

The block is passed in the same way as the argument to this function. This can be specified explicitly, for example:

class Test
  def my_each(&block)
    "abcdeabcabc".scan("a") do |x|
      puts "!!! block"
      yield x
      # Could be replaced with: block.call(x)
    end
  end
end

, (puts, ), , . , yield, LocalJumpError ( , , Rubinius). , "!!!".

. , , , , if block, yield s. content_tag Rails. -. :

content_tag :div do
  content_tag :div
end

... , :

<div>
  <div></div>
</div>

, "" ( ) . , yield - . , .

UPD:

Enumerator, each es, , , .

: my_each:

class Test
  def my_each(&block)
    if block
      "abcdeabcabc".scan("a") { |x| yield x }
    else
      Enumerator.new(self, :my_each)
    end
  end
end
+2

scan, . , .

+1

"abcdeabcabc".scan("a") {|x| yield x}

#scan .

#scan yield, , my_each. x , my_each.

, .

my_each Test?

#scan, , , , #my_each ( ), #scan.

- ?

, yield, #scan.

: -

"abcdeabcabc".scan("w") {|x| yield x}

, #scan, , #scan , yield #my_each wouldn ' t ( ), "abcdeabcabc".

0

Source: https://habr.com/ru/post/1544105/


All Articles