Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- module Types
- InvalidTypeError = Class.new(ArgumentError)
- def specify(spec, a_method)
- args_spec = []
- return_spec = nil
- case spec.first
- when Hash
- args_spec = spec.first.keys.first
- return_spec = spec.first.values.first
- when Array
- args_spec = spec.first
- else
- args_spec = spec
- end
- original_method = :"_#{a_method}_without_type_checking"
- alias_method original_method, a_method
- define_method(a_method) do |*args|
- ensure_correct_types(args_spec, args)
- result = send(original_method, *args)
- ensure_correct_types(return_spec, [result], what: "return value") if return_spec
- result
- end
- a_method
- end
- module InstanceMethods
- def ensure_correct_types(spec, args, what: "argument")
- Array(spec).each.with_index do |klass, index|
- raise InvalidTypeError, ["Type for #{what}:", klass, "for" , args[index]&.inspect || "-missing #{index.succ} argument-", args[index].class].join(" ") if klass && !(klass === args[index])
- end
- end
- end
- private_constant :InstanceMethods
- def self.extended(mod)
- mod.include InstanceMethods
- end
- end
- Object.extend Types
- class Foo
- specify [String],
- def foo(arg)
- 42
- end
- specify [String => Numeric],
- def bar(arg)
- 42
- end
- specify [[String, String]],
- def foo2(arg1, arg2)
- 42
- end
- specify [[String, String] => Numeric],
- def bar2(arg1, arg2)
- 42
- end
- end
- Foo.new.foo("42")
- Foo.new.bar2("42", ?x)
Add Comment
Please, Sign In to add comment