Created
July 3, 2021 19:14
-
-
Save JoshCheek/60afe9a95fec6f538fa861ad4c2f52e5 to your computer and use it in GitHub Desktop.
Alternative version of type checking that doesn't use method_added
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
# convo: https://twitter.com/dorianmariefr/status/1411306589739433984 | |
# alternative to this: https://gist.github.com/JoshCheek/df6154555387f966ef1808262e38f72e | |
# We'll ignore everything except required args, to keep it simpler | |
private def with_types(*ordtypes, name) | |
# I guess this works for main, and singleton methods on `self`, but not singleton methods | |
owner = is_a?(Module) ? self : method(name).owner | |
meth = owner.instance_method(name) | |
params = meth.parameters | |
ordtypes.size == params.size or raise TypeError, "#{ordtypes.inspect} does not match signature: #{params.inspect}" | |
meth.owner.define_method name do |*ords| | |
ords.size == ordtypes.size or raise ArgumentError, "wrong # of args, expected #{ordtypes.inspect}, got #{ords.inspect}" | |
ords.zip(ordtypes).each_with_index do |(ord, type), i| | |
type === ord or raise TypeError, "arg #{i} of `#{name}': #{type.inspect}, does not match #{ord.inspect}" | |
end | |
meth.bind(self).call(*ords) | |
end | |
end | |
# Provided example | |
with_types Integer, Integer, def add(a, b) | |
a + b | |
end | |
add 1, 2 # => 3 | |
add 'a', 'b' rescue $! # => #<TypeError: arg 0 of `add': Integer, does not match "a"> | |
# With mismatched signature | |
with_types Integer, Integer, def add2(arg) | |
arg | |
end rescue $! # => #<TypeError: [Integer, Integer] does not match signature: [[:req, :arg]]> | |
# On a class | |
class String | |
with_types String, def add(rhs) | |
self + rhs | |
end | |
end | |
"a".add "b" # => "ab" | |
"a".add 5 rescue $! # => #<TypeError: arg 0 of `add': String, does not match 5> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment