如何在源代码中查看Ruby方法#lcm?

时间:2016-06-11 07:03:35

标签: ruby

我正在努力了解#lcm的工作原理。它属于Integer类,如docs所示。我看过Ruby's github page,但我不知道如何导航它。

感谢。

2 个答案:

答案 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));
}