Data Processing

Change Topic
  • Map - data projection from a list or array like data structure
  • Reduce - reduction of a list or array like data structure into a new aggregate object
  • Deferred Execution -
  • Deferred Execution with AST -

Python Language

TypeScript Language


Map

numbers = [1, 2, 3, 4, 5] squares = list(map(lambda x: x * x, numbers)) print(squares) # [1, 4, 9, 16, 25] evens = list(filter(lambda x: x % 2 == 0, numbers)) print(evens) # [2, 4]

Better implemented using a list comprehension:

numbers = [1, 2, 3, 4, 5] squares = [x * x for x in numbers]

Map

const numbers = [1, 2, 3, 4, 5]; const squares = numbers.map((n) => n * n); console.log(squares); // [1, 4, 9, 16, 25] const evens = numbers.filter((n) => n % 2 === 0); console.log(evens); // [2, 4]

Reduce

from functools import reduce sum_numbers = reduce(lambda acc, x: acc + x, numbers) print(sum_numbers) # 15

Better implemented using a list comprehension:

numbers = [1, 2, 3, 4, 5] squares = [x * x for x in numbers] sum_of_squares = sum(x * x for x in numbers)

Reduce

const sum = numbers.reduce((acc, n) => acc + n, 0);

console.log(sum); // 15

Deferred Execution

To defer execution of the call graph in Python, you can use lambda functions, generators, or callables to delay evaluation until explicitly invoked.

Using a lambda function:

def compute(): print("Running compute") return 42 lazy_result = lambda: compute() # Deferred print("Before calling") result = lazy_result() # Triggers execution print("Result:", result)

Using a generator:

def lazy_range(n): for i in range(n): print(f"Yielding {i}") yield i for num in lazy_range(3): print("Got:", num)

Deferred Execution

Support via libraries for deferred execution. RxJs and lodash/fp support pipelines, but these don't allow expression analysis for deferred execution.

import { of } from "rxjs"; import { map, filter } from "rxjs/operators"; const numbers$ = of(1, 2, 3, 4, 5).pipe( filter((n) => n % 2 === 0), // Deferred filter map((n) => n * n), // Deferred map ); // Execution only happens when subscribed numbers$.subscribe((result) => console.log(result)); // Output: 4, 16
import fp from "lodash/fp"; const numbers = [1, 2, 3, 4, 5]; const processNumbers = fp.pipe( fp.filter((n) => n % 2 === 0), // Deferred filter fp.map((n) => n * n), // Deferred map ); console.log(processNumbers(numbers)); // [4, 16]

Deferred Execution with AST

To defer execution and be able to analyze the AST of the expression passed in, use the ast and inspect modules to inspect a function or lambda expression.

import ast import inspect f = lambda x: x * x + 1 source = inspect.getsource(f) tree = ast.parse(source) print(ast.dump(tree, indent=4))

This gives you full access to the internal structure of the function before execution, enabling you to:

  • Perform static analysis
  • Rewrite or transform code safely
  • Enforce constraints or validations

For advanced manipulation, consider using libraries like astor, libcst, or RedBaron for AST round-tripping and source regeneration.


Deferred Execution With AST

JavaScript proxy support does allow for some analysis:

const handler = { get: (target, prop) => { return (...args) => { target.operations.push({ prop, args }); return target; }; }, }; function createExpression() { return new Proxy({ operations: [] }, handler); } const expr = createExpression(); expr.filter((x) => x > 2).map((x) => x * 2); console.log(expr.operations); // Output: [{ prop: 'filter', args: [Function] }, { prop: 'map', args: [Function] }]