Archive

Archive for the ‘duck typing’ Category

Second delhi.rb meetup - Some Advance Ruby Skills

July 20th, 2007

Hey Everyone,
Vinsol is proudly taking charge to spread Rubyism in delhi and to grow the Ruby & Rails communities here in New Delhi, India. We are organizing delhi.rb meetups around once every month, the meetup is all about ruby and rails as well. The meetup was on 19th July 2007 was our second meetup, first was on 22nd June 2007.

Manik presenting SOLR
Manik presenting SOLR


Me presenting Some Advance Ruby Skills
Me presenting Some Advance Ruby Skills

More photos here.

It was really a nice experience attending the meetup, sharing the ruby/rails thoughts and upcoming features. It helps keeping yourself up-to-date with the latest trends in this technology domain at least in Ruby and Rails(what else m talking except ruby :D). So, there were two presentations in the meetup — first Manik presented Full text search implementation for Rails using SOLR(it was really an interesting presentation, i got SOLR learning for free, thanks Manik :)), second I presented Some Advance Ruby Skills which i am going to share in this post too. Though in the first meetup I presented Caching on RubyOnRails but i haven’t posted here…

Some Advance Ruby Skills

1.) Everything is object

A popular phrase about Ruby, “Everything is Object”. At the root of the ruby it is Object. Everything we define in ruby is object. Even the classes we define are actually object. A class defined with class ClassName; end is actually an object of the class Class.
The Object keeps the record of whatever class or module we define. We can justify it as
[source:ruby]
class Klass
end
Object.constants.include?(”Klass”) # => true
[/source]

2.) module_eval

Use module_eval to define instance and class methods of a class at runtime, when you are outside the class.
example 1
defining an instance method
[source:ruby]
class C
end

C.module_eval do
define_method :wish do
p “hello instance method”
end
end

c = C.new
c.wish # => hello instance method
[/source]
example 2
defining a class method
[source:ruby]
class C
end

C.module_eval do
class << self
define_method :wish do
p "hello class method"
end
end
end

C.wish # => hello class method
[/source]
example 3
another form of using module_eval
when method body is available as a String object
[source:ruby]
class D
class << self
def method_body
ret =<<-EOS
def wish
p "hello, supplied as String object"
end
EOS
end
end

class C
end

c = C.new

c.class.module_eval(D.method_body)

c.wish # => hello, supplied as String object
end
[/source]

3.) alias_method

It is NOT method call delegation but insertion of customized functionalities on a specific method call.
[source:ruby]
class C

def wish
p “hello”
end

end

c = C.new
c.wish # hello

class D

class << self
def keep_some_record
p "I am keeping some records"
end
end

end

# aliasing the wish method

c.class.module_eval do

alias_method :wish_orig, :wish

define_method :wish do
D.keep_some_record
wish_orig
end

end

c.wish # I am keeping some records; hello
[/source]

4.) The Anonymous class

I just presented same a la this post

5.) send

Calling a method when method name is stored as a string object in a variable i.e. you can not see which method to call.
example 1
when method name is simply stored as a String object
[source:ruby]
class C
def wish
p “hello DELHI.rb”
end
end
a = “wish”
c = C.new
c.send(a)
[/source]
example 2
making set method at runtime
[source:ruby]
class C
attr_accessor :name
end

c = C.new

a = “name”

c.send(a + “=”, “SUR MAX”)

p c.send(a)
[/source]
example 3
this is interesting, when attribute name itself is send
[source:ruby]
class C
attr_accessor :send
end

c = C.new

a = “send”

c.__send__(a + “=”, “SUR MAX”)

p c.__send__(a) # => Sur Max
[/source]
well, don’t say “what if attribute name is __send__” :P

6.) The Method class

Methods of the class are objects of the Method class when retrieved with the method method and can be called with the method call.
example 1
anything we define with def-end is an object of the class Method
[source:ruby]
class C
def wish
p “hello”
end
end

c = C.new

m1 = c.method(”wish”)

p m1.class # => Method

m1.call # => hello
[/source]
example 2
method can hold the object’s reference and associated instance variables
[source:ruby]
class C
attr_accessor :name

def initialize(name)
self.name = name.to_s
end

def wish
p “hello ” + name.to_s
end
end

c = C.new(”Sur Max”)

