Created
July 17, 2019 15:49
-
-
Save delonnewman/59acb78fe080f4c5dc09d8600d53e4b1 to your computer and use it in GitHub Desktop.
This file contains 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
module X | |
module Generic | |
Any = BasicObject | |
def define_generic_method(name, pattern, &blk) | |
generic_methods[name] ||= {} | |
generic_methods[name][pattern] = blk | |
define_method name do |obj, *args| | |
# This will cost O^n, but it may not be too much of a cost given that cases tend to be few | |
fn = generic_methods[name].select { |pat, _| pat === obj }.first | |
if fn | |
obj.instance_exec(*args, &fn[1]) | |
else | |
raise TypeError, "#{name} is not defined for #{obj.inspect}" | |
end | |
end | |
end | |
alias generic define_generic_method | |
def generic_methods | |
@generic_methods ||= {} | |
end | |
end | |
end | |
include X::Generic | |
generic :test, Integer do | |
puts "This is a test #{self.inspect}" | |
end | |
generic :test, String do | |
puts "This is a test #{self.inspect}" | |
end | |
generic :test, nil do | |
puts "Nil" | |
end | |
generic :cool, /^A/ do | |
puts "#{self} starts with A" | |
end | |
generic :cool, ->(x) { x == 0 } do | |
puts "#{self} is zero" | |
end | |
generic :cool, (0..10) do | |
puts "#{self} is a number between 0 and 10" | |
end | |
generic :cool, Any do | |
puts "cool on #{self} is not well defined" | |
end | |
test 1 | |
test "This is a test" | |
test nil | |
cool "Adventure" | |
cool 5 | |
cool 0 | |
cool 25 | |
cool "Boat" | |
module Cron | |
include X::Generic | |
class Job; end | |
class HTTPJob < Job; end | |
class ScriptJob < Job; end | |
generic :run, HTTPJob do | |
puts "Run #{self} via http" | |
end | |
generic :run, ScriptJob do | |
puts "Run #{self} via script interface" | |
end | |
generic :run, Job do | |
puts "Run #{self} via shell" | |
end | |
generic :run, Object do | |
puts "Log error #{self} is not a valid Job type" | |
end | |
module_function :run | |
end | |
Cron.run Cron::Job.new | |
Cron.run Cron::HTTPJob.new | |
Cron.run Cron::ScriptJob.new | |
Cron.run 1 | |
Cron.run Object.new |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment