Monthly Archives: January 2013

Method Calls in Ruby – 2 (map)

A little more on meta-programming. “map(&:to_i)” sounds neat. It would be useful when handling string inputs.

p ["10", "20"].map(&:to_i)
 # => [10, 20]

proc1 = :to_i.to_proc
p ["10", "20"].map(&proc1)
# => [10, 20]

proc2 = Proc.new { |x| x.to_i }
p ["10", "20"].map(&proc2)
 # => [10, 20]

proc3 = Proc.new { |x| x.send(:to_i) }
p ["10", "20"].map(&proc3)
 # => [10, 20]

p ["10", "20"].map(&method(:Integer))
 # => [10, 20]
Advertisements

Method Calls in Ruby

After watching Google Tech Talks – Monads and Gonads , I found some interest in functional programming concepts. Though I haven’t been able to understand the monad concept, just played around some language features of ruby functional programming, or meta-programming.

class String
  def get_binding
    binding()
  end
end

puts eval('"abc".length')
 # => "3"
puts eval("length", "abc".get_binding)
 # => "3"
puts "abc".send("length")
 # => "3"
puts "abc".method(:length).call
 # => "3"
puts "abc".instance_exec(){ self.length }
 # => "3"
puts String.instance_method(:length).bind("abc").call
 # => "3"

Object-Oriented Design in Ruby – Reading 1. Reusable Code

http://www.amazon.com/dp/0321721330

I started reading the highly-praised ruby book – Practical Object-Oriented Design in Ruby: An Agile Primer. It’s pretty much nicely organized with concise examples. Though I haven’t been able to finish it, I wanted to put some notes on it.

Reusable Code

This book repeatedly talks about reusable code as good example. Reusable would mean that each module has clear responsibility and appopriate dependency to other modules. Also, it means stable code, and less required changes on extending the modules.

There’re a lot of metrics to the good coding, but the “reusability” would be a easier concept to think in mind when implementing a module rather than thinking about the coding techniques.

Impression

This book uses a simple bicycle topic as coding example. Through the course of the content, it gradually being enhanced. Each time the code is enhanced, it reveals the glitch in the previous implementation, and then tries to refactor it. This process is very helpful understanding the important factors maintaining a code in the actual word, rather than keep posting a ideal solution from the beginning.

Testing with STDIN and STDOUT

Recently, I started working on http://codeforces.com/ problem set. They uses STDIN (standard input) and STDOUT (standard output) for the program input/output.

After researching on a way to write test codes against STDIN/STDOUT, I managed to reach to the following code. It’s a little tricky, but I find it relatively compact and useful.

spec_helper.rb

require "rspec"

def test(input, output)
  capture(:stdout) {
    fake_stdin(input){ yield }
  }.should == output
end

def fake_stdin(*args)
  begin
    $stdin = StringIO.new
    $stdin.puts(args.shift) until args.empty?
    $stdin.rewind
    yield
  ensure
    $stdin = STDIN
  end
end

def capture(stream)
  begin
    stream = stream.to_s
    eval "$#{stream} = StringIO.new"
    yield
    result = eval("$#{stream}").string
  ensure
    eval("$#{stream} = #{stream.upcase}")
  end

  result
end

sample.rb

def run
  a, b = $stdin.readline.split.map { |x| x.to_i }
  puts a + b
end

run if $0 == __FILE__

sample_spec.rb

require 'rspec'
require 'spec_helper'
require 'sample'

describe do
  it "adds two values" do
    test("1 2\n", "3\n") { run }
  end
end