m1 = c.method(”wish”)
m1.call # => hello Sur Max
[/source]
example 3
we are able to let this method object flow throughout the application code and let it available anywhere in the code.
[source:ruby]
class C
attr_accessor :name

def initialize(name)
self.name = name.to_s
end

def wish
p “hello ” + name.to_s
end

def self.supply_wish
c = new(”Sur Max”)
return c.method(”wish”)
end

end

C.supply_wish.call # => hello Sur Max
[/source]

7.) what is “self”

I just presented a la this post

8.) Single Method Delegation - using Forwardable

Allows you to delegate named method calls to other objects.
[source:ruby]
require ‘forwardable’

class C
extend Forwardable

attr_accessor :h

def initialize
@h = {}
end

def_delegator(:@h, :[], :show)
def_delegator(:@h, :[]=, :add)

end

end

c = C.new

c.add(1, “asdf”)

p c.show(1)

p c.h
[/source]
Notice the beauty of ruby here… The methods [], []= of a hash object are usually called as
[source:ruby]
h = {}
h["key"] # this will return the corresponding value
h["key"] = “value” # this will set the “value” corresponding to the “key”
[/source]
BUT in the above delegation code we are calling them as(delegating the method call on them as)
[source:ruby]
h = {}
h.[](”key”) # this will return the corresponding value
h.[]=(”key”, “value”) # this will set the “value” corresponding to the “key”
[/source]

9.) Full class Delegation - using Delegator

Extending an object(instance of Class) with the capabilities of another.
[source:ruby]
require ‘delegate’

class Words < DelegateClass(Array)

def initialize(list = "one two three four")
super(list.split)
end

end

w = Words.new

p w # => ["one", "two", "three", "four"]

p w.length # => 4

[/source]

10.) SimpleDelegator

Write memory optimized code with SimpleDelegator…
[source:ruby]
require ‘delegate’

a = SimpleDelegator.new([10, 20])

old_id = a.__id__

b = a

a.__setobj__(”a new object”) # this is not possible otherwise with the method “replace” which can replace only object of same class on same memory location

new_id = a.__id__

p a # => “a new object”
p b # => “a new object”

p new_id == old_id # => true
[/source]

sur advance_ruby, classes, delegation, delhi.rb, duck typing, metaprogramming, rails, ror, ruby, rubyonrails

Ruby is DuckTyped

May 16th, 2007

NOTE : This post may contains repeated and boring stuff for those who already have the programming practice of DuckTyping.

What is Duck Typing ?
Duck Typing is Dynamic Typing
In ruby we do not declare the type of the variable. It automatically becomes the object of the related class. For example, if we assign str = “hello string” then the variable str will automatically becomes the object of class String, that we can confirm by issuing str.class. But according to Duck Typing philosophy even Classes are not Types.
That is the basic rule of Duck Typing is that THE TYPE OF OBJECT IS DETERMINED BY WHAT IT CAN DO, NOT BY ITS CLASS. Lets exemplify the statement…
[source:ruby]
obj = nil

[/source]
now here the object obj is a NilClass object but (in ruby) it will be wrong to say that obj is a NilClass type object. The statement is confining the tasks that can be performed by it. Coz we can have the object obj as a NilClass object and still performing singleton functionalities declared over it. Like …
[source:ruby]
obj = (def wish; puts “good morning, lets code like a Duck :)”; end)
obj # => nil
obj.class # => NilClass
obj.wish # => good morning, lets code like a Duck :) [/source]

So, even a nil object can wish you good morning! Here a method wish has been added to a nil object. But it will not be available for all nil objects, or will that be ? Well, thats a homewok for you!!
Check this out, in this case the wish method will be available for all the nil objects… and the reason is that all the nil objects actually points to a same preserved nil object in the ObjectSpace but not creates a new object everytime like in most cases. Well, i will discuss more deeply regarding the ObjectSpace very soon.

Moreover, extending the modules over an object both at run time and compile time is itself a functionality supporting the statement that Classes are not types and this is what Duck Typing is.

Why known as Duck Typing ?

Alex Martelli, a member of the Python Software Foundation , have given the name DuckTyping to this approach in reference with Duck Test … which says that When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.
So, if an object is behaving like string the it is string type object but not if only it have the class as String.

sur duck typing, ruby