I would like to know if operator precedence in programming languages depends on implementation or there is a fixed rule that all languages follow. And if possible, could you order the following operators with highest precedence first: AND, OR, NOT, XOR.
I googled and found out this which says that some languages like APL and SmallTalk do not have operator precedence rules and they strictly evaluate expressions from left to right/left to right.
However,relative order of precedence followed is NOT > XOR > AND > OR in most of the languages especially those derived from C
You have seen that when expressions mix && with || that evaluation must be done in the correct order. Parentheses can be used to group operands with their correct operator, just like in arithmetic. Also like arithmetic operators, logical operators have precedence that determines how things are grouped in the absence of parentheses.
In an expression, the operator with the highest precedence is grouped with its operand(s) first, then the next highest operator will be grouped with its operands, and so on. If there are several logical operators of the same precedence, they will be examined left to right.
It is common for programmers to use parentheses to group operands together for readability even when operator precedence alone would work.
Source
Boolean or bitwise? There is no fixed rule, most languages have similar rules but differ in details. Look it up in the language definition.
There are three basic Boolean operators: NOT, AND, OR. XOR is just a simple version of A AND NOT B OR NOT A AND B or (A OR NOT B) AND (NOT A OR B). So, only these three have common precedence: NOT > AND > OR. XOR has different position in languages, but it has surely not higher precedence than AND and not lower than OR. Most languages (e.g. C/C++/Javascript etc.) have it between AND and OR, but in other ones (e.g. Perl) XOR has the same precedence as OR.
(OR can be expressed using only AND and NOT, but it is still a basic operator: A OR B = NOT(NOT A AND NOT B))
Obvious and easy way to prove that AND is of higher precedence than OR is to compare results of statements with and without parentheses:
std::cout << std::boolalpha;
std::cout << ( true || false && false ) << std::endl; // gives true
std::cout << ( ( true || false ) && false ) << std::endl; // gives false
Related
The Q Tips book (Nick Psaris) shows the
following function (Chapter 10):
q)merge:`time xdesc upsert
As it is stated, it corresponds to function composition. I see the pattern: the
expression supplies a function that takes both arguments for upsert and then
uses its result to feed time xdesc. However the syntax feels weird, since
I would expect upsert to be the second argument of the xdesc invocation.
Aiming at simplifying the expression, I could see that the very same scenario
applies here:
q)f:1+*
q)f[2;3]
7
If we show its result, we can clearly see that f behaves as expected:
q)f
+[1]*
However, If we slightly modify the function, the meaning of the expression is
completely different:
q)g:+[1;]*
q)g[2;3]
'rank
[0] g[2;3]
^
In fact, +[1;] is passed as first argument to the * operator instead,
leading us to a rank error:
q)g
*[+[1;]]
I could also notice that the pattern breaks when the first function is
"monadic":
q)h:neg *
q)h[2;3]
'rank
[0] h[2;3]
^
Also here:
q)i:neg neg
'type
[0] i:neg neg
^
At this point, my intuition is that this pattern only applies when we are
interested on composing dyadic standard (vs user-defined) operators that exploit infix
notation. Am I getting it right? Is this syntactic sugar actually more general? Is there any
documentation where the pattern is fully described? Thanks!
There are some documented ways to achieve what you wish:
https://code.kx.com/q/ref/apply/#composition
You can create a unary train using #
q)r:neg neg#
q)r 1
1
https://code.kx.com/q/ref/compose/
You can use ' to compose a unary value with another of rank >=1
q)f:('[1+;*])
q)f[2;3]
7
Likely the behaviour you are seeing is not officially there to be exploited by users in q so should not be relied upon. This link may be of interest:
https://github.com/quintanar401/DCoQ
I always thought that in q and in k all expressions divided ; evaluated left-to-right and operator precedence inside is right-to-left.
But then I tried to apply this principle to Ament At operator parameters. Confusingly it seems working in the opposite direction:
$ q KDB+ 3.6 2019.04.02 Copyright (C) 1993-2019 Kx Systems
q)#[10 20 30;g;:;100+g:1]
10 101 30
The same precedence works inside a function parameters too:
q){x+y}[q;10+q:100]
210
So why does it happend - why does it first calculate the last one parameter and only then first? Is it a feature we should avoid?
Upd: evaluation vs parsing.
There could be another cases: https://code.kx.com/q/ref/apply/#when-e-is-not-a-function
q)#[2+;"42";{)}]
')
[0] #[2+;"42";{)}]
q)#[string;42;a:100] / expression not a function
"42"
q)a // but a was assigned anyway
100
q)#[string;42;{b::99}] / expression is a function
"42"
q)b // not evaluated
'b
[0] b
^
The semicolon is a multi-purpose separator in q. It can separate statements (e.g. a:10; b:20), in which case statements are evaluated from left-to-right similar to many other languages. But when it separates elements of a list it creates a list expression which (an expression) is evaluated from right-to-left as any other q expression would be.
Like in this example:
q)(q;10+q:100)
110 100
One of many overloads of the dot operator (.) evaluates its left operand on a list of values in its right operand:
q){x+y} . (q;10+q:100)
210
In order to do so a list expression itself needs to be evaluated first, and it will be, from right-to-left as any other list expression.
However, the latter is just another way of getting the result of
{x+y}[q;10+q:100]
which therefore should produce the same value. And it does. By evaluating function arguments from right-to-left, of course!
A side note. Please don't be confused by the conditional evaluation statement $[a;b;c]. Even though it looks like an expression it is in fact a statement which evaluates a first and only then either b or c. In other words a, b and c are not arguments of some function $ in this case.
I practicing in swift's playground and I couldn't figure out why swift is too specific about where programmer should provide spaces and where not. I asked this question on many sites and chatrooms but didn't got any answer.
var j: Int = 34 // Right
var j:Int=23 //Wrong
Also, In class
self.variable-= 5 //Wrong. Error: Consecutive statements must be followed by ;
self.variable-=5 // Right
self.variable -= 5 // Right
;
Even this ":" creates some issues with spaces sometimes.
I think spaces should have absolutely no effect on the code. It's usually just for a programmer's benefit. It just makes the code more readable nothing else. What's the best resource to read all swift rules about spaces.
Answer to the second part of your question can be found here swift docs
The whitespace around an operator is used to determine whether an operator is used as a prefix operator, a postfix operator, or a binary operator. This behavior is summarized in the following rules:
If an operator has whitespace around both sides or around neither side, it is treated as a binary operator. As an example, the + operator in a+b and a + b is treated as a binary operator.
If an operator has whitespace on the left side only, it is treated as a prefix unary operator. As an example, the ++ operator in a ++b is treated as a prefix unary operator.
If an operator has whitespace on the right side only, it is treated as a postfix unary operator. As an example, the ++ operator in a++ b is treated as a postfix unary operator.
If an operator has no whitespace on the left but is followed immediately by a dot (.), it is treated as a postfix unary operator. As an example, the ++ operator in a++.b is treated as a postfix unary operator (a++ .b rather than a ++ .b).
etc... (read the docs for more on this)
As for the first part of your question, I didn't see any issue with either way of declaring the variables.
var j: Int = 34
var j:Int=23
The only issue with that provided code is that you declare j twice in the same scope. Try changing one of the j's to an x or y or something else.
If you were wondering about
var j:Int =10
or
var j:Int= 10
look at the rules above. = is an operator so if you were to do either of those, it would be treated as prefix or postfix, and you would get the error that prefix/postfix = is reserved
These rules are important due to the existence of operators such as the unary plus and unary minus operators. The compiler needs to be able to distinguish between a binary plus and a unary plus operator. List of operators
I know about perlop. What I am looking for is a quick lookup like the GHCi :info command:
ghci> :info (+)
class (Eq a, Show a) => Num a where
(+) :: a -> a -> a
...
-- Defined in GHC.Num
infixl 6 +
where I learn (+) is left-associative and has a precedence level of 6 from the infixl 6 + line.
I realize that it is not exactly what you ask for, but what about:
perl -MO=Deparse,-p -e "print $a+$b*$c**$d;"
it prints parentheses around the expressions according to precedence:
print(($a + ($b * ($c ** $d))));
And for things out of perl distibution, you can look on perlopquick - the pod arranged very similar manner as you specified in your question.
Any reasonable reference manual and electronic version or help facility for the language should include the operator precedence in a list either horizontal or vertical, starting with the first entry as the highest prcedence.
I am just learning Perl's comparison operators. I tried the below code :-
$foo=291;
$bar=30;
if ($foo < $bar) {
print "$foo is less than $bar (first)\n";
}
if ($foo lt $bar) {
print "$foo is less than $bar (second)\n";
}
The output is 291 is less than 30 (second). Does this mean the lt operator always converts the variables to string and then compare? What is the rationale for Perl making lt operator behave differently from the < operator?
Thanks,
Your guess is right. The alphabetic operators like lt compare the variables as strings whereas the symbolic ones like < compare them as numbers. You can read the perlop man page for more details.
The rationale is that scalars in Perl are not typed, so without you telling it Perl would not know how to compare two variables. If it did guess then it would sometimes getting it wrong, which would lead to having to do things like ' ' + $a < ' ' + $b to force string comparsion which is probably worse than lt.
That said this is a horrible gotcha which probably catches out everyone new to Perl and still catches me out when coming back to Perl after some time using a less post-modern language.
Since Perl is loosely typed, and values can silently convert between strings and integers at any moment, Perl needs two different types of comparison operators to distinguish between integer comparison (<) and string comparison (lt). If you only had one operator, how would you tell the difference?
Rationale? It's a string operator. From "perldoc perlop":
Binary "lt" returns true if the left argument is stringwise less than the right argument.
If that's not what you want, don't use it.
lt compares values lexically (i.e. in ASCII/UNICODE or locale order) and < compares values numerically. Perl has both operators for the same reason "10" + 5 is 15 rather than a type error: it is weakly typed. You must always tell the computer something unambiguous. Languages that are strongly typed tend to use casting to resolve ambiguity, whereas, weakly typed languages tend to use lots of operators. The Python (a strongly typed language) equivalent to "10" + 5 is float("10") + 5.
Does this mean the 'lt' operator
always converts the variables to
string and then compare?
Yes, see perlop
What is the rationale for Perl making
'lt' operator behave differently from
'<' operator?
Because having a numeric comparison operator and a string comparison operator makes a lot more sense then having a mumble mumble operator and another, identical mumble mumble operator.