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]
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
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