Last active
August 29, 2015 14:21
-
-
Save archseer/abd6ead4e7482425d428 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Adapted from http://phuu.net/2014/08/31/csp-and-transducers.html | |
compose = -> (f, g) { | |
return -> x { f.(g.(x)) } | |
} | |
fn = compose.(-> x {x + 1}, -> x {x * 3}) | |
fn.(1) | |
# Map function derivation | |
# 1 | |
[1,2,3,4].map do |input| | |
input + 1 | |
end # => [2,3,4,5] | |
# 2 | |
concat = -> (a, b) { a.concat([b]) } | |
[1,2,3,4].reduce([]) do |result, input| | |
concat.(result, input + 1) | |
end # => [2,3,4,5] | |
# 3 | |
inc = -> x { x + 1 } | |
map = -> (transform, collection) { | |
return collection.reduce([]) do |result, input| | |
concat.(result, transform.(input)) | |
end | |
} | |
map.(inc, [1,2,3,4]) | |
# Algorithmic transformations | |
## Basic filter | |
[1,2,3,4].select do |input| #.filter | |
input > 2 | |
end # => [3,4] | |
## Filter with reduce | |
[1,2,3,4].reduce([]) do |result, input| | |
input > 2 ? | |
concat.(result, input) : | |
result | |
end # => [3,4] | |
## Transform (called the predicate) | |
greaterThanTwo = -> x { | |
return x > 2 | |
} | |
## And finally, filter as function | |
filter = -> (predicate, collection) { | |
return collection.reduce([]) do |result, input| | |
predicate.(input) ? | |
concat.(result, input) : | |
result | |
end | |
} | |
## Run it! | |
filter.(greaterThanTwo, [1,2,3,4]) # => [3,4] | |
## Compose! | |
incrementAndFilter = compose.( | |
-> x { filter.(greaterThanTwo, x)}, | |
-> x { map.(inc, x)}, | |
) | |
incrementAndFilter.([1,2,3,4]) # => [3,4,5] | |
# Reducing functions | |
mapper = -> (transform) { | |
return -> (result, input) { | |
return concat.(result, transform.(input)) | |
} | |
} | |
filterer = -> (predicate) { | |
return -> (result, input) { | |
predicate.(input) ? | |
concat.(result, input) : | |
result | |
} | |
} | |
[1,2,3,4].reduce([], &mapper.(inc)) # => [2,3,4,5] | |
[1,2,3,4].reduce([], &filterer.(greaterThanTwo)) # => [3,4] | |
## Identity function | |
identity = -> (x) { x } | |
[1,2,3,4].reduce([], &mapper.(identity)) # => [1,2,3,4] | |
## Filter with mapper | |
lessThanThree = -> x { | |
return x < 3 | |
} | |
mapper = -> (transform) { | |
return -> (result, input) { | |
return concat.(result, transform.(input)) | |
} | |
} | |
filterer = -> (predicate) { | |
return -> (result, input) { | |
predicate.(input) ? | |
mapper.(identity).(result, input) : | |
result | |
} | |
} | |
[1,2,3,4].reduce([], &filterer.(lessThanThree)) # => [1,2] | |
## Getting to transformations | |
mapping = -> (transform) { | |
return -> (reduce) { | |
return -> (result, input) { | |
return reduce.(result, transform.(input)) | |
} | |
} | |
} | |
filtering = -> (predicate) { | |
return -> (reduce) { | |
return -> (result, input) { | |
predicate.(input) ? | |
reduce.(result, input) : | |
result | |
} | |
} | |
} | |
filterLessThanThreeAndIncrement = compose.( | |
filtering.(lessThanThree), | |
mapping.(inc), | |
) | |
[1,2,3,4].reduce([], &filterLessThanThreeAndIncrement.(concat)) # => [2,3] | |
### Changing the reducer | |
[1,2,3,4].reduce({}, &filterLessThanThreeAndIncrement.(-> (result, input) { | |
result[input] = true | |
return result | |
})) # => { 2: true, 3: true } | |
### Complex data | |
posts = [ | |
{ author: 'Agatha', text: 'just setting up my pstr' }, | |
{ author: 'Bert', text: 'Ed Balls' }, | |
{ author: 'Agatha', text: '@Bert fancy a thumb war?' }, | |
{ author: 'Charles', text: '#subtweet' }, | |
{ author: 'Bert', text: 'Ed Balls' }, | |
{ author: 'Agatha', text: '@Bert m(' } | |
] | |
graph = -> (result, input) { | |
(result[input[:from]] ||= []) << input[:to] | |
return result | |
} | |
extractMentions = compose.( | |
# Find mentions | |
filtering.(-> (post) { | |
return post[:text].match(/^@/) | |
}), | |
# Build object with {from, to} keys | |
mapping.(-> (post) { | |
return { | |
from: post[:author], | |
to: post[:text].split(' ').shift.sub(/^@/, '') | |
} | |
}) | |
) | |
puts posts.reduce({}, &extractMentions.(graph)) | |
# => { Agatha: ['Bert', 'Charles'], | |
# Bert: ['Agatha'], | |
# Charles: ['Bert'] } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment