Blocks and proxies in Ruby

I started learning Ruby, and I read a couple of lessons, and I even bought a book ("Programming Ruby 1.9 - A Guide for Pragmatic Programmers"), and I came across something new that I had not seen in any of the other languages ​​that I know (I work as a PHP web developer).

Blocks and proxies. I think I understand what it is, but I don’t understand why they are so wonderful, and when and why I should use them. Everywhere I look, they say that blocks and procs are a great feature in Ruby, but I don't understand them.

Can anyone here give a generic Ruby newbie, as I have some explanation?

+5
source share
6 answers

, . : , .

- , , . , , , , , :

int list[50] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50};
int evenNumbers[50] = {0};
int copyIndex = 0;
for (int i = 0; i < 50; i++) {
    if (list[i] % 2 == 0) {
        evenNumbers[copyIndex++] = list[i];
    }
}

Ruby:

list = 1..50
listCopy = list.select {|n| n.even?}

. , , - . , select. .

- , " " . , File.open, , .

, , . , - ( , Objective-C Cocoa):

class Controller
  def delete_button_clicked(item)
    item.add_red_highlight
    context = {:item => item}
    dialog = Dialog.new("Are you sure you want to delete #{item}?")
    dialog.ok_callback = :delete_OK
    dialog.ok_receiver = self
    dialog.cancel_callback = :cancel_delete
    dialog.cancel_receiver = self
    dialog.context = context
    dialog.ask_for_confirmation
  end

  def delete_OK(sender)
    delete(sender.context[:item])
    sender.dismiss
  end

  def cancel_delete(sender)
    sender.context[:item].remove_red_highlight
    sender.dismiss
  end
end

Yowza. ( , Ruby):

class Controller
  def delete_button_clicked(item)
    item.add_red_highlight
    Dialog.ask_for_confirmation("Are you sure you want to delete #{item}?") do |response|
      response.ok { delete item }
      response.cancel { item.remove_red_highlight }
    end
  end
end

- do...end {} - . , ? , , , self item.

Procs, . .

+13

Ruby, , PHP .

[1,2,3,4,5].each {|i| print "#{i} "}

[1,2,3,4,5].each do |i|
  print "#{i} "
end

File.open('p014constructs.rb', 'r') do |f1|  
  while line = f1.gets  
    puts line
  end
end

PHP5 ; .

echo preg_replace_callback('~-([a-z])~', function ($match) {
  return strtoupper($match[1]);
}, 'hello-world');
+2

, .

, :

superOverFlowArray.each { |flow| puts flow }

{| flow | } . ruby, | flow |.

Procs . Procs - , . proc "" Proc.

, Proc:

def category_and_title(category)
     Proc.new { |title| "The title is: " + title + " in category: " + category }
end

myFirstTitle = category_and_title("Police Drama")
mySecondTitle = category_and_title("Comedy")

puts myFirstTitle.call("Law and Order")
puts mySecondTitle.call("Seinfeld")
puts myFirstTitle.call("CSI")

Proc , , .

+2

Procs, , , , . , procs .

    hello = Proc.new do |x, y|
      puts "i am a proc"
      sum = x+y
      puts "sum: #{sum}"
    end

, , "call" hello. , x y, . Proc, :

    hello.call(2, 3)

:

    i am a proc
    sum: 5

!! Proc. ? , proc . , proc, . ,

    class SomeClass
      def initialize(&block)
        @block = block
      end

      def output_value(x, y)
        @block.call(x, y)
      end
    end

SomeClass,

    some_class = SomeClass.new(&hello)

, "&" proc .

, , 2 , :

    some_class.output_value(1, 3)

:

    i am a proc
    sum: 4

!! . . Procs , Ruby . , :)

+1

, , , .

0

procs .

map , jQuery :

  ['spite','rest','purpose'].map {|s| s << 'ful' }

  ['sprite','restful','luck'].map {|s| s << (s.end_with?('uck') ? 'i' : '') << 'ly' }

There is a smart operator '&' which means "convert the character to proc and call it", so you can convert the lines of objects:

  ['spite',12,:purpose].map(&:to_s)

And using closures and a combination of writing simple closures, we can find where numbers are adjacent. This is pretty awkward Ruby, but more concise than most languages:

  last = -2 # this variable is accessed and changed within the closure
  objs.sort.map do |o|
    if (last + 1) != o
       last = o
       nil # not one more than previous so return nil
    else
       o
    end
  end.compact  # compact removes nils

When you start to rewrite it in another language, you understand how convenient it is. This encourages you to structure your code into smaller operations, so it can be reused and tested.

0
source

All Articles