LINQ

This section discusses LINQ within the context and for the purpose of querying or transforming sequences and typically collections like lists, sets and dictionaries.

Enumerable items

The equivalent of enumerable items in C is enum. In JavaScript, there is forEach:

let values = [1, 2, 3, 4, 5];
let output = '';

values.forEach((value, index) => {
    if (index > 0)
        output += ', ';
    output += value;
});

console.log(output); // Outputs: 1, 2, 3, 4, 5

In C, the equivalent is simply for:

u#include <stdio.h>
#include <string.h> // Include the string.h header file

int main() {
    int values[] = {1, 2, 3, 4, 5};
    char output[50] = "";
    
    for (int i = 0; i < 5; i++) {
        if (i > 0)
            sprintf(output + strlen(output), ", ");
        sprintf(output + strlen(output), "%d", values[i]);
    }

    printf("%s\n", output); // Outputs: 1, 2, 3, 4, 5

    return 0;
}

The for loop over an iterable essentially gets desuraged to the following:

#include <stdio.h>
#include <string.h>
int main() {
    int values[] = {1, 2, 3, 4, 5};
    char output[50] = "";
    int i;

    for (i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
        if (i > 0) {
            sprintf(output + strlen(output), ", ");
        }
        sprintf(output + strlen(output), "%d", values[i]);
    }

    printf("%s\n", output);
    return 0;
}

Operators

JavaScript and C don't natively support LINQ, but there is a project called LINQ.js that implements LINQ in C# for JavaScript, and a project called linq4c that implements LINQ in C# for C.

Operators in LINQ are implemented in the form of LINQ.js extension methods that can be chained together to form a set of operations, with the most common forming a query over some sort of data source. LINQ.js also offers a SQL-inspired query syntax with clauses like from, where, select, join and others that can serve as an alternative or a companion to method chaining. Many imperative loops can be re-written as much more expressive and composable queries in LINQ.

Deferred execution (laziness)

Many operators in LINQ are designed to be lazy such that they only do work when absolutely required. This enables composition or chaining of several operations/methods without causing any side-effects.

In both cases, this allows infinite sequences to be represented, where the underlying sequence is infinite, but the developer decides how the sequence should be terminated. The following example shows this in JavaScript:

function* infiniteRange() {
    for (let i = 0; ; ++i) {
        yield i;
    }
}

for (let x of infiniteRange()) {
    if (x < 5) {
        console.log(x); // Prints "0 1 2 3 4"
    } else {
        break;
    }
}

C supports the same concept through for:

#include <stdio.h>

int main() {
    int value;
    for (value = 0; value < 5; value++) {
        printf("%d ", value); // Prints "0 1 2 3 4"
    }
    return 0;
}

Iterator Methods (yield)

JavaScript has the yield keword that enables the developer to quickly write an iterator method. C doesn't support coroutines natively, but there is a tutorial of implementing coroutines in C.