Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly are anonymous functions?

In my journey of a thousand lines of Ruby, I'm having a really hard time with the concept of anonymous functions. Wikipedia says something about there being some nameless soul in the code and it submitting to a higher order, but my understanding ends there.

Or in other words, how would I (when I understand it) explain anonymous functions to my mom?

like image 826
Casey Chow Avatar asked Apr 24 '11 02:04

Casey Chow


2 Answers

An anonymous function has these characteristics:

  1. It has no name (hence anonymous)
  2. Is defined inline
  3. Used when you don't want the overhead/formality of a normal function
  4. Is not explicitly referenced more than once, unless passed as an argument to another function
like image 135
sym3tri Avatar answered Sep 30 '22 08:09

sym3tri


Here's one example of an anonymous function in Ruby (called a block in this case):

my_array.each{ |item| puts item }

Where's the anonymous function in the above? Why, it's the one that receives a single parameter, names it 'item', and then prints it. In JavaScript, the above might be written as...

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); });

...which both makes it a little bit more clear that a function is being passed as an argument, and also helps one appreciate Ruby's syntax. :)

Here's another anonymous function (back in 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!

Although the example is obviously contrived, it shows how you can create a new function (in this case named count) and assign it to a variable, and use that for recursive calls inside a master method. (Some feel that this is better than creating a second method just for the recursion, or re-using the master method for recursion with very different parameters.)

The function doesn't have a name, the variable does. You could assign it to any number of variables, all with different names.

Returning to the first example, there's even a syntax in Ruby for passing a lambda as the single, blessed block:

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

...but you can also pass a lambda as a normal parameter and call it later, as illustrated here:

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
like image 39
Phrogz Avatar answered Sep 30 '22 10:09

Phrogz