How do the "if and (ne)" operators work in helm? - go

I'm working with a chart that has the following structure at the beginning but I'm having a hard time understanding when does this evaluate to true.
{{- if and .Values.vpceIngress.enabled .Values.http.paths (ne .Values.vpceIngress.class "traefik2") }}
I believe that both enabled and paths must be true, but the ne throws me off after that.

and and ne are functions in go templates.
and
Returns the boolean AND of its arguments by returning the
first empty argument or the last argument, that is,
"and x y" behaves as "if x then y else x". All the
arguments are evaluated.
ne
Returns the boolean truth of arg1 != arg2
So the template line equates to a more psuedo codish
if (
.Values.vpceIngress.enabled
&& .Values.http.paths
&& .Values.vpceIngress.class != "traefik2"
)
The truthiness of the plain .Value.key is basically a "is this field/key not the zero value for the data type. This also works for maps as 'is this field/key defined' due to a map without that path equating to nil or non value (Note that this only works when the parent map is actually defined! Otherwise the template errors)

Related

|| and && aren't methods on Object -- what are they?

The single pipe "or" | exists as a method on TrueClass and FalseClass, but the short circuit || operator does not. Neither does it exist as a method on Object.
This seems to be an exception to ruby's "everything is an object" metaphor.
Main Question: Syntactically speaking, what are || and &&? Are they just baked bits of global syntax?
Secondary Question: I'm flagging this as not part of the main question, because it is potentially subjective, though I suspect it probably isn't.
Is there a language design or performance reason for this asymmetry? It seems to me both operators could have been implemented as methods on Object. Something like:
class Object
def short_circuit_or(other)
!nil? ? true :
!other.nil? ? true : false
end
end
I assume there is a reason they were not. What is it?
Both | and || are operators. || is part of the language while | is implemented as a method by some classes (Array, FalseClass, Integer, NilClass and TrueClass) .
In programming languages, | is used in general as the bitwise OR operator. It combines the bits of its integer operands and produces a new integer value. When used with non-integer operands, some languages convert them to integer, others prohibit such usage.
|| is the logical OR operator. It combines two boolean values (true or false) and produces another boolean value. When its operands are not boolean values, they are converted to boolean by some languages. Ruby (and JavaScript and other languages) evaluate its first operand as boolean and the value of the expression is the value of its first operand if its boolean value is true or the value of its second operand if the logical value of its first one is false. The type of the resulting value is its original type, it is not converted to boolean.
Each language uses its own rules to decide what non-boolean values are converted to false (usually the number 0, the empty string '' and null or undefined); all the other values are converted to true. The only "false" values in Ruby are false (boolean) and nil (non-boolean); all the other values (including 0) are "true".
Because true || anything is true and false && anything is false, many programming languages including Ruby implement short-circuit evaluation for logical expressions.
Using short-circuit evaluation, a logical expression is evaluated from left to right, one operand at a time until the value of the expression can be computed without the need to compute the other operands. In the examples above, the value of anything doesn't change the value of the entire expression. Using short-circuit evaluation, the value of anything is not computed at all because it does not influence the value of the entire expression. Being anything a method call that takes considerable time to execute, the short-circuit evaluation avoids calling it and saves execution time.
As others already mentioned in comments to the question, implementing || as a method of some class is not possible. The value of its second operand must be evaluated in order to be passed as argument to the method and this breaks the short-circuiting behaviour.
The usual representation of the logical values in programming languages uses only one bit (and I guess Ruby does the same.) Results of | and || are the same for operands stored on one bit.
Ruby uses the | symbol to implement different flavors of the OR operation as follows:
bitwise OR for integers;
non-short-circuit logical OR for booleans and nil;
union for arrays.
An expression like:
x = false | a | b | c
ensures that all a, b and c expressions are evaluated (no short-circuit) and the value of x is the logical OR of the logical values of a, b and c.
If a, b and c are method calls, to achieve the same result using the logical OR operator (||) the code needs to look like this:
aa = a
bb = b
cc = c
x = aa || bb || cc
This way each method is called no matter what values are returned by the methods called before it.
For TrueClass, FalseClass and NilClass, the | operator is useful when short-circuit evaluation is not desired.
Also, for Array (an array is just an ordered set), the | operator implements union, an operation that is the semantically equivalent of logical OR for sets.

Early or late argument evaluation in golang?

