Collections: map, filter, reduce
The same pipeline in all seven languages: take a list of integers, keep the even ones, double each, then sum the result (answer: 24). Watch where each language puts the transformation — chained methods on the data (guji, Raku, Rust), free functions wrapping the data (Python, OCaml), or right-to-left composition you read inside-out (Perl). Notice too whether reduce needs an explicit seed and whether the intermediate steps allocate new lists or stream lazily.
“Computer language design is just like a stroll in the park. Jurassic Park, that is.” — Larry Wall
sub main(): Int {
@nums = [1, 2, 3, 4, 5, 6]
$total = @nums
.filter({ $_ % 2 == 0 })
.map({ $_ * 2 })
.reduce(0, sub($acc, $x) { $acc + $x })
print("evens doubled, summed: $total")
0
}Every prelude function is data-first (§7.2), so filter/map/reduce chain left-to-right with . — there is no separate pipeline operator. The single-argument steps use a topic block { ... } whose implicit parameter is $_; reduce takes a seed plus a two-parameter lambda written as an anonymous sub. This whole chain could collapse to .filter(...).map(...).sum(), but spelling out reduce shows the fold explicitly.
package main
import "fmt"
func main() {
nums := []int{1, 2, 3, 4, 5, 6}
total := 0
for _, x := range nums {
if x%2 == 0 {
total += x * 2
}
}
fmt.Printf("evens doubled, summed: %d\n", total)
}Go's standard idiom is an explicit for ... range loop with the filter, map, and accumulate fused into one pass — there is no built-in map/filter/reduce over slices. Generic helpers exist (slices in 1.21+, and iter.Seq range-over-func in 1.23+), but for a concrete pipeline like this most Go code just writes the loop. It is the most verbose example here and also the one with zero intermediate allocations.
let () =
let nums = [1; 2; 3; 4; 5; 6] in
let total =
nums
|> List.filter (fun x -> x mod 2 = 0)
|> List.map (fun x -> x * 2)
|> List.fold_left ( + ) 0
in
Printf.printf "evens doubled, summed: %d\n" totalOCaml's List module supplies filter, map, and fold_left as ordinary functions; the |> pipe threads the list through them left-to-right, reading top-to-bottom like the method chains. fold_left ( + ) 0 is reduce with the (+) operator passed as a plain function value. Each stage builds a fresh list, so for hot paths one would reach for List.fold_left alone or the lazy Seq module.
use strict;
use warnings;
use List::Util qw(reduce);
my @nums = (1, 2, 3, 4, 5, 6);
my $total = reduce { $a + $b } 0,
map { $_ * 2 }
grep { $_ % 2 == 0 } @nums;
print "evens doubled, summed: $total\n";Perl spells the pipeline right-to-left, so you read it inside-out: grep (filter) runs first, then map, then reduce from List::Util. The block forms use the implicit $_ topic, while reduce exposes the running pair as the package globals $a and $b. Passing 0 as the first list element seeds the fold so an empty input still yields 0.
my @nums = 1, 2, 3, 4, 5, 6;
my $total = @nums
.grep(* %% 2)
.map(* * 2)
.reduce(&[+]) // 0;
say "evens doubled, summed: $total";Raku chains methods on the list like guji: grep filters, map transforms, reduce folds. The * is the Whatever star building a one-argument closure, and %% is the built-in divisible-by operator, so * %% 2 reads as “divisible by 2.” &[+] passes the + operator as a function to reduce; the // 0 guards the empty case, since reduce on an empty list returns Nil.
fn main() {
let nums = [1, 2, 3, 4, 5, 6];
let total: i32 = nums
.iter()
.filter(|&&x| x % 2 == 0)
.map(|&x| x * 2)
.sum();
println!("evens doubled, summed: {total}");
}Rust builds a lazy iterator chain: filter and map are adapters that do nothing until a consumer drives them, and sum() (a specialized reduce/fold) is what actually runs the pipeline in a single pass with no intermediate Vec. The &&x and &x patterns dereference the borrowed i32s that .iter() yields. Writing .fold(0, |acc, x| acc + x) instead of .sum() would make the reduce explicit.
from functools import reduce
nums = [1, 2, 3, 4, 5, 6]
evens = filter(lambda x: x % 2 == 0, nums)
doubled = map(lambda x: x * 2, evens)
total = reduce(lambda acc, x: acc + x, doubled, 0)
print(f"evens doubled, summed: {total}")Python keeps map and filter as built-in functions that wrap the data and return lazy iterators, while reduce lives in functools. Each takes the function first and the iterable second — the opposite argument order from the data-first chains above. Most Pythonistas would actually write this as a comprehension, sum(x * 2 for x in nums if x % 2 == 0), which is shorter and the more idiomatic spelling.