kdb+/q: Check if argument has been supplied to the function call - kdb

Say we have function fun with two arguments, second one is optional.
How to check within the function whether the second, optional argument has been supplied and act accordingly?
fun: {[x;optarg] $["optarg was supplied" like "optarg was supplied";"behavior 1"; "behavior 2"] }
fun[1;2] / behavior 1
fun[1] / behavior 2
```

I don't think this is possible. Supplying less than the specified number of arguments result in a projection.
A good alternative is to have your function accept one argument - a list. And then you can check for the existence of each element of the list.
f:{[l] $[1=count[l];
/ do something with first arg only;
/ do something with both args ]
}
Or you could have the function accept a dictionary (this allows you to set default values in the function).
q)f:{[dict] def:`a`b`c!10 20 30;
def:def upsert dict;
:def[`a] + def[`b] + def[`c] }
q)f[`a`b!5 10]
45
q)f[`a`c!5 10]
35

You can't check for number of arguments, kdb+ will report rank error when number of arguments is more than expected. But there is a workaround which will result in function which will accept any number of arguments:
q)func:('[{$[1=count x;"one";"more"]};enlist])
q)func[1]
"one"
q)func[1;2]
"more"
q)func[1;2;3]
"more"
Here is an example:
q)func:('[{$[1=count x;x[0];sum x]};enlist])
q)func[1]
1
q)func[1;2]
3
q)func[1;2;4]
7
q)func[1;2;4;7]
14

func:('[{
inputs:(`a_Required`b_Required`c_Optional`d_Optional);
optionalDefaults:`c_Optional`d_Optional!(0b;1b);
if[(count inputs)<count x;-1"Too Many input arguments";:()];
data:inputs xcols optionalDefaults, (!) . (numInputs:count x)#'(inputs;x);
show data;
data
};enlist]
)

Related

Iterate (/) a multivalent function

How do you iterate a function of multivalent rank (>1), e.g. f:{[x;y] ...} where the function inputs in the next iteration step depend on the last iteration step? Examples in the reference manual only iterate unary functions.
I was able to achieve this indirectly (and verbosely) by passing a dictionary of arguments (state) into unary function:
f:{[arg] key[arg]!(min arg;arg[`y]-2)}
f/[{0<x`x};`x`y!6 3]
Note that projection, e.g. f[x;]/[whilecond;y] would only work in the scenario where the x in the next iteration step does not depend on the result of the last iteration (i.e. when x is path-independent).
In relation to Rahul's answer, you could use one of the following (slightly less verbose) methods to achieve the same result:
q)g:{(min x,y;y-2)}
q)(g .)/[{0<x 0};6 3]
-1 -3
q).[g]/[{0<x 0};6 3]
-1 -3
Alternatively, you could use the .z.s self function, which recursively calls the function g and takes the output of the last iteration as its arguments. For example,
q)g:{[x;y] x: min x,y; y:y-2; $[x<0; (x;y); .z.s[x;y]]}
q)g[6;3]
-1 -3
Function that is used with '/' and '\' can only accept result from last iteration as a single item which means only 1 function parameter is reserved for the result. It is unary in that sense.
For function whose multiple input parameters depends on last iteration result, one solution is to wrap that function inside a unary function and use apply operator to execute that function on the last iteration result.
Ex:
q) g:{(min x,y;y-2)} / function with rank 2
q) f:{x . y}[g;] / function g wrapped inside unary function to iterate
q) f/[{0<x 0};6 3]
Over time I stumbled upon even shorter way which does not require parentheses or brackets:
q)g:{(min x,y;y-2)}
q){0<x 0} g//6 3
-1 -3
Why does double over (//) work ? The / adverb can sometimes be used in place of the . (apply) operator:
q)(*) . 2 3
6
q)(*/) 2 3
6

Ignoring an output parameter from vDSP

When using vDSP to perform some speedy calculations, I often don't care about one of the output parameters. Let's say I'm finding the index of an array's maximum value:
var m:Float = 0
var i:vDSP_Length = 0
vDSP_maxvi(&array,
1,
&m,
&i,
vDSP_Length(array.count))
Ideally, I'd like to get rid of m altogether so that vDSP_maxvi fills i only. Something like:
var i:vDSP_Length = 0
vDSP_maxvi(&array,
1,
nil,
&i,
vDSP_Length(array.count))
But of course this doesn't work ("nil is not compatible with expected argument type 'UnsafeMutablePointer<Float>'"). Is there some sort of argument I can send to these kinds of methods that says "ignore this parameter"? Thanks for reading.
Except for documented cases where a null argument is accepted, you must pass a valid address. There is no argument value that tells vDSP to ignore the argument.

KDB+/Q: About unused parameters in inner functions

I have this function f
f:{{z+x*y}[x]/[y]}
I am able to call f without a 3rd parameter and I get that, but how is the inner {z+x*y} able to complete without a third parameter?
kdb will assume, if given a single list to a function which takes two parameters, that you want the first one to be x and the remainder to be y (within the context of over and scan, not in general). For example:
q){x+y}/[1;2 3 4]
10
can also be achieved by:
q){x+y}/[1 2 3 4]
10
This is likely what's happening in your example.
EDIT:
In particular, you would use this function like
q){{z+x*y}[x]/[y]}[2;3 4 5 6]
56
which is equivalent to (due to the projection of x):
q){y+2*x}/[3 4 5 6]
56
which is equivalent to (due to my original point above):
q){y+2*x}/[3;4 5 6]
56
Which explains why the "third" parameter wasn't needed
You need to understand 2 things: 'over' behavior with dyadic functions and projection.
1. Understand how over/scan works on dyadic function:
http://code.kx.com/q/ref/adverbs/#over
If you have a list like (x1,x2,x3) and funtion 'f' then
f/(x1,x2,x3) ~ f[ f[x1;x2];x3]
So in every iteration it takes one element from list which will be 'y' and result from last iteration will be 'x'. Except in first iteration where first element will be 'x' and second 'y'.
Ex:
q) f:{x*y} / call with -> f/ (4 5 6)
first iteration : x=4, y=5, result=20
second iteration: x=20, y=6, result=120
2. Projection:
Lets take an example funtion f3 which takes 3 parameters:
q) f3:{[a;b;c] a+b+c}
now we can project it to f2 by fixing (passing) one parameter
q) f2:f3[4] / which means=> f2={[b;c] 4+b+c}
so f2 is dyadic now- it accepts only 2 parameters.
So now coming to your example and applying above 2 concepts, inner function will eventually become dyadic because of projection and then finally 'over' function works on this new dyadic function.
We can rewrite the function as :
f:{
f3:{z+x*y};
f2:f3[x];
f2/y
}

Strings Expansion is changing order or the string

I'm trying to so some normal variable expansion in a string and, when it's in a function, it comes out out-of-order.
function MakeMessage99($startValue, $endValue) { "Ranges from $startValue to $endValue" }
MakeMessage99(1, 100)
This returns Ranges from 1 100 to then it should return Ranges from 1 to 100
Functions in powershell shouldn't use parenthesis to enclose parameters. Instead:
PS C:\> MakeMessage99 1 100
Ranges from 1 to 100
Where MakeMessage is your function, "1" is a parameter in the first position, and "100" is a parameter in the second position. According to about_Functions_Advanced_Parameters:
By default, all function parameters are positional. Windows PowerShell assigns position numbers to parameters in the order in which the parameters are declared in the function.
Powershell has several ways to check input going in. You could cast the input as a numeric type. There are also baked-in validation methods for parameters that may prevent this sort of error in the future. If you really want an integer, a simple cast would cause an array to be invalid input. For example:
function MakeMessage99 {
Param
(
[int]$startValue,
[int]$endValue
)
"Ranges from $startValue to $endValue"
}
You could also explore range validation (such as [ValidateRange(0,100)]), pattern validation (such as [ValidatePattern("[0-9][0-9][0-9][0-9]")] to validate a four-digit number) or other validation attributes listed in the link above.
This is a common pitfall in PowerShell. When you invoke...
MakeMessage99(1, 100)
...you're actually passing an array containing the values 1 and 100 as the first parameter. To pass 1 as the first parameter and 100 as the second parameter, use...
MakeMessage99 1 100

Anonymous function with a variable-length argument list

Can I create an anonymous function that accepts a variable number of arguments?
I have a struct array S with a certain field, say, bar, and I want to pass all the bar values to my anonymous function foo. Since the number of elements in struct S is unknown, foo must be able to accept a variable number of arguments.
The closest thing that I've been able to come up with is passing a cell array as the input argument list:
foo({arg1, arg2, arg3, ...})
and I'm invoking it with foo({S.bar}), but it looks very awkward.
Creating a special m-file just for that seems like an overkill. Any other ideas?
Using varargin as the argument of the anonymous function, you can pass a variable number of inputs.
For example:
foo = #(varargin)fprintf('you provided %i arguments\n',length(varargin))
Usage
s(1:4) = struct('bar',1);
foo(s.bar)
you provided 4 arguments
va_arg in matlab called varargin here is the content of the link
:
varargin is an input variable in a function definition statement that
allows the function to accept any number of input arguments.
function varlist(varargin)
fprintf('Number of arguments: %d\n',nargin);
celldisp(varargin)
varlist(ones(3),'some text',pi)
Number of arguments: 3
varargin{1} =
1 1 1
1 1 1
1 1 1
varargin{2} =
some text
varargin{3} =
3.1416
define anonymous function as 2 of 4 outputs of m file function