mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Add Integer.try_convert [Feature #15211]
This commit is contained in:
parent
eee709595c
commit
301d194ee3
Notes:
git
2021-07-16 17:50:23 +09:00
6 changed files with 83 additions and 3 deletions
5
NEWS.md
5
NEWS.md
|
@ -92,6 +92,10 @@ Outstanding ones only.
|
||||||
* File.dirname now accepts an optional argument for the level to
|
* File.dirname now accepts an optional argument for the level to
|
||||||
strip path components. [[Feature #12194]]
|
strip path components. [[Feature #12194]]
|
||||||
|
|
||||||
|
* Integer
|
||||||
|
|
||||||
|
* Integer.try_convert is added. [[Feature #15211]]
|
||||||
|
|
||||||
* Module
|
* Module
|
||||||
|
|
||||||
* Module#prepend now modifies the ancestor chain if the receiver
|
* Module#prepend now modifies the ancestor chain if the receiver
|
||||||
|
@ -191,6 +195,7 @@ Excluding feature bug fixes.
|
||||||
[Feature #12194]: https://bugs.ruby-lang.org/issues/12194
|
[Feature #12194]: https://bugs.ruby-lang.org/issues/12194
|
||||||
[Feature #14256]: https://bugs.ruby-lang.org/issues/14256
|
[Feature #14256]: https://bugs.ruby-lang.org/issues/14256
|
||||||
[Feature #15198]: https://bugs.ruby-lang.org/issues/15198
|
[Feature #15198]: https://bugs.ruby-lang.org/issues/15198
|
||||||
|
[Feature #15211]: https://bugs.ruby-lang.org/issues/15211
|
||||||
[Feature #16043]: https://bugs.ruby-lang.org/issues/16043
|
[Feature #16043]: https://bugs.ruby-lang.org/issues/16043
|
||||||
[Feature #16806]: https://bugs.ruby-lang.org/issues/16806
|
[Feature #16806]: https://bugs.ruby-lang.org/issues/16806
|
||||||
[Feature #17312]: https://bugs.ruby-lang.org/issues/17312
|
[Feature #17312]: https://bugs.ruby-lang.org/issues/17312
|
||||||
|
|
|
@ -77,6 +77,7 @@ VALUE rb_int_lshift(VALUE x, VALUE y);
|
||||||
VALUE rb_int_div(VALUE x, VALUE y);
|
VALUE rb_int_div(VALUE x, VALUE y);
|
||||||
int rb_int_positive_p(VALUE num);
|
int rb_int_positive_p(VALUE num);
|
||||||
int rb_int_negative_p(VALUE num);
|
int rb_int_negative_p(VALUE num);
|
||||||
|
VALUE rb_check_integer_type(VALUE);
|
||||||
VALUE rb_num_pow(VALUE x, VALUE y);
|
VALUE rb_num_pow(VALUE x, VALUE y);
|
||||||
VALUE rb_float_ceil(VALUE num, int ndigits);
|
VALUE rb_float_ceil(VALUE num, int ndigits);
|
||||||
VALUE rb_float_floor(VALUE x, int ndigits);
|
VALUE rb_float_floor(VALUE x, int ndigits);
|
||||||
|
|
|
@ -5247,6 +5247,12 @@ rb_int_s_isqrt(VALUE self, VALUE num)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
int_s_try_convert(VALUE self, VALUE num)
|
||||||
|
{
|
||||||
|
return rb_check_integer_type(num);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Document-class: ZeroDivisionError
|
* Document-class: ZeroDivisionError
|
||||||
*
|
*
|
||||||
|
@ -5473,6 +5479,7 @@ Init_Numeric(void)
|
||||||
rb_undef_alloc_func(rb_cInteger);
|
rb_undef_alloc_func(rb_cInteger);
|
||||||
rb_undef_method(CLASS_OF(rb_cInteger), "new");
|
rb_undef_method(CLASS_OF(rb_cInteger), "new");
|
||||||
rb_define_singleton_method(rb_cInteger, "sqrt", rb_int_s_isqrt, 1);
|
rb_define_singleton_method(rb_cInteger, "sqrt", rb_int_s_isqrt, 1);
|
||||||
|
rb_define_singleton_method(rb_cInteger, "try_convert", int_s_try_convert, 1);
|
||||||
|
|
||||||
rb_define_method(rb_cInteger, "to_s", int_to_s, -1);
|
rb_define_method(rb_cInteger, "to_s", int_to_s, -1);
|
||||||
rb_define_alias(rb_cInteger, "inspect", "to_s");
|
rb_define_alias(rb_cInteger, "inspect", "to_s");
|
||||||
|
|
16
object.c
16
object.c
|
@ -3232,19 +3232,23 @@ rb_check_convert_type_with_id(VALUE val, int type, const char *tname, ID method)
|
||||||
#define try_to_int(val, mid, raise) \
|
#define try_to_int(val, mid, raise) \
|
||||||
convert_type_with_id(val, "Integer", mid, raise, -1)
|
convert_type_with_id(val, "Integer", mid, raise, -1)
|
||||||
|
|
||||||
ALWAYS_INLINE(static VALUE rb_to_integer(VALUE val, const char *method, ID mid));
|
ALWAYS_INLINE(static VALUE rb_to_integer_with_id_exception(VALUE val, const char *method, ID mid, int raise));
|
||||||
|
/* Integer specific rb_check_convert_type_with_id */
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
rb_to_integer(VALUE val, const char *method, ID mid)
|
rb_to_integer_with_id_exception(VALUE val, const char *method, ID mid, int raise)
|
||||||
{
|
{
|
||||||
VALUE v;
|
VALUE v;
|
||||||
|
|
||||||
if (RB_INTEGER_TYPE_P(val)) return val;
|
if (RB_INTEGER_TYPE_P(val)) return val;
|
||||||
v = try_to_int(val, mid, TRUE);
|
v = try_to_int(val, mid, raise);
|
||||||
|
if (!raise && NIL_P(v)) return Qnil;
|
||||||
if (!RB_INTEGER_TYPE_P(v)) {
|
if (!RB_INTEGER_TYPE_P(v)) {
|
||||||
conversion_mismatch(val, "Integer", method, v);
|
conversion_mismatch(val, "Integer", method, v);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
#define rb_to_integer(val, method, mid) \
|
||||||
|
rb_to_integer_with_id_exception(val, method, mid, TRUE)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to convert \a val into \c Integer.
|
* Tries to convert \a val into \c Integer.
|
||||||
|
@ -3371,6 +3375,12 @@ rb_Integer(VALUE val)
|
||||||
return rb_convert_to_integer(val, 0, TRUE);
|
return rb_convert_to_integer(val, 0, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_check_integer_type(VALUE val)
|
||||||
|
{
|
||||||
|
return rb_to_integer_with_id_exception(val, "to_int", idTo_int, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rb_bool_expected(VALUE obj, const char *flagname)
|
rb_bool_expected(VALUE obj, const char *flagname)
|
||||||
{
|
{
|
||||||
|
|
40
spec/ruby/core/integer/try_convert_spec.rb
Normal file
40
spec/ruby/core/integer/try_convert_spec.rb
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
require_relative '../../spec_helper'
|
||||||
|
require_relative 'fixtures/classes'
|
||||||
|
|
||||||
|
ruby_version_is "3.1" do
|
||||||
|
describe "Integer.try_convert" do
|
||||||
|
it "returns the argument if it's an Integer" do
|
||||||
|
x = 42
|
||||||
|
Integer.try_convert(x).should equal(x)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns nil when the argument does not respond to #to_int" do
|
||||||
|
Integer.try_convert(Object.new).should be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sends #to_int to the argument and returns the result if it's nil" do
|
||||||
|
obj = mock("to_int")
|
||||||
|
obj.should_receive(:to_int).and_return(nil)
|
||||||
|
Integer.try_convert(obj).should be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sends #to_int to the argument and returns the result if it's an Integer" do
|
||||||
|
x = 234
|
||||||
|
obj = mock("to_int")
|
||||||
|
obj.should_receive(:to_int).and_return(x)
|
||||||
|
Integer.try_convert(obj).should equal(x)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sends #to_int to the argument and raises TypeError if it's not a kind of Integer" do
|
||||||
|
obj = mock("to_int")
|
||||||
|
obj.should_receive(:to_int).and_return(Object.new)
|
||||||
|
-> { Integer.try_convert obj }.should raise_error(TypeError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not rescue exceptions raised by #to_int" do
|
||||||
|
obj = mock("to_int")
|
||||||
|
obj.should_receive(:to_int).and_raise(RuntimeError)
|
||||||
|
-> { Integer.try_convert obj }.should raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -660,4 +660,21 @@ class TestInteger < Test::Unit::TestCase
|
||||||
def o.fdiv(x); 1; end
|
def o.fdiv(x); 1; end
|
||||||
assert_equal(1.0, 1.fdiv(o))
|
assert_equal(1.0, 1.fdiv(o))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_try_convert
|
||||||
|
assert_equal(1, Integer.try_convert(1))
|
||||||
|
assert_equal(1, Integer.try_convert(1.0))
|
||||||
|
assert_nil Integer.try_convert("1")
|
||||||
|
o = Object.new
|
||||||
|
assert_nil Integer.try_convert(o)
|
||||||
|
def o.to_i; 1; end
|
||||||
|
assert_nil Integer.try_convert(o)
|
||||||
|
o = Object.new
|
||||||
|
def o.to_int; 1; end
|
||||||
|
assert_equal(1, Integer.try_convert(o))
|
||||||
|
|
||||||
|
o = Object.new
|
||||||
|
def o.to_int; Object.new; end
|
||||||
|
assert_raise_with_message(TypeError, /can't convert Object to Integer/) {Integer.try_convert(o)}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue