Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inject double ampersand operator

Tags:

ruby

I have an inject call

[2,4,6].inject(true) { |res, val| res && val % 2 == 0 }

and want to send the && operator to inject as in inject(0, :+). How can I do that?

like image 818
Zoltán Szőcs Avatar asked Feb 05 '14 15:02

Zoltán Szőcs


People also ask

What is double ampersand C?

In C, the double ampersand && is a short-circuit logical AND operation. If you have something like a && b , then this will evaluate as follows: it will return true if both a and b are true, but if a is false then b will never be executed.

What is double ampersand in JavaScript?

JavaScript uses the double ampersand ( && ) to represent the logical AND operator. The following expression uses the && operator: let result = a && b; Code language: JavaScript (javascript) If a can be converted to true , the && operator returns the b ; otherwise, it returns the a .

How does the double ampersand && differ from a single ampersand &?

The single ampersand operator (&) evaluates both sides of the operator before arriving at its answer. The double ampersand operator (&& – also known as the conditional-AND operator) evaluates the RHS only if the LHS is true. It short-circuits the evaluation so it doesn't have to evaluate the RHS if it doesn't have to.

What does ampersand mean in Java?

The & operator in Java has two definite functions: As a Relational Operator: & is used as a relational operator to check a conditional statement just like && operator. Both even give the same result, i.e. true if all conditions are true, false if any one condition is false.


3 Answers

You can't because && and ||, unlike other operators, are not syntacic sugar for methods (i.e. there is no method called && or ||), so you can't reference them using a symbol.

However you can avoid using inject to compute the logical conjunction or disjunction of an array of boolean values, replacing it with all? or any? respectively, because for any array the following conditions hold:

ary.inject(true) { |res, b| res && b } == ary.all?
ary.inject(false) { |res, b| res || b } == ary.any?

So, for example, the code you posted could be rewritten as:

[2,4,6].map(&:even?).all?
# => true

Update: obviously my latter example is not the right way to express this computation, falsetru's answer is much faster:

require 'fruity'

compare(
  -> { (0..1000).map(&:even?).all? },
  -> { (0..1000).all?(&:even?) }
)
Running each test 1024 times. Test will take about 2 seconds.
Code 2 is faster than Code 1 by 111x ± 10.0   
like image 108
toro2k Avatar answered Sep 21 '22 03:09

toro2k


How about using Enumerable#all?

[2,4,6].all? &:even?
# => true
[2,4,6,5].all? &:even?
# => false

If you want to use inject, you need to define an instance method.

class Object
  def is_even(val)
    self && val % 2 == 0
  end
end

[2,4,6].inject(true, :is_even) # => true
[1,2,4,6,5].inject(true, :is_even) # => false
like image 25
falsetru Avatar answered Sep 23 '22 03:09

falsetru


'&&' is not a method, hence you can't inject it. However you can inject & method.

[2,4,6,5].map(&:even?).inject(true, :&)

Which will do the same

NOTE: This however should not be done, as it is extremely risky and might cause unexpected consequences (if run on collection containing at least one non-boolean (true, false, nil) value). You should always use any? or all? methods instead.

like image 22
BroiSatse Avatar answered Sep 23 '22 03:09

BroiSatse