Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
What if we could check type signatures in Ruby? A proof of concept.
# Allow multiple classes to be declared via A|B instead of [A, B].
class Class
def |(*other_classes)
SetOfClasses.new(self, other_classes)
end
end
require 'set'
class SetOfClasses
attr_reader :classes
def initialize(*classes)
@classes = Set.new(classes.flatten)
end
def |(*other_classes)
SetOfClasses.new([self, *other_classes])
end
def none?(&block)
classes.none?(&block)
end
end
class Class
def signature(*arg_types)
@method_signature = arg_types
end
def method_added(method_name)
puts 'method_added'
if @method_signature
method_signature = @method_signature
@method_signature = nil
original_method_name = "#{method_name}_without_type_checking"
self.send(:alias_method, "#{original_method_name}", "#{method_name}")
define_method("#{method_name}".to_sym) do |*args, &block|
check_method_signature(method_signature, args)
self.send(original_method_name, *args, &block)
end
end
end
end
class Object
def check_method_signature(arg_types, args)
puts "Checking signature: #{arg_types}: #{args}"
arg_types.each_with_index do |arg_type, index|
var = args[index]
if arg_type.kind_of?(SetOfClasses)
if arg_type.none?{|type| var.kind_of?(type)}
raise ArgumentError.new("Argument '#{var}' must be one of the types #{arg_type}")
end
elsif arg_type.kind_of?(Class)
unless var.kind_of?(arg_type)
raise ArgumentError.new("Argument '#{var}' must be of type #{arg_type}")
end
else
raise ArgumentError.new("Arguments to signature() must be classes.")
end
end
end
end
class Xyz
signature(Integer|Fixnum, String, Symbol)
def xyz(a, b, c)
puts 'xyz:'
puts a.inspect
puts b.inspect
puts c.inspect
end
end
Xyz.new.xyz(1,'b',:c) # Should work.
Xyz.new.xyz('1','b',:c) # Should raise an exception.
@booch

This comment has been minimized.

Copy link
Owner Author

booch commented Jan 14, 2014

No idea how this ended up with 4-space tabbing.

@adkron

This comment has been minimized.

Copy link

adkron commented Jan 14, 2014

This is kind of cool, but kind of makes me sick.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.