Skip to content

Instantly share code, notes, and snippets.

@delonnewman
Created July 17, 2019 15:49
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 delonnewman/59acb78fe080f4c5dc09d8600d53e4b1 to your computer and use it in GitHub Desktop.
Save delonnewman/59acb78fe080f4c5dc09d8600d53e4b1 to your computer and use it in GitHub Desktop.
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