Skip to content

Instantly share code, notes, and snippets.

@sunaku
Last active December 29, 2015 11:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sunaku/7663078 to your computer and use it in GitHub Desktop.
Save sunaku/7663078 to your computer and use it in GitHub Desktop.
Example of the functional approach to problem decomposition in Ruby. https://class.coursera.org/proglang-002/forum/thread?thread_id=1962
BadResult = Class.new Exception
Int = Struct.new :i
Negate = Struct.new :e1
Add = Struct.new :e1, :e2
def eval e
case e
when Int then e
when Negate then case v1 = (eval e.e1)
when Int then Int.new -v1.i
else raise BadResult, "non-int in negation"
end
when Add then case v1 = (eval e.e1)
when Int then case v2 = (eval e.e2)
when Int then Int.new v1.i + v2.i
end
end or raise BadResult, "non-int in negation"
else raise ArgumentError, e
end
end
def toString e
case e
when Int then e.i.to_s
when Negate then "-(" + (toString e.e1) + ")"
when Add then "(" + (toString e.e1) + " + " + (toString e.e2) + ")"
else raise ArgumentError, e
end
end
def hasZero e
case e
when Int then e.i == 0
when Negate then hasZero e.e1
when Add then hasZero e.e1 or hasZero e.e2
else raise ArgumentError, e
end
end
def noNegConstants e
case e
when Int then if e.i < 0 then Negate.new Int.new -e.i else e end
when Negate then Negate.new noNegConstants e.e1
when Add then Add.new (noNegConstants e.e1), (noNegConstants e.e2)
else raise ArgumentError, e
end
end
$ ruby -r ./section8.rb -e 'p (toString (Add.new (Int.new 5), (Add.new (Negate.new (Int.new 3)), (Int.new 8))))'
"(5 + (-(3) + 8))"
$ ruby -r ./section8.rb -e 'p (eval (Add.new (Int.new 5), (Add.new (Negate.new (Int.new 3)), (Int.new 8))))'
#<struct Int i=10>
$ ruby -r ./section8.rb -e 'p (hasZero (Add.new (Int.new 5), (Add.new (Negate.new (Int.new 3)), (Int.new 8))))'
false
$ ruby -r ./section8.rb -e 'p (toString (Add.new (Int.new -5), (Int.new -3)))'
"(-5 + -3)"
$ ruby -r ./section8.rb -e 'p (toString (noNegConstants (Add.new (Int.new -5), (Int.new -3))))'
"(-(5) + -(3))"
$ ruby -r ./section8.rb -e 'p (eval (Add.new (Int.new 5), "hello"))'
./section8.rb:19:in `eval': hello (ArgumentError)
from ./section8.rb:15:in `eval'
from -e:1:in `'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment