#! /usr/bin/ruby

# ---- runtime method definitions in modules ---
# in this example we create one module of math methods with default behaviour,
# and a second module in which the behaviour is defined by the user at run time

# the UserMath module begins with just one method, UserMath.addOp,
#     which allows the user to add new methods to the module
module UserMath
   def UserMath.addOp(func)
       puts "\n---adding to UserMath---\n#{func}\n"
       eval(func)
   end
end

# the DefaultMath module contains (surprise) the default versions of
#     various math functions
# (ok, right now it's just one - div)
module DefaultMath
   def DefaultMath.div(n, d)
       return (n/d.to_f)
   end
end


# get the user to supply the function they want added to UserMath
#     e.g. "def UserMath.div(n,d); return(n.to_f/d.to_f); end"
# and add to the the module using addOp
puts "adding a user-defined operation to UserMath module"
puts "enter your definition for the new function, e.g."
puts "   def UserMath.div(n,d); return(n.to_f/d.to_f); end"
userMethod = gets
UserMath.addOp(userMethod)


# try the default and custom versions out
puts "Enter the method call you wish to test, without the module name"
puts "   e.g. div(3,4)"
testf = gets

# build the calls to the two different versions
defCall = "DefaultMath.#{testf}"
userCall = "UserMath.#{testf}"

puts "Processing #{testf}"

defRes = eval(defCall)
puts "the default answer is #{defRes}"

userRes = eval(userCall)
puts "the custom answer is #{userRes}"

# -------------- Sample Run -------------------
#
# adding a user-defined operation to UserMath module
# enter your definition for the new function, e.g.
#    def UserMath.div(n,d); return(n.to_f/d.to_f); end
# def UserMath.div(num,denom); if (denom == 0) then; return 0; else; return (num.to_i)/denom.to_i); end; end
#
# ---adding to UserMath---
# def UserMath.div(num,denom); if (denom == 0) then; return 0; else; return (num.to_i/denom.to_i); end; end
#
# Enter the method call you wish to test, without the module name
#    e.g. div(3,4)
# div(5,4)
# Processing div(5,4)
# the default answer is 1.25
# the custom answer is 1

# --- if needed, remove_method :methodName

