- 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 -
Data Processing
Change TopicPython 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] }]