In my program I do a series of sequential checks in this manner:
var value int
if !(ParseOrFail(inputStrVal, &value) &&
Validate(value)) {
return SomeErr
}
I know that Validate is called only if ParseOrFail returns true, but I'm not sure whether in all such scenarios it will get the updated value.
Is it correct to do so? Or must I pass a pointer to Validate ?
Playground link: https://play.golang.org/p/l6XHbgQjFs
The Go Programming Language
Specification
Expressions
An expression specifies the computation of a value by applying
operators and functions to operands.
Operands
Operands denote the elementary values in an expression. An operand may
be a literal, a (possibly qualified) non-blank identifier denoting a
constant, variable, or function, a method expression yielding a
function, or a parenthesized expression.
Order of evaluation
At package level, initialization dependencies determine the evaluation
order of individual initialization expressions in variable
declarations. Otherwise, when evaluating the operands of an
expression, assignment, or return statement, all function calls,
method calls, and communication operations are evaluated in lexical
left-to-right order.
Calls
Given an expression f of function type F,
f(a1, a2, … an)
calls f with arguments a1, a2, … an. Except for one special case,
arguments must be single-valued expressions assignable to the
parameter types of F and are evaluated before the function is called.
The type of the expression is the result type of F. A method
invocation is similar but the method itself is specified as a selector
upon a value of the receiver type for the method.
Logical operators
Logical operators apply to boolean values and yield a result of the
same type as the operands. The right operand is evaluated
conditionally.
&& conditional AND p && q is "if p then q else false"
|| conditional OR p || q is "if p then true else q"
! NOT !p is "not p"
The behavior of your code is defined in The Go Programming Language Specification.
var value int
if !(ParseOrFail(inputStrVal, &value) && Validate(value)) {
return SomeErr
}
Or, in pseudocode,
ParseOrFail arguments are evaluated
ParseOrFail is called
if ParseOrFail == true
Validate arguments are evaluated
Validate is called
That is, in your example (https://play.golang.org/p/l6XHbgQjFs), late evaluation.

Will `&&` always run before `if` on the same line in Ruby

Will every && run before if on the same line in Ruby?
For example:
#building.approved = params[:approved] if xyz && abc && mno...
Can an unlimited number of && be used on the right side of an if without using parentheses?
I'm inclined to use parentheses but I'd like to understand the default behaviour.
Everything after the if must be part of the condition by virtue of the syntax. The only way to get around this is to be really specific:
(#building.approved = params[:approved] if xyz) && abc && ...
Which is obviously not what you're intending here.
Operator binding strength isn't an issue here since if is a syntax element not an operator, so it has the absolute lowest priority.
The only conditions that will be evaluated are the ones that produce a logically false value, or come after one that was logically true as the first one to return logically false will halt the chain.
That is:
if a && b && c
Will stop at a if that is a logically-false value. b and c will not be evaluated. There's no intrinsic limit on chaining though.

Do "Ors" Evaluate The Whole Expression?

Say I have the following statement logic (I'll be using VBA for this example, but it also pertains to other languages)
x = 1
y = 2
z = 1000
If x = 1 Or y = 2 Or z = 4 Then
Execute Code
End
Does the compiler or executing program find that the first value is true, and then continue to Execute Code or does it finish off the rest of the statement?
I can't speak for VBA, but I can say that it is language specific. In some languages, the programmer has the ability to use "short-circuit" AND and OR expressions. Short-circuiting is the process of no longer evaluating a boolean expression if the result has already been determined.
If using a short-circuited AND, the boolean operation stops early if a FALSE is found. If using a short-circuited OR, the boolean operation stops early if a TRUE is found.
For example, in Java:
a || b is a short-circuited OR
a | b is a non-short-circuited OR
a && b is a short-circuited AND
a & b is a non-short-circuited AND
Some may ask, "why would I ever use a non-short-circuited AND or OR?" The reason for this comes when you are calling a function that returns a boolean that you want to run in every case. For example a() | b() would run both function a and function b. a() || b() only runs function b if a returns false.
I think that also in vba you can use OrElse.
'Or' (bitwise comparison) always finishes the rest of the statement, 'OrElse' (logical comparison) stops when the requirement is met.
In C++, C# and Java you can use '|' and '||'.
For example if object is null Or object.value = "" will result in a null exception when the object is empty because of the attempt to access a field from an empty object.
With OrElse the evaluation if object is null OrElse object.value = "" will stop at the first comparison when an empty object is evaluated.

Does the || operator evaluate the second argument even if the first argument is true?

I'm trying to evaluate the expression (a=10) || (rr=20) while the rr variable is not defined
so typing rr in the ruby console before evaluating the previous expression returns
rr
NameError: undefined local variable or method `rr' for main:Object
from (irb):1
from :0
When I write the expression (a=10) || (rr=20) it returns 10, and when I write rr afterwards it says nil
(a=10) || (rr=20)
rr # => nil
so, why is this happening? Shouldn't rr be defined only if the second argument of the || operator is evaluated, which should be never based on the documentation?
This happens because the ruby interpreter defines a variable when it sees an assignment to it (but before it executes the actual line of code). You can read more about it in this answer.
Boolean OR (||) expression will evaluate to the value of left hand expression if it is not nil and not false, else || will evaluate to the value of right hand expression.
In your example the ruby interpreter sees an assignment to a and rr (but it doesn't execute this line yet), and initializes (defines, creates) a and rr with nil. Then it executes the || expression. In this || expression, a is assigned to 10 and 10 is returned. r=20 is not evaluated, and rr is not changed (it is still nil). This is why in the next line rr is nil.
As #DOC said, && and || are known as short circuited conditional operators.
In case of ||, if the left part of || expression returns true, the right part won't be executed. That means the right part will be executed only if the left part of || expression returns false.
In case of &&, right part of the&&expression will be executed only if left part of && returns true.
In the given scenario (a=10) || (rr=20), rr=20 won't be executed since the ruby expression a=10 returns true. Note that in ruby assignment expression returns true except nil and false.
I think variable definement happens at the parsing stage, not the execution moment. So when it evaluates the line, it parses the whole thing and the variable is defined, but unassigned.
When the parser discovers a variable it is automatically valid within the context it's defined in. Evaluating rr on its own is not valid. Evaluating rr=20 is sufficient to cause a definition even if the value assignment never occurs.
This is a quirk of how Ruby tries to discern between variables and method calls. It's imperfect but usually works out for the best.

Resources