Характеристика доходности Руби по отношению к информатике - PullRequest
49 голосов
/ 19 апреля 2009

Я недавно обнаружил блоки Руби и полезные свойства, и мне было интересно: как это соотносится с теорией информатики? Это метод функционального программирования или что-то более конкретное?

Ответы [ 4 ]

104 голосов
/ 19 апреля 2009

Ruby's yield не является итератором, как в C # и Python. yield само по себе является действительно простой концепцией, если вы понимаете, как работают блоки в Ruby.

Да, блоки - это функциональная функция программирования, хотя Ruby не является функциональным языком. Фактически, Ruby использует метод lambda для создания блочных объектов, который заимствован из синтаксиса Lisp для создания анонимных функций, то есть блоков. С точки зрения информатики, блоки Руби (и лямбда-функции Лиспа) замыкания . В Ruby методы обычно занимают только один блок. (Вы можете пройти больше, но это неловко.)

Ключевое слово yield в Ruby - это просто способ вызова блока, переданного методу. Эти два примера эквивалентны:

def with_log
  output = yield # We're calling our block here with yield
  puts "Returned value is #{output}"
end

def with_log(&stuff_to_do) # the & tells Ruby to convert into
                           # an object without calling lambda
  output = stuff_to_do.call # We're explicitly calling the block here
  puts "Returned value is #{output}"
end

В первом случае мы просто предполагаем, что есть блок, и говорим, чтобы вызвать его. В другом случае Ruby оборачивает блок в объект и передает его в качестве аргумента. Первый более эффективен и удобочитаем, но в действительности он одинаков. Вы бы назвали любой из них так:

with_log do
  a = 5
  other_num = gets.to_i
  @my_var = a + other_num
end

И будет напечатано значение, которое в итоге будет присвоено @my_var. (Хорошо, так что это совершенно глупая функция, но я думаю, вы поняли идею.)

Блоки используются во многих вещах в Ruby. Почти в каждом месте, где вы бы использовали цикл в языке, подобном Java, он заменяется в Ruby методами, которые принимают блоки. Например,

[1,2,3].each {|value| print value} # prints "123"
[1,2,3].map {|value| 2**value}    # returns [2, 4, 8]
[1,2,3].reject {|value| value % 2 == 0} # returns [1, 3]

Как заметил Эндрю, он также широко используется для открытия файлов и во многих других местах. В основном, когда у вас есть стандартная функция, которая может использовать некоторую пользовательскую логику (например, сортировку массива или обработку файла), вы будете использовать блок. Есть и другие применения, но этот ответ уже так долго, я боюсь, что это вызовет сердечные приступы у читателей с более слабыми конституциями. Надеюсь, это прояснит путаницу в этой теме.

6 голосов
/ 19 апреля 2009

Там больше доходности и блоков, чем просто петли.

Серия Перечисление перечислимых имеет ряд вещей, которые вы можете делать с перечислениями, например, спрашивать, верно ли утверждение для любого члена группы, или оно верно для всех членов, или выполнять поиск для любого или всех членов, удовлетворяющих определенному условию.

Блоки также полезны для переменной области. Вместо того, чтобы просто быть удобным, это может помочь с хорошим дизайном. Например, код

File.open("filename", "w") do |f|
  f.puts "text"
end

гарантирует, что поток файлов будет закрыт, когда вы закончите с ним, даже если возникнет исключение, и что переменная выйдет из области действия, как только вы закончите с ней.

Случайный гугл не придумал хорошего сообщения в блоге о блоках и доходах в рубине. Я не знаю почему.

Ответ на комментарий :

Я подозреваю, что он закрывается из-за окончания блока, а не потому, что переменная выходит из области видимости.

Насколько я понимаю, ничего особенного не происходит, когда последняя переменная, указывающая на объект, выходит из области видимости, за исключением того, что этот объект имеет право на сборку мусора. Я не знаю, как это подтвердить.

Я могу показать, что файловый объект закрывается до того, как он соберет мусор, что обычно происходит не сразу. В следующем примере вы можете видеть, что файловый объект закрывается во втором операторе puts, но он не был сборщиком мусора.

g = nil
File.open("/dev/null") do |f|
  puts f.inspect # #<File:/dev/null>
  puts f.object_id # Some number like 70233884832420
  g = f
end
puts g.inspect # #<File:/dev/null (closed)>
puts g.object_id # The exact same number as the one printed out above,
  # indicating that g points to the exact same object that f pointed to
2 голосов
/ 19 апреля 2009

Я думаю, что оператор yield произошел от языка CLU . Мне всегда интересно, был ли персонаж из Трона тоже назван в честь CLU ....

0 голосов
/ 19 апреля 2009

Я думаю 'сопрограмма' - это ключевое слово, которое вы ищете.

например. http://en.wikipedia.org/wiki/Yield

Доходность в области вычислительной техники и информатики:

  • в информатике, точка возврата (и повторного входа) сопрограммы
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...