The Artima Developer Community
Sponsored Link

Java Buzz Forum
Closures: What's the big deal?

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Brian McCallister

Posts: 1282
Nickname: frums
Registered: Sep, 2003

Brian McCallister is JustaProgrammer who thinks too much.
Closures: What's the big deal? Posted: May 14, 2005 10:46 PM
Reply to this message Reply

This post originated from an RSS feed registered with Java Buzz by Brian McCallister.
Original Post: Closures: What's the big deal?
Feed Title: Waste of Time
Feed URL: http://kasparov.skife.org/blog/index.rss
Feed Description: A simple waste of time and weblog experiment
Latest Java Buzz Posts
Latest Java Buzz Posts by Brian McCallister
Latest Posts From Waste of Time

Advertisement

Folks get all excited about closures for some reason. If you break away from the closure == anonymous function school, the cool thing about closures is that they let a function have state! To demonstrate, I'll borrow a page from Mr. Dybvig (search for "make-stack") and implement a stack as a function which returns a function, which is passed messages explicitely:

def make_stack(list=[])
  lambda do |op, *args|
    case 
      when op == :push
        list.push args[0]
      when op == :pop
        list.pop
      else
        raise "Illegal Operation"
    end
  end
end

This snippet defines a function which returns an anonymous function which represents a classical stack data structure. It works:

s = make_stack

s.call :push, "First In"
s.call :push, "First Out"
puts s.call :pop
puts s.call :pop

~>
First Out
First In

The reason this works is because a new list local variable in the make_stack function is created each time make_stack is invoked, and that list is referenced by the Proc returned (created via the lambda call).

This, btw, is easily the basis for a (very) small object system:

def make_instance
  vars = {}
  lambda do |op, *args|
    if op == :define
      vars[args[0]] = args[1]
    else
      vars[op].call args
    end
  end
end

Okay, this technically cheats a bit because I needed Object to respond to :call, so I added

class Object  

  # "calling" an object returns itself unless subclass (Proc) overrides
  def call(*args)
    self
  end
end

Now, this is a complete toy, and hack, and is atrocious, but it illustrates the idea, which we then use:

b = make_instance
e = make_instance
b.call :define, :talk, lambda { puts "Hello, world"}
e.call :define, :talk, lambda { puts "Goodbye, world"}

b.call :talk
e.call :talk

b.call :define, :name, "Brian"       
puts( b.call :name )

~>
Hello, world
Goodbye, world
Brian

But it gets more fun, we want inheritance, right? Let's make a minor change to make_instance so that it supports prototype based inheritance, and add a new special funtion, new_instance

def make_instance(vars={})
  lambda do |op, *args|
    if op == :define
      vars[args[0]] = args[1]
    elsif op == :new_instance
      make_instance(vars.clone)
    else
      vars[op].call args
    end
  end
end

Now we can build up a "base class" and create new instances which inherit what is defined on the base (like JavaScript):

person = make_instance
person.call :define, :talk, lambda { |message| puts message }

k = person.call :new_instance
k.call :talk, "hello, world!"

Yea closures!

Read: Closures: What's the big deal?

Topic: Mysteriously children are getting saved from near death in Bengal! Previous Topic   Next Topic Topic: Project Harmony: Apache J2SE... I know the real reason behind it

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use