我正在努力了解#lcm
的工作原理。它属于Integer
类,如docs所示。我看过Ruby's github page,但我不知道如何导航它。
感谢。
答案 0 :(得分:3)
如果您将鼠标悬停在Ruby文档中的某个方法上,则会看到"点击切换来源"在右边。点击它,你就会看到它的定义:
VALUE
rb_lcm(VALUE self, VALUE other)
{
other = nurat_int_value(other);
return f_lcm(self, other);
}
这当然是C代码,而不是Ruby。许多Ruby的核心模块都是用C实现的。对于这些模块,我推荐另一个信息来源:Ruby Cross-Reference。在那里,您可以搜索任何C标识符,例如rb_lcm
,并查找其定义。在Integer#lcm
的情况下,它实际上是defined in rational.c
(您可以在GitHub的根目录中找到它)。在那里,您可以点击f_lcm
查看its definition:
static VALUE
f_lcm(VALUE x, VALUE y)
{
if (f_zero_p(x) || f_zero_p(y))
return ZERO;
return f_abs(f_mul(f_div(x, f_gcd(x, y)), y));
}
......等等。
答案 1 :(得分:2)
就个人而言,我更倾向于阅读Rubinius's source code而非阅读YARV。 Rubinius的结构更好,更好的因素,最重要的是,大部分内容是用Ruby程序员非常熟悉的语言编写的,即Ruby:
def lcm(other)
raise TypeError, "Expected Integer but got #{other.class}" unless other.kind_of?(Integer)
if self.zero? or other.zero?
0
else
(self.div(self.gcd(other)) * other).abs
end
end
IronRuby's source code结构合理,但不幸的是不再真正维护:
[RubyMethod("lcm")]
public static object/*!*/ Lcm(int self, int other) {
return Lcm(self, other, SignedGcd(self, other));
}
[RubyMethod("lcm")]
public static object/*!*/ Lcm(BigInteger/*!*/ self, BigInteger/*!*/ other) {
return Lcm(self, other, SignedGcd(self, other));
}
[RubyMethod("lcm")]
public static object/*!*/ Lcm(object/*!*/ self, object other) {
throw RubyExceptions.CreateTypeError("not an integer");
}
我的第三个选择是JRuby:
public IRubyObject lcm(ThreadContext context, IRubyObject other) {
checkInteger(context, other);
return f_lcm(context, this, RubyRational.intValue(context, other));
}
哪个指向this:
public static IRubyObject f_lcm(ThreadContext context, IRubyObject x, IRubyObject y) {
if (f_zero_p(context, x) || f_zero_p(context, y)) {
return RubyFixnum.zero(context.runtime);
}
return f_abs(context, f_mul(context, f_div(context, x, f_gcd(context, x, y)), y));
}