# Pair structure 

let pair = fun(first, second) {
    let dispatcher = fun(index) {
        if(index == 0) {
            return first;
        } 
        if(index == 1) {
            return second;
        }
    }
    return dispatcher;
}

let first = fun(somePair) {
    return somePair(0);
}

let second = fun(somePair) {
    return somePair(1);
}

let randomList = pair(1, pair(2, pair(3, pair(4, pair(5, null)))));

# Pair methods

let generateList = fun(x) {
    if(x == 0) {
        return null;
    }
    return pair(x, generateList(x - 1));
}


let map = fun(proc, items) {
    if(!items) {
        return null;
    }

    let current = first(items);
    let next = second(items);
    
    return pair(
        proc(current), 
        map(proc, next)
    );
}

let filter = fun(cond, items) {
    if(!items) {
        return null;
    }
    
    let current = first(items);
    let next = second(items);

    if(cond(current)) {
        return pair(
            current, 
            filter(cond, next)
        );
    }

    return filter(cond, next);
}

let forEach = fun(proc, items) {
    if(!items) {
        return null;
    }

    let current = first(items);
    let next = second(items);

    proc(current);
    forEach(proc,next);
}

# Pair example

let square = fun(x) {
    return x * x;
}

let printInline = fun(x) {
    print(toString(x) + " ");
}

let even = fun(x) {
    return x % 2 == 0;
}

let list = generateList(100);
let squareList = map(square, list);
let evenList = filter(even, squareList);
forEach(printInline, evenList);