Created
April 19, 2012 12:02
-
-
Save dasch/2420529 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'pattern' | |
# Returns the n'th number in the Fibonacci sequence. | |
def fib(n) | |
Pattern.match(n) do | |
on(0) { 0 } | |
on(1) { 1 } | |
on(Integer) { fib(n - 2) + fib(n - 1) } | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# A simple implementation of pattern matching in Ruby. | |
class Pattern | |
class NoMatch < RuntimeError | |
end | |
def self.match(value, &block) | |
catch(:ok) do | |
matcher = Matcher.new(value) | |
matcher.instance_eval(&block) | |
# If none of the patterns matched, we'll end up here. | |
raise NoMatch | |
end | |
end | |
end | |
class Pattern::Matcher | |
def initialize(value) | |
@value = value | |
end | |
def on(pattern) | |
if pattern === @value | |
throw :ok, yield | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rubygems' | |
require 'rspec/autorun' | |
describe Pattern::Matcher do | |
describe "#on" do | |
let(:matcher) { Pattern::Matcher.new("foo") } | |
it "throws :ok when the pattern matches the value" do | |
catch(:ok) { matcher.on(/foo/) { "bar" } }.should eq "bar" | |
end | |
it "does not throw :ok when the pattern doesn't match the value" do | |
matcher.on("baz") { "bar" }.should be_nil | |
end | |
end | |
end | |
describe Pattern, ".match" do | |
it "returns the value from the matching clause" do | |
Pattern.match "foo" do | |
on("foo") { "bar" } | |
on("baz") { "bim" } | |
end.should eq "bar" | |
end | |
it "returns nil if that's what the matching clause returns" do | |
Pattern.match "foo" do | |
on("foo") { nil } | |
end.should be_nil | |
end | |
it "raises NoMatch if there were no matches" do | |
lambda do | |
Pattern.match "foo" do | |
on("baz") { "bar" } | |
end | |
end.should raise_error(Pattern::NoMatch) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment