Transducers are a type of reducing function that take in a reducing function and give back another reducing function. They allow you to compose functions together in a chain or pipeline structure to quickly, easily and efficiently transform data. In PHP, we have the mtdowling/transducers library, built off the basis of the idea of Clojure's transducer library.
20. Phone Tree as Transducer
use Transducers as t;
$employees = (new EmployeeService)->getAllEmployees();
$getNonManagerPhones = tcomp(
tfilter(function ($employee) {
return ! $employee->isManager();
}),
tmap(function ($employee) {
return $employee->getPhoneNumber();
})
);
$numbers = tto_array($getNonManagerPhones, $employees);
21. The Data
Name Number Manager
Bob 303-555-1212 Yes
Sue 303-555-1234 No
Barb 303-555-1111 No
Spongebob 303-555-1001 Yes
Arnold 303-555-1313 No
22. Collection Data Pipeline
Name Number Manager
Bob 303-555-1212 Yes
Sue 303-555-1234 No
Barb 303-555-1111 No
Spongebob 303-555-1001 Yes
Arnold 303-555-1313 No
Filter
Name Number Manager
Sue 303-555-1234 No
Barb 303-555-1111 No
Arnold 303-555-1313 No
Map
Number
303-555-1234
303-555-1111
303-555-1313
23. Transducer Data Flow
Name Number Manager
Bob 303-555-1212 Yes
Sue 303-555-1234 No
Barb 303-555-1111 No
Spongebob 303-555-1001 Yes
Arnold 303-555-1313 No
Number
303-555-1234
303-555-1111
303-555-1313
filter
map
NO
24. Transducer Data Sources
• Anything that you can use foreach on
• Arrays
• Iterators
• Traversables
• Generators
27. A Bigger Example
• Incoming TSV, but should be CSV
• Date format is wrong
• Names are not capitalized
• We need days from or until birthdate, for reasons
28. Transformer
use transducers as t;
/* SNIP Definition of the functions used below */
$transformer = tcomp(
tdrop(1), // Get rid of the header
tmap($convertToArray), // Turn TSV to Array
tmap($convertToDate), // Change to DateTimeImmutable Object
tmap($addDaysFromBirthday), // Date math
tmap($fixDateFormat), // Format DateTimeImmutable
// to Y-m-d string
$fixNames, // Capitalize names
);
35. Function to Build a Function
// Function to return a function
$ucField = function($field) {
return function ($row) use ($field) {
$row[$field] = ucfirst($row[$field]);
return $row;
};
};
36. Functionally Functional
$mungeField = function ($field, $munger) {
return function ($row) use ($field, $munger) {
$row[$field] = $munger($row[$field]);
return $row;
};
};
38. Revisit Transformer
use transducers as t;
/* SNIP Definition of the functions used below */
$transformer = tcomp(
tdrop(1), // Get rid of the header
tmap($convertToArray), // Turn TSV to Array
tmap($convertToDate), // Change to DateTimeImmutable Object
tmap($addDaysFromBirthday), // Date math
tmap($fixDateFormat), // Format DateTimeImmutable
// to Y-m-d string
$fixNames, // Capitalize names
);
45. Included Transducer
Functions
• map($f) - Apply $f function to each value in a
collection
• filter($predicate) - If predicate returns true, retain
the value, otherwise discard
• remove($predicate) - Removes items that satisfy the
predicate function
• cat() - Concatenates items from nested lists
46. More Included Functions
• partition($size) - Splits the source into arrays of the
specified size
• partition_by($predicate) - Splits input into arrays
when value returned by $predicate changes
• take($n) - Takes $n items from the collection
• take_while($predicate) - Takes items from the
collection while the $predicate is true
47. Even Moar!
• take_nth($n) - Takes every $n values from the
collection
• drop($n) - Drops $n items from the start of a
sequence
• drop_while($predicate) - Drops items from the
collection as long as $predicate returns true
• replace(array $map) - Replaces values in the
sequence according to the $map
48. Ermegerhd, even more?!
• keep($f) - Keeps items when $f does not
return null
• keep_indexed($f) - Returns the non-null
results of calling $f($index, $value)
• dedupe - Removes values that are the same
as the previous value in an ordered
sequence
• interpose($separator) - Adds the separator
between each value in a sequence
49. Last list, I promise
• tap($interceptor) - "Taps" into the chain, in
order to do something with the intermediate
result. Does not change the sequence
• compact() - Trims out all "falsey" values from
the sequence
• words() - Splits input into words
• lines() - Splits input by lines
50. Transducers
• Compose powerful data processing functions
• Interact with streams of data
• Easy to understand
• Simple to test