Functions and adverbs

Good day eveyrbody, 

I am currently reading Q for Mortals and I have a problem with understanding how functions in q work with adverbs. Allow me to explain:

  1. Define a function: 

{[x;y] x+y}

  1. Then if I want to apply the function to the arguments:

{[x;y] x+y}[1;2]

3

  1. If I want to apply the function to a list and sum it “over” using adverb “/”

0 {[x;y] x+y}/ 1 2 3 4 5

15

The confusing part follows:

  1. Why does this work? 

{[x;y] x+y}/[1;2]

3

  1. And this does not. 

0 {[x;y] x+y}/[1;2]

  1. Why does this work?

0 {[x;y] x+y}/1 2 3

6

  1. And this does not.

0 {[x;y] x+y}/[1 2 3]

'type

  1. This does not work as well AND it produces different error message…

0 {[x;y] x+y}/ [1 2 3 4 5]

'length

I would absolutely love to know why equation (7) and equation (8) produce different error messages. 

Regards

VA. 

Well, I’m also a newbie and didn’t read the book yet, though I’ll try to explain it:

{[x;y] x+y}  // the function definition

{[x;y] x+y}[1;2] // call the function, in the normal form, func[arg1; arg2; …]

0 {[x;y] x+y}/ 1 2 3 4 5 // call the derived function modified by over as a verb, in (and it must be in) the juxtaposition form, without “”, e.g 1 + 2 3 4, not 1 + [2 3 4]

0 {[x;y] x+y}/[1;2]

0 {[x;y] x+y}/[1 2 3]

0 {[x;y] x+y}/ [1 2 3 4 5]
// as mentioned above, you’re trying call it as a verb with juxtaposition, but using a “”, so it is explained in a different way, see below

the last 3 lines are explained as {0 x}[{[x;y] x+y}/ […] ], which is
 {0 x}[3]

 {0 x}[6]

 {0 x}[15]

that means send 3,6,15 to the current console (0 is treated as a handler, see http://code.kx.com/wiki/Reference/Number)

But I don’t know why the error of {0 x}[3] and {0 x}[15] are different, sorry.


This email address (zhuo.dev<at>gmail.com) is only for development affairs, e.g. mail list, please mail to zhuo<at>hexoasis.com or zhuoql<at>zoho.com for other purpose.

ZHUO QL (KDr2), http://kdr2.com

I hadn’t intended for this to be so wordy - apologies.


Parsing…

the core grammar is: E:E;e|e e:nve|te| t:n|v v:tA|V n:t[E]|(E)|{E}|N

the relevant parts to adverb and application are:

v:tA (a verb is a term followed by an adverb.

n:t[E] (a term followed by a ‘[’)


   

  1. Why does this work?
    {[x;y] x+y}/[1;2]
    3

this parses as t[E] where t is a verb (tA) where the lambda is a term (t)

q)0N!parse"{[x;y] x+y}/[1;2]";

((/;{[x;y] x+y});1;2)


t is a verb that can accept one or two arguments. two arguments are provided as E (1 and 2) and is equivalent to the juxtapose

q)0N!parse"1{[x;y] x+y}/2";

((/;{[x;y] x+y});1;2)

note that the first arg in the call is the "x" argument (left) and the second is "y"
  1. And this does not. 

0{[x;y] x+y}/[1;2]

this expression is equivalent to:
0 ( 1{[x;y] x+y}/2 )

q)0N!parse"0{[x;y] x+y}/[1;2]";

(0;((/;{[x;y] x+y});1;2))


that is, 0(6) - and the function “zero” does not like integers: http://code.kx.com/wiki/Reference/Zero


it can be thought that kdb+ evaluates from right to left of “right of left”, but it is actually the parsing rules that cause the right of left “evaluation”.

considering e:nve|te|e| and “1-2+3”. using nve: (1-“2+3”) -> (1-(2+“3”)) -> (1-(2+(3))) (last step by e:te|)

the actual tree is:

q)0N!parse"1-2+3";

(-;1;(+;2;3)) /verb followed by arguments - recursively evaluated

  1. And this does not.
    0 {[x;y] x+y}/[1 2 3]
    'type

we know that {[x;y] x+y}/[1 2 3] evaluates to 6. so the expression reduces to 0(6).

as soon as you use the n:t[E] syntax, the t expression becomes a noun and there is no way to pass an x/left argument to a noun by using juxtaposition (only verbs allow arguments to their left - oh, and an adverb takes a single term to it’s left)

  1. This does not work as well AND it produces different error message…
    0 {[x;y] x+y}/ [1 2 3 4 5]
    'length

this one seems to be a curiosity - 0 must have at least two constraints (type and length) and the length constraint isn’t violated until an integer argument exceeds 9. the length constraint is checked first and so when length constraint is violated… that’s my guess.

The confusing part follows:

  1. Why does this work? 

{[x;y] x+y}/[1;2]

3

{[x;y]x+y}  is equivalent to  {x+y},

{x+y}/    produces a “new” function which has  one OR two arguments.

q allows you to call a funciton with  two arguments via   function[param1;param2]   OR  in some cases (for example + or - and THIS NEW function)  via  param1 function param2   (=>  example 1+3)

If used with two arguments the first one is just the first step in the “over” (/) reduce.

so {x+y}/[1;2]   is  the same as   1{x+y}/enlist 2  which is the same as    {x+y}/[1 2]…

 

  1. And this does not. 

0 {[x;y] x+y}/[1;2]

now you try to call the new function with 3 parameters: first 0, second 1 third 2.  As the “new” function has only max 2 arguments, you get an error

 

  1. Why does this work?

0 {[x;y] x+y}/1 2 3

6

you call it again with two arguments: first 0    second list of 1 2 and 3

 

  1. And this does not.

0 {[x;y] x+y}/[1 2 3]

'type

here you call  the new function with one parameter: 1 2 3.  This results 6.  Now  you apply  6 to 0.   (same as 0@6  or 0[6], ..) which gives a type error

 

  1. This does not work as well AND it produces different error message…

0 {[x;y] x+y}/ [1 2 3 4 5]

'length

I would absolutely love to know why equation (7) and equation (8) produce different error messages. 

cant tell you why you get a different error.  But you call   0@15 here which produces a length error  0@6 produces type error. no idea why..

I think you  should read the  function part in the tutorial: http://code.kx.com/wiki/JB:QforMortals2/primitive\_operations#Introduction\_to\_Functions

In q/k you have many variants on how you can execute a function. It is fundamentally important to understand this

regards, Markus

Very detailed answers, thank you very much I shall go through the explanations today.