# Waquo/combinators-info.github.com

### Subversion checkout URL

You can clone with HTTPS or Subversion.

Fetching contributors…

Cannot retrieve contributors at this time

186 lines (149 sloc) 18.717 kb
 3 The Thrush

3 The Thrush

In Combinatory Logic, the thrush is an extremely simple permuting combinator; it reverses the normal order of evaluation. The thrush is written Txy = yx. It reverses evaluation. In Ruby terms,

thrush.call(a_value).call(a_proc)
=> a_proc.call(a_value)

In No Detail Too Small, I defined Object#into, an implementation of the thrush as a Ruby method:

class Object
def into expr = nil
expr.nil? ? yield(self) : expr.to_proc.call(self)
end
end

If you are in the habit of violating the Law of Demeter, you can use #into to make an expression read consistently from left to right. For example, this code:

lambda { |x| x * x }.call((1..100).select(&:odd?).inject(&:+))

Reads “Square (take the numbers from 1 to 100, select the odd ones, and take the sum of those).” Confusing. Whereas with #into, you can write:

(1..100).select(&:odd?).inject(&:+).into { |x| x * x }

Which reads “Take the numbers from 1 to 100, keep the odd ones, take the sum of those, and then answer the square of that number.”

A permuting combinator like #into is not strictly necessary when you have parentheses or local variables. Which is kind of interesting, because it shows that if you have permuting combinators, you can model parentheses and local variables.

But we are not interested in theory. #into may be equivalent to what we can accomplish with other means, but it is useful to us if we feel it makes the code clearer and easier to understand. Sometimes a longer expression should be broken into multiple small expressions to make it easier to understand. Sometimes it can be reordered using tools like #into.

3.1 Let

Object#into defines the thrush as a method that takes a block, lambda, or anything that can become a block or lambda as its argument. There is another way to formulate a Thrush:

class Kernel
def let it
yield it
end
end

It’s remarkably simple, so simple that it appears to be less useful than #into. The example above would look like this if we used let:

let (1..100).select(&:odd?).inject(&:+) do |x|
x * x
end

How does that help? I’ll let you in on a secret: Ruby 1.9 changes the game. In Ruby 1.8, x is local to the surrounding method, so it doesn’t help. But in Ruby 1.9, x is a block local variable, meaning that it does not clobber an existing variable. So in Ruby 1.8:

def say_the_square_of_the_sum_of_the_odd_numbers(x)
sotos = let (1..x).select(&:odd?).inject(&:+) do |x|
x * x
end
"The square of the sum of the odd numbers from 1..#{x} is #{sotos}"
end

say_the_square_of_the_sum_of_the_odd_numbers(10)
=> "The square of the sum of the odd numbers from 1..25 is 625"

1..25!? What happened here is that the x inside the block clobbered the value of the x parameter. Not good. In Ruby 1.9:

say_the_square_of_the_sum_of_the_odd_numbers(10)
=> "The square of the sum of the odd numbers from 1..10 is 625"

Much better, Ruby 1.9 creates a new scope inside the block and x is local to that block, shadowing the x parameter. Now we see a use for let:

let(some_expression) do |my_block_local_variable|
# ...
end

let creates a new scope and defines your block local variable inside the block. This signals that the block local variable is not used elsewhere. Imperative methods can be easier to understand when they are composed of smaller blocks with well-defined dependencies between them. A variable local to the entire method creates a dependency across the entire method. A variable local to a block only creates dependencies within that block.

Although Ruby 1.8 does not enforce this behaviour, it can be useful to write code in this style as a signal to make the code easier to read.

Summary

We have seen two formulations of the thrush combinator, #into and let. One is useful for making expressions more consistent and easier to read, the other for signaling the scope of block-local variables.

1. 0.1 The MIT License
2. 0.2 Preface
3. 1 Introduction
4. 2 Kestrels
5. 2.1 Object initializer blocks
6. 2.2 Inside, an idiomatic Ruby Kestrel
7. 2.3 The Enchaining Kestrel
8. 2.4 The Obdurate Kestrel
9. 2.5 Kestrels on Rails
10. 2.6 Rewriting “Returning” in Rails
11. 3 The Thrush
12. 3.1 Let
13. 4 Songs of the Cardinal
14. 4.1 Building a Cardinal in Ruby
15. 5 Quirky Birds and Meta-Syntactic Programming
16. 5.1 A limited interpretation of the Quirky Bird in Ruby
17. 5.2 Embracing the Quirky Bird
18. 5.3 Andand even more
19. 6 Aspect-Oriented Programming in Ruby using Combinator Birds
20. 6.1 Giving methods advice
21. 6.2 The super keyword, perhaps you’ve heard of it?
22. 6.3 The Queer Bird
23. 7 Mockingbirds
24. 7.1 Duplicative Combinators
25. 7.2 Recursive Lambdas in Ruby
26. 7.3 Recursive Combinatorics
27. 7.4 Recursive Combinators in Idiomatic Ruby
28. 7.5 The Mockingbird
29. 8 Refactoring Methods with Recursive Combinators
30. 8.1 Divide and Conquer
31. 8.2 The Merge Sort
32. 8.3 Separating Declaration from Implementation
33. 8.4 Practical Recursive Combinators
34. 8.5 Spicing things up
35. 8.6 Building on a legacy
36. 8.7 Seriously
37. 8.8 Separating Implementation from Declaration
38. 8.9 A Really Simple Recursive Combinator
39. 9 You can’t be serious!?
40. 9.1 String to Proc
41. 9.2 The Message
42. 10 The Hopelessly Egocentric Book Chapter
43. 10.1 Object-oriented egocentricity
44. 11 Bonus Chapter: Separating Concerns in Coffeescript using Aspect-Oriented Programming
45. 12 Appendix: Finding Joy in Combinators
46. 12.1 Languages for combinatorial logic
47. 12.2 Concatenative languages
48. 13 Appendix: Source Code
49. 13.1 kestrels
50. 13.2 thrushes
51. 13.3 the cardinal
52. 13.4 quirky birds
53. 13.5 bluebirds
54. 14 About The Author
55. 14.1 contact
Something went wrong with that request. Please try again.