How different languages handle the processing of data through projection and aggregation.
Data Processing
TypeScript Language
Go Language Map/Reduce
Map
Data projection from a list or array-like data structure.
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]
In Go, mapping a function over a slice requires iteration using for
loops or the range
keyword.
Example: Mapping a function to square numbers
package main import ( "fmt" ) func square(n int) int { return n * n } func mapSlice(nums []int, fn func(int) int) []int { result := make([]int, len(nums)) for i, num := range nums { result[i] = fn(num) } return result } func main() { numbers := []int{1, 2, 3, 4, 5} squares := mapSlice(numbers, square) fmt.Println(squares) // [1, 4, 9, 16, 25] }
Example: Filtering Even Numbers
package main import "fmt" func filterSlice(nums []int, predicate func(int) bool) []int { result := []int{} for _, num := range nums { if predicate(num) { result = append(result, num) } } return result } func main() { numbers := []int{1, 2, 3, 4, 5} evens := filterSlice(numbers, func(n int) bool { return n%2 == 0 }) fmt.Println(evens) // [2, 4] }
Reduce
Reduction of a list or array-like data structure into a new aggregate object.
const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(sum); // 15
Go does not have a built-in reduce
function like Python, but you can implement one using iteration.
Example: Reducing a Slice to Sum All Elements
package main import "fmt" func reduce(nums []int, fn func(int, int) int, initial int) int { result := initial for _, num := range nums { result = fn(result, num) } return result } func main() { numbers := []int{1, 2, 3, 4, 5} sumNumbers := reduce(numbers, func(acc, n int) int { return acc + n }, 0) fmt.Println(sumNumbers) // 15 }
Better Alternative using a Simple Loop
package main import "fmt" func main() { numbers := []int{1, 2, 3, 4, 5} sum := 0 for _, num := range numbers { sum += num } fmt.Println(sum) // 15 }
Deferred Execution
Execution of operations is delayed until necessary.
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]
Go provides deferred execution using the defer
keyword. This is typically used for resource cleanup, ensuring that certain actions (such as closing files or unlocking mutexes) occur before the function exits.
Example: Deferring Execution
package main import "fmt" func main() { fmt.Println("Start") defer fmt.Println("This will be printed last") fmt.Println("Middle") }
Output:
Start Middle This will be printed last
Deferred Execution with AST
Execution is deferred and represented as an Abstract Syntax Tree (AST).
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] }]
Go does not have an equivalent to Python’s AST manipulation for execution deferral, but it does provide reflection and closures that allow dynamic execution.
Example: Using Closures for Deferred Execution
package main import ( "fmt" ) func deferredExecution(fn func()) { defer fn() } func main() { deferredExecution(func() { fmt.Println("Deferred function executed") }) fmt.Println("Main function finished") }
Output:
Main function finished Deferred function executed