@paulh16 there are a few separate things going on here:
Note: I’m assuming you understand how inject works and are confused by the :& part.
TL DR;
inject(:&) calls the & method on all the values in your array. Under the hood, it’s evaluating: ((true & true) & true)
This should not be confused with a similar syntax that starts with &: (note the reversed order) that takes advantage of Symbol#to_proc and is commonly used by Rubyists instead of passing a block to a method.
Blocks
Many methods in Ruby allow you to pass them a block (inject being one of them). For example, if you wanted to sum an array of numbers, you could do:
[1,2,3,4].inject do |running_total, number|
running_total + number
end
# => 10
Procs
Instead of passing a block, you can pass in a Proc (Ruby’s function object) as an argument. When passing a function as an argument instead of using a block, we need to prefix it with &.
sum = ->(x, y) { x + y }
# => #<Proc:0x007fc980c19160@(pry):4 (lambda)>
[1,2,3,4].inject(&sum)
#=> 10
Symbols
When passing an object instead of a block with &, Ruby will call to_proc on them before trying to evaluate the function. This means we can pass any object that responds to to_proc. Symbol is another type of object that responds to this method. Symbol#to_proc returns a proc object that will delegate the method named by the symbol to it’s arguments. For example:
sum = :+.to_proc
# => #<Proc:0x007f890c1433d0(&:+)>
sum.call(1,2) # this is how you invoke a Proc object
# => 3
[1,2,3,4].inject(&sum)
# => 10
Since to_proc gets called automatically, we can pass in symbols instead of procs:
[1,2,3,4].inject(&:+)
# => 10
The inject method
Any method in Ruby that accepts a block can use the Symbol#to_proc trick instead:
[1,2,3,4].map(&:even?)
# => [false, true, false, true]
[1,2,3,4].any?(&:negative?)
# => false
This style is commonly used with the various methods from the Enumerable module. It is used throughout the article you linked.
However, inject is special. From the docs (linked to by @trueheart78):
Combines all elements of enum by applying a binary operation, specified by a block or a symbol that names a method or operator.
Inject can take an optional symbol argument instead of a block. This means you can do:
[1,2,3,4].inject(:+)
=> 10
This is very similar to what we did before. However, notice that the argument is :+, not :&:+. The result is the same.
Your example
In addition to being used within method signatures to denote a block parameter, the & is a method defined on TrueClass and FalseClass to implement boolean logic:
true & true
#=> true
true & false
#=> false
false & true
#=> false
false & false
# => false
In your example [true, true, true].inject(:&), the symbol :& is passed to inject. When using Symbol#to_proc, the equivalent would be [true, true, true].inject(&:&). Both of these do the same thing: they AND all the values and return the result.
[true, true, true].inject(:&)
# => true
[true, true, true].inject(&:&)
# => true
Under the hood, it’s evaluating: ((true & true) & true)