Today i started reading Ruby By Example Book By Kevin C.Baird.
I wanted to share few important quotations i found from this book.
1) In Ruby, like its ancestor Smalltalk, everything is an object, which is just an instance of a class.
2) If you call the method class on an Integer, it will report either Fixnum or Bignum, not Integer. This stems from how Ruby stores numbers internally. Computers can operate faster if they don’t waste space, so they have to worry about how much space numbers take up. However, computers also need to be able to handle very large numbers. Therefore,they compromise and store small numbers so that they take up little space, but they also store very large numbers, which inevitably take up more space. Sophisticated high-level languages like Ruby translate between these different types of numbers automatically,so you can just deal with numbers without worrying about these specific details. Isn’t that handy? For example, 100.class returns Fixnum, and (100 ** 100).class returns Bignum. That’s because 100 is small enough to fit in a Fixnum, but the value of (100 ** 100) will only fit in a Bignum—it’s too big for a Fixnum.
3) The nil value is distinct from all other values. However, when we force Ruby to evaluate nil as a Boolean, it evaluates to false, as shown:
i="It's true!" if nil
puts i
The only values that evaluate to false Booleans are nil and false. In many other languages 0 or "" (a String with zero characters) will also evaluate to false, but this is not so in Ruby. Everything other than nil or false evaluates to true when forced into a Boolean.
4) Ruby has inherited a tradition from its ancestor Lisp of naming methods with a question mark when they return either true or false.Such methods that only return a Boolean are called predicates.
5) Remember that a method that returns a Boolean is a predicate, and Ruby follows the Lisp tradition of naming predicates so that they end in question marks.
6) Ruby gives us a the option of doing what’s called metaprogramming, which allows us to manipulate our objects while we’re still in the process of defining them. In this case, we’re defining to_b as an alias to the method true? that we just created.
class Object
def false?()
not self
end
def true?()
not false?
end
alias :to_b :true?
end
7) Sometimes you may have a text file that you want to perform whitespace compression on, such as converting all repeated spaces into a single space. The script below assumes that all double line breaks should be preserved and that all single line breaks should be converted into spaces. Each group of repeated spaces should also be converted into a single space.
def softwrap(filename)
File.open(filename, 'r').readlines.inject('') do |output,line|
output += softwrap_line(line)
end.gsub(/\t+/, ' ').gsub(/ +/, ' ')
end # softwrap
def softwrap_line(line)
return "\n\n" if line == "\n"
return line.chomp + ' '
end # softwrap_line
puts softwrap("one.txt")
one.txt --->
one
two prasanth
three
The inject method is your first real taste of functional programming, a style of programming in which operations are treated as mathematical functions and side effects are minimized
8) Computing Powers
This is the most purely mathematical of this chapter’s scripts, and it deals with exponentiation.
class Integer
def power_of(base)
# return nil for inapplicable situations
return nil unless base.is_a?(Integer)
return nil if (base.zero? and not [0, 1].include?(self))
# deal with odd but reasonable
# numeric situations
return 1 if base == self
return 0 if self == 1
return false if base == 1
return false if base.abs > self.abs
exponent = (self/base).power_of(base)
return exponent ? exponent + 1 : exponent
end
end
puts 64.power_of(4)
9) One of the most traditional ways to represent a number as a String is as a Roman numeral.This script adds a new method to all Integers called to_roman.
class Integer
# Base conversion Hash
ARABIC_TO_ROMAN = {
1000 => 'M',
500 => 'D',
100 => 'C',
50 => 'L',
10 => 'X',
5 => 'V',
1 => 'I',
0 => '',
}
# Represent 4 as 'IV', rather than 'IIII'?
SUBTRACTIVE_TO_ROMAN = {
900 => 'CM',
400 => 'CD',
90 => 'XC',
40 => 'XL',
9 => 'IX',
4 => 'IV',
}
# Use SUBTRACTIVE_TO_ROMAN Hash?
SUBTRACTIVE = true
def to_roman()
@@roman_of ||= create_roman_of()
return '' unless (self > 0)
return to_s if self > maximum_representable()
base = @@roman_of.keys.sort.reverse.detect { |k| k <= self }
return '' unless (base and base > 0)
return (@@roman_of[base] * round_to_base(base)) + (self % base).to_roman()
end
private
def create_roman_of()
return ARABIC_TO_ROMAN unless SUBTRACTIVE
ARABIC_TO_ROMAN.merge(SUBTRACTIVE_TO_ROMAN)
end
def maximum_representable()
(@@roman_of.keys.max * 5) - 1
end
def round_to_base(base)
(self - (self % base)) / base
end
end
puts 42.to_roman()
Prints XLII
10) Ruby has two main ancestors: Smalltalk and Lisp.1 From Smalltalk, Ruby gets its heavy object orientation, which we’ve explored in some depth up to this point. From Lisp it derives several ideas from functional programming.
11) Every “thing” in Ruby is an object, so the notion of treating functions as objects is not conceptually odd.
Example:
def make_incrementer(delta)
return lambda { |x| x + delta }
end
incrementer_proc_of = Hash.new()
[10, 20].each do |delta|
incrementer_proc_of[delta] = make_incrementer(delta)
end
incrementer_proc_of.each_pair do |delta,incrementer_proc|
puts "#{delta} + 5 = #{incrementer_proc.call(5)}\n"
end
12) Example of how to use Procs as data generated by another function.
#!/usr/bin/env ruby
# return_proc.rb
class Object
def false?()
not self
end
def true?()
not false?
end
alias :to_b :true?
end
def return_proc(criterion, further_criterion=1)
proc_of_criterion = {
'div_by?' => lambda { |i| i if (i % further_criterion).zero? },
'is?' => lambda { |i| i == further_criterion }
}
# allow 'is_even' as an alias for divisible by 2
return return_proc('div_by?', 2) if criterion == ('is_even')
proc_to_return = proc_of_criterion[criterion]
fail "I don't understand the criterion #{criterion}" unless proc_to_return
return proc_to_return
end
# Demonstrate calling the proc directly
even_proc = return_proc('is_even') # could have been ('div_by', 2)
div3_proc = return_proc('div_by?', 3)
is10_proc = return_proc('is?', 10)
[4, 5, 6].each do |num|
puts %Q[Is #{num} even?: #{even_proc[num].true?}]
puts %Q[Is #{num} divisible by 3?: #{div3_proc[num].true?}]
puts %Q[Is #{num} 10?: #{is10_proc[num].true?}]
printf("%d is %s.\n\n", num, even_proc[num].true? ? 'even' : 'not even')
end
# Demonstrate using the proc as a block for a method
digits = (0..9).to_a
even_results = digits.find_all(&(return_proc('is_even')))
div3_results = digits.find_all(&(return_proc('div_by?', 3)))
puts %Q[The even digits are #{even_results.inspect}.]
puts %Q[The digits divisible by 3 are #{div3_results.inspect}.]
puts
Output:
Is 4 even?: true
Is 4 divisible by 3?: false
Is 4 10?: false
4 is even.
Is 5 even?: false
Is 5 divisible by 3?: false
Is 5 10?: false
5 is not even.
Is 6 even?: true
Is 6 divisible by 3?: true
Is 6 10?: false
6 is even.
The even digits are [0, 2, 4, 6, 8].
The digits divisible by 3 are [0, 3, 6, 9].
13) Basic code for finding out factorial of a given number.
class Integer
def fact()
return 1 if (self.zero?) or (self == 1)
return self * (self-1).fact
end
end
puts 3.fact
Here’s a variant that decides what to return via the include? method, which eliminates the need to run two separate tests to find out whether self is either zero or one. The motivation is that it could be faster to do a single test instead of two separate tests.
class Integer
def fact()
return 1 if [0, 1].include?(self)
return self * (self-1).fact
end
end
14) Validating XML
All the XML processing in the world won’t do any good if your XML file is not well-formed. Since an XML document either is or is not well-formed,a well-formedness checker that will return either true or false seems like an ideal predicate method. Since XML documents are Files with Strings as their contents, we’ll add a well_formed_xml? method to both the File class and the String class.
require 'xml/dom/builder'
class File
def well_formed_xml?()
read.well_formed_xml?
end
end
class String
def well_formed_xml?()
builder = XML::DOM::Builder.new(0)
builder.setBase("./")
begin
builder.parse(self, true)
rescue XMLParserError
return false
end
return true
end
end
def well_formed?(filename)
return unless filename
return File.open(filename, 'r').well_formed_xml?
end
puts well_formed?('demo.xml')
About The Author
Kevin C. Baird received his Ph.D. from the State University of New York at Buffalo. He originally wrote his dissertation in Python but rewrote the project after discovering Ruby, and he hasn't looked back since. He has presented at RubyConf and written articles for Linux Journal, Music & Computers magazine, and the New Interfaces for Musical Expression conference proceedings
Monday, 1 September 2008
Subscribe to:
Post Comments (Atom)
3 comments:
Hai prasanth,
Seen the archive. Very keen and sharp work. I feel I am not upto the mark to make any comment. All the best...
Muralikrishna
Hai prasanth,
Seen the archive. Very keen and sharp work. I feel I am not upto the mark to make any comment. All the best...
Muralikrishna
Mavayya,
Thanks a lot for your encouraging comments.
Thanks
Prashant
Post a Comment