計算機科学のブログ

Building Abstractions with Functions - Formulating Abstractions with Higher-Order Functions - Functions as Arguments - accumlate function, recursive process, iterative process

Structure and Interpretation of Computer Programs: JavaScript Edition(Harold Abelson(著)、Gerald Jay Sussman(著)、Julie Sussman(著)、The MIT Press)のChapter 1(Building Abstractions with Functions)、1.3(Formulating Abstractions with Higher-Order Functions)、1.3.1(Functions as Arguments)、Exercise 1.32の解答を求めてみる。

コード

function add(x, y) {
    return x + y;
}
function mul(x, y) {
    return x * y;
}
function inc(x) {
    return x + 1;
}
function identity(x) {
    return x;
}
function add2(x) {
    return x + 2;
}
function double(x) {
    return 2 * x;
}
console.log('a.')

function accumulate_recursive(combiner, null_value, term, a, next, b) {
    return a > b ?
        null_value :
        combiner(
            term(a),
            accumulate_recursive(combiner, null_value, term, next(a), next, b)
        );
}

function sum_recursive(term, a, next, b) {
    return accumulate_recursive(add, 0, term, a, next, b);
}
function product_recursive(term, a, next, b) {
    return accumulate_recursive(mul, 1, term, a, next, b);
}

console.log(sum_recursive(identity, 1, inc, 10));
console.log(sum_recursive(identity, 1, add2, 10));
console.log(sum_recursive(identity, 2, add2, 10));
console.log();

console.log(sum_recursive(double, 1, inc, 10));
console.log(sum_recursive(double, 1, add2, 10));
console.log(sum_recursive(double, 2, add2, 10));
console.log();

console.log(product_recursive(identity, 1, inc, 10));
console.log(product_recursive(identity, 1, add2, 10));
console.log(product_recursive(identity, 2, add2, 10));
console.log();

console.log(product_recursive(double, 1, inc, 10));
console.log(product_recursive(double, 1, add2, 10));
console.log(product_recursive(double, 2, add2, 10));
console.log();

console.log('b.');

function accumulate(combiner, null_value, term, a, next, b) {
    function iter(n, result) {
        return n > b ?
            result :
            iter(next(n), combiner(result, term(n)));
    }
    return iter(a, null_value);
}
function sum(term, a, next, b) {
    return accumulate(add, 0, term, a, next, b);
}
function product(term, a, next, b) {
    return accumulate(mul, 1, term, a, next, b);
}


console.log(sum(identity, 1, inc, 10));
console.log(sum(identity, 1, add2, 10));
console.log(sum(identity, 2, add2, 10));
console.log();

console.log(sum(double, 1, inc, 10));
console.log(sum(double, 1, add2, 10));
console.log(sum(double, 2, add2, 10));
console.log();

console.log(product(identity, 1, inc, 10));
console.log(product(identity, 1, add2, 10));
console.log(product(identity, 2, add2, 10));
console.log();

console.log(product(double, 1, inc, 10));
console.log(product(double, 1, add2, 10));
console.log(product(double, 2, add2, 10));
console.log();

入出力結果(Terminal, Zsh)

% node answer1.32.js
a.
55
25
30

110
50
60

3628800
945
3840

3715891200
30240
122880

b.
55
25
30

110
50
60

3628800
945
3840

3715891200
30240
122880

%