Is there a quick way to determine precedence and associativity of operators? - perl

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.

Related

What is the general pattern behind (dyadic) function composition's syntax?

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

What is (!). in kdb and are below usecases valid to use it?

What is (!). called in kdb?
and are below use cases valid to use (!). to convert a list to a dictionary or are there better ways and other uses of (!). ?
Example:
q)(!). (`A`B;(`C`D`E;`F`G`H));
q).[(!);flip (`A`B;`C`D;`E`F)]
I cannot find any documentation on the use cases on (!). in kdb tutorials. Please share any information on (!). and its uses?
It's a version of apply & yep your use case is valid. The reason the operator is wrapped in parentheses is because it itself is a dyadic infix operator as is dot apply (.)
If you attempt to apply it as is, your expression is like so, which Q doesn't like
// infixOp infixOp operand
q)+ . 4 5
'
[0] + . 4 5
^
Wrapping the operator within parentheses effectively transforms it so the expression now becomes
// operand infixOp operand
q)(+). 4 5
9
If you define a function which can't be used infix, then there's no need to wrap it
q)f:+
q)4 f 5
'type
[0] 4 f 5
^
q)f . 4 5
9
If using apply with bracket notation as in your example, there's no need to wrap the function
q).[+;4 5]
9
https://code.kx.com/q/ref/apply/#apply-index
https://code.kx.com/q/basics/syntax/#parentheses-around-a-function-with-infix-syntax
Jason
In terms of use-cases, I find it very useful when defining dictionaries/tables as configs particularly when dictionaries are too wide (horizontal) for the screen or when it's more useful to see fields/mappings vertically as pairs. From a code/script point of view that is.
For example:
mapping:(!) . flip(
(`one; 1);
(`two; 2);
(`three; 3));
is much easier to read when scanning through a q script than
mapping2:`one`two`three!1 2 3
when the latter gets very wide.
It makes no difference to the actual dictionary of course because as Jason pointed out it's the same thing.

Expressions/operator precedence in Amend At and in function parameters

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.

Is 35.+(10) still called infix notation?

I nearly talked about
35.+(10)
as an example of postfix notation because I understood
35 + 10
to be infix notation (at least everyone talks about that as an example of infix notation). But that's wrong isn't it?
35 10 +
would be postfix.
So how do I distinguish between the first two examples by name? Are they both "infix" but the second just a neater way?
Indeed it is still "infix".
Postfix means that all operands to an operator come in the stream before the operator itself. (an example is the factorial "!" operator in mathematics)
Prefix means the operator comes before the operands (an example is the "negate"/"-" operator to make a number negative).
Infix simply means that the operator is somewhere between the operands.
To decide how to name the application syntax, break the fragment up into tokens.
35.+(10)
is
[35] [.] [+] [(] [10] [)]
dropping the redundant parens, and let's name '.' as 'apply' we get:
[35] [apply] [+] [10]
So it most certainly is infix, as the binary operator is between the first and second argument.
It's just a bit noisy for what is also written as 35 + 10

Why is the 'Use of "shift" without parentheses is ambiguous' warning issued by Perl?

Does anyone know what parsing or precedence decisions resulted in the warning 'Use of "shift" without parentheses is ambiguous' being issued for code like:
shift . 'some string';
# and not
(shift) . 'some string'; # or
shift() . 'some string';
Is this intentional to make certain syntactic constructs easier? Or is it merely an artifact of the way perl's parser works?
Note: this is a discussion about language design, not a place to suggest
"#{[shift]}some string"
With use diagnostics, you get the helpful message:
Warning: Use of "shift" without parentheses is ambiguous at (eval
9)[/usr/lib/perl5/5.8/perl5db.pl:628] line 2 (#1)
(S ambiguous) You wrote a unary operator followed by something that
looks like a binary operator that could also have been interpreted as a
term or unary operator. For instance, if you know that the rand
function has a default argument of 1.0, and you write
rand + 5;
you may THINK you wrote the same thing as
rand() + 5;
but in actual fact, you got
rand(+5);
So put in parentheses to say what you really mean.
The fear is you could write something like shift .5 and it will be parsed like shift(0.5).
Ambiguous doesn't mean truly ambiguous, just ambiguous as far as the parser had determined.
shift . in particular is "ambiguous" because . can start a term (e.g. .123) or an operator,
so it doesn't know enough to decide whether what follows is shift's operand or an operator for which shift() is the operand (and the parser isn't smart enough to know that: a) the .
isn't the start of such a term or b) .123 isn't a valid operand for shift).