Fundamentals 8 min read

Functions as Data Transformations: Recursion, Tail Calls, and Efficient Exponentiation & Fibonacci Implementations

The article treats functions as pure data‑to‑data mappings and demonstrates how common mathematical operations such as factorial, exponentiation, and Fibonacci can be expressed in TypeScript/JavaScript using recursive, tail‑recursive, iterative, and logarithmic‑time algorithms that illustrate functional transformation techniques and efficient algorithm design.

Youzan Coder
Youzan Coder
Youzan Coder
Functions as Data Transformations: Recursion, Tail Calls, and Efficient Exponentiation & Fibonacci Implementations

The article treats functions as pure data‑to‑data mappings and shows how to express common mathematical operations (factorial, exponentiation, Fibonacci) with recursive and tail‑recursive forms in TypeScript/JavaScript.

Factorial example (imperative version):

function fact(n: number): number {
    let result = 1;
    for (let i = 0; i <= n; i++) {
        result *= i;
    }
    return result;
}

It then discusses the idea that a function can be seen as a mapping between an input model and an output view, similar to the Model→View concept in React.

Simple recursive exponentiation:

function exp(a: number, n: number): number {
    return a * exp(a, n - 1);
}

This version suffers from O(n) recursive calls and possible stack overflow. A tail‑recursive version introduces an accumulator prev :

function expImpl(a: number, prev: number, i: number, n: number): number {
    if (i >= n) {
        return prev;
    }
    return expImpl(a, a * prev, i + 1, n);
}

The tail‑recursive call can be optimized by modern compilers into an iterative loop:

function exp(a: number, n: number): number {
    let i = n;
    let ret = 1;
    while (i > 0) {
        ret = ret * a;
        i--;
    }
    return ret;
}

Using the exponentiation identity (a^(n/2))² = (a²)^(n/2) for even n, a logarithmic‑time version is derived:

function fastExpImpl(a: number, prev: number, i: number): number {
    if (i <= 0) {
        return prev;
    }
    if (i % 2 === 0) {
        return fastExpImpl(a * a, prev, i / 2);
    }
    return fastExpImpl(a, a * prev, i - 1);
}
function fastExp(a: number, n: number): number {
    return fastExpImpl(a, 1, n);
}

The same transformation mindset is applied to the Fibonacci sequence. A naïve recursive definition:

function fib(n: number): number {
    if (n <= 2) {
        return 1;
    }
    return fib(n - 1) + fib(n - 2);
}

is replaced by a tail‑recursive version that carries the two previous values as parameters:

function fibImpl(a: number, b: number, i: number, n: number): number {
    if (i <= 1) {
        return a;
    }
    return fibImpl(a + b, a, i - 1, n);
}
function fib(n: number): number {
    return fibImpl(1, 0, n, n);
}

An equivalent iterative version is also provided:

function fibIter(n: number): number {
    let a = 1;
    let b = 0;
    let i = n;
    while (i > 1) {
        a = a + b;
        b = a;
        i--;
    }
    return a;
}

Finally, the article introduces a generic transformation T(p,q) that updates a pair (a,b) by the rules a←b·q + a·q + a·p and b←b·p + a·q. Applying T(p,q) twice yields another transformation T(p',q') whose parameters can be computed from the original p and q . This mirrors the fast exponentiation technique and leads to an O(log n) Fibonacci algorithm, illustrating how functional thinking simplifies algorithm design.

Author: 金智鑫, Team: 共享前端.

TypeScriptalgorithmFunctional Programmingrecursionexponentiationfibonaccitail-call
Youzan Coder
Written by

Youzan Coder

Official Youzan tech channel, delivering technical insights and occasional daily updates from the Youzan tech team.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.