def gcd(a, b):
    return a if b == 0 else gcd(b, a % b)

def install_rational_package():
    # internal functions
    def numer(x):
        return head(x)
    def denom(x):
        return tail(x)
    def make_rat(n, d):
        g = gcd(n, d)
        return pair(n // g, d // g)
    def add_rat(x, y):
        return make_rat(numer(x) * denom(y) +
                        numer(y) * denom(x),
                        denom(x) * denom(y))
    def sub_rat(x, y):
        return make_rat(numer(x) * denom(y) -
                        numer(y) * denom(x),
                        denom(x) * denom(y))
    def mul_rat(x, y):
        return make_rat(numer(x) * numer(y),
                        denom(x) * denom(y))
    def div_rat(x, y):
        return make_rat(numer(x) * denom(y),
                        denom(x) * numer(y))
    # interface to rest of the system
    def tag(x):
        return attach_tag("rational", x)
    put("add", llist("rational", "rational"),
        lambda x, y: tag(add_rat(x, y)))
    put("sub", llist("rational", "rational"),
        lambda x, y: tag(sub_rat(x, y)))
    put("mul", llist("rational", "rational"),
        lambda x, y: tag(mul_rat(x, y)))
    put("div", llist("rational", "rational"),
        lambda x, y: tag(div_rat(x, y)))
    put("make", "rational",
        lambda n, d: tag(make_rat(n, d)))
install_rational_package()

def make_rational(n, d):
    return get("make", "rational")(n, d)
