Using the Python C API, how can I write a function that accepts any number of arguments, including none at all? - python-c-api

METH_VARARGS requires at least one argument; METH_NOARGS doesn't seem to let me pass any at all.
How can I define a function build() that can be called as either build() or build(True)/build(False)?
Calling a METH_VARARGS function with no arguments results in:
TypeError: function takes exactly 1 argument (0 given)

I was thinking about the problem wrong. It's not the definition, but rather the parsing that rose my TypeError.
To prevent it, I just had to use "|O" instead of "O" in PyArg_ParseTuple!

Related

Call a kdb function passing another function as argument using sendSync method of qpython(kdb)

In the KDB server, we have two functions defined as
q)t:{0N!x[`min]; 0N!x[`max];}
q).up.map:{[keyList; valueList] keyList!valueList}
The KDB server, does not allow to pass dict()!() as an argument directly to a function, rather one has to use .up.map.
Calling t function from kdb would be like
q)t[.up.map[`min`max;10 20]]
I want to call the t function from qpython sendSync() method passing another function .up.map[`min`max;10 20] as an argument to t.
Unfortunately, I cannot find a solution in the qptyhon doc - https://qpython.readthedocs.io/en/latest/qpython.html#qpython.qconnection.QConnection.sendSync
Error -
When I tried sendSync() method, below error is raised -
qpython.qtype.QException: b'['
The KDB server, does not allow to pass dict()!() as an argument directly to a function, rather one has to use .up.map.
May I know why this is so? It's not a bad idea to challenge the original design before looking for workarounds. If dictionary were allowed as its parameter, it could have been as simple as
params = QDictionary(qlist(numpy.array(["min", "max"], dtype=numpy.string_), qtype=QSYMBOL_LIST),
qlist(numpy.array([10, 20], dtype=numpy.int64), qtype=QLONG_LIST))
with qconnection.QConnection(host='localhost', port=5000) as q:
q.sendSync("t", params)
If you want to do what you can do in q console via qpython, it's actually also simple: you pass the same string over. Effectively it's the same mechanism as a q client passing a string via IPC to the server, where the string is parsed and evaluated. Here you need to convert the input to the given string format in your Python code, thus not as clean as the above (although it looks more verbose).
with qconnection.QConnection(host='localhost', port=5000) as q:
q.sendSync("t[.up.map[`min`max;10 20]]")
Maybe you can use a lambda for this. That way it's just the arguments that need be serialized:
q.sendSync("{t[.up.map[x;y]]}", qlist(["min", "max"], qtype=QSYMBOL_LIST), [10, 20])
If that's not permitted, you could create it as a named wrapper function on the kdb side, which could be.
Alternatively, you could format your call with arguments as a string. A bit hacky; but workable for simple input.
q.sendSync(f"t[.up.map[`{'`'.join(['min', 'max'])};{' '.join(['10', '20'])}]]")

Spread syntax in function call in Reason

In Javascript you can use the spread syntax in a function call like this:
console.log(...[1,2,3]);
Is there an equivalent in Reason? I tried the following:
let bound = (number, lower, upper) => {
max(lower, min(upper, number));
};
let parameters = (1,0,20);
bound(...parameters) |> Js.log;
But this gives an unknown syntax error:
Try reason snippet
There's not. Reason is a statically typed language, and lists are dynamically-sized and homogenous. It would be of very limited use, and not at all obvious how it would deal with too few or too many arguments. If you want to pass a list, you should just accept a list and deal with it appropriately, as a separate function if desired.
You could of course use a tuple instead, which is fixed-size and heterogenous, but I don't see a use-case for that either, since you might as well just call the function directly then.
For JavaScript FFI there is however the bs.splice attribute, which will allow you to apply a variable number of arguments to a js function using an array. But it needs to be called with an array literal, not just any array.

Command syntax for matlab function still generates output?

There are two ways to call functions in Matlab, the command syntax and function syntax.
I am viewing a code written by someone else in which there's a statement as follows in one .m file:
params=sys_params;
while sys_params is defined as a function in another .m file as:
function params=sys_params()
params happens to be a structure.
What I wish to know is, if according to Matlab documentation, a command syntax cannot be used to output from a function, then how is the first statement working perfectly well?
Two things:
The distinction between command and function syntax comes into play when arguments are passed.
The parentheses for calling a function in MATLAB are optional when calling with no arguments. MATLAB will call the function without an invoking () unlike some other languages.
One exception to this that comes to mind is that () is required to invoke a function handle/anonymous function.
From Calling Functions:
To call a function that does not require any inputs and does not return any outputs, type only the function name
The one ambiguous thing not explicitly told there is that assigning output of such a function call is perfectly valid.
I'll note that I don't really like that () is optional as it hides function calls at-first-glance. Therefore, I try to use () as often as possible to make it clear I am invoking a function, so nearly all of my scripts start with clc();clear();.

"cannot call value of non-function type" error when attempting to call the max(_:_:) function

I'm trying to call the max function: max(x: T, y: T). However I keep getting the following error when I type max(2,3):
error: cannot call value of non-function type Int
var a = max(2, 3)
I am a beginner, and I have never encountered a function signature that uses a type "T". SO threads relating to using the max function call it in the manner I am (like max(2,3) ) so I am not sure where I am going wrong.
I am looking for an explanation on the "T" and how to call functions that support generic types and how to make the max function return 3 when comparing integers 2 and 3.
The problem (as you've confirmed in the comments) is that you have defined a variable named max, causing a naming conflict with the function max(_:_:).
The solution therefore is to either specify the Swift module namespace (as George suggested) in order to disambiguate the fact that you're referring to the max(_:_:) function:
Swift.max(2, 3)
Or, preferably, you should consider renaming your variable. I strongly suspect that there's a more descriptive name you could give it (remember, the Swift API Design Guidelines favours clarity over brevity).
Are you calling max within extension Int?
Try Swift.max(2, 3).

What is the difference between ByRef and Output method argument modifiers?

All is in the subject, really.
I fail to see what the difference in behavior is between those two methods for x:
// first version
Method m(ByRef x As whatever)
{
// play with x
}
// second version
Method m(Output x As whatever)
{
// play with x
}
There must be some reason why both those modifiers exist, however my "mastery" (uhm) of the language is not enough to understand the difference. I have tried and read the documentation, search it etc, to no avail so far.
So, what is the difference between those two argument modifiers?
Well those are just "prettifiers", they don't do much in terms of actual language behaviour, and only used to provide documentation. Idea is that arguments documented as ByRef provide both input and output, for example you can pass an array to be sorted, and Output arguments only provide output, for example list of errors. Output modifier was introduced later, and a lot of system code still use ByRef for both use cases.
If argument is actually passed by reference is only determined by method caller, and keyword doesn't really matter. You will call your method as ..m(.parameter) to pass variable by reference, and ..m(parameter) to pass variable by value.