Что такое анонимные функции? - PullRequest
13 голосов
/ 24 апреля 2011

В моем путешествии из тысячи строк Ruby у меня было действительно трудное время с концепцией анонимных функций.Википедия говорит что-то о , что в коде есть какая-то безымянная душа и она подчиняется более высокому порядку, но мое понимание на этом заканчивается.

Или, другими словами, как бы я (когда я это понимаю) объяснил анонимные функции моей маме?

Ответы [ 4 ]

14 голосов
/ 24 апреля 2011

Анонимная функция имеет следующие характеристики:

  1. У него нет имени (следовательно, анонимно)
  2. Определяется в строке
  3. Используется, когда вы не хотите накладных расходов / формальности нормальной функции
  4. Не указывается явно более одного раза, если не передан в качестве аргумента другой функции
12 голосов
/ 24 апреля 2011

Вот один пример анонимной функции в Ruby (в данном случае она называется block ):

my_array.each{ |item| puts item }

Где вышеописанная анонимная функция? Да, это тот, который получает один параметр, называет его «item», а затем печатает его. В JavaScript вышеприведенное может быть записано как ...

Array.prototype.each = function(anon){
  for (var i=0,len=this.length;i<len;++i) anon(this[i]);
};
myArray.each(function(item){ console.log(item); });

... что несколько упрощает передачу функции в качестве аргумента, а также помогает оценить синтаксис Ruby. :)

Вот еще одна анонимная функция (обратно в Ruby):

def count_to(n)
  puts "I'm going to count to #{n}"
  count = lambda do |i|
    if (i>0)
      count[i-1]
      puts i
    end
  end
  count[n]
  puts "I'm done counting!"
end
count_to(3)
#=> I'm going to count to 3
#=> 1
#=> 2
#=> 3
#=> I'm done counting!

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

Функция не имеет имени, переменная имеет. Вы можете назначить его любому количеству переменных, все с разными именами.

Возвращаясь к первому примеру, в Ruby даже есть синтаксис для передачи лямбды в виде одного благословенного блока:

print_it = lambda{ |item| puts item }
%w[a b c].each(&print_it)
#=> a
#=> b
#=> c

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

module Enumerable
  def do_both_to_each( f1, f2 )
    each do |item|
      f1[item]
      f2[item]
    end
  end
end

print_prefix  = lambda{ |i| print "#{i}*#{i} -> " }
print_squared = lambda{ |i| puts i*i }

(1..4).do_both_to_each(print_prefix,print_squared)
#=> 1*1 -> 1
#=> 2*2 -> 4
#=> 3*3 -> 9
#=> 4*4 -> 16
6 голосов
/ 24 апреля 2011

В дополнение к предыдущим ответам анонимные функции очень полезны при работе с замыканиями :

def make_adder n
  lambda { |x|
    x + n
  }
end

t = make_adder 100
puts t.call 1

или (в Ruby 1.9):

def make_adder_1_9 n
   ->(x) {
     x + n
   }
end

t_1_9 = make_adder_1_9 100
puts t_1_9.call 1
4 голосов
/ 24 апреля 2011

Как сказано в Википедии: функция без имени.

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

Рассмотрим этот JavaScript (я знаю, вы пометили этот рубин, но ...):

  window.onload=function(){
           //some code here
  }

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

...