KDB namespace of a function - kdb

I have a function
f:{[t;c];
q: (1.0;0.8;0.6;0.4;0.2);
tc:(cols[t] where cols[t] like c)[0];
sorted:desc t[tc];
qt:( {x: "i"$sorted["i"$x*count sorted]} each q) ! q;
k:asc key qt;
{[t;c;n;f] #[t;n;:;f t c]}[t;c;`quint;{[x] qt k k binr "i"$x}]
}
when I try to call it, it returns ERROR:sorted. It seems the variables declared inside the function are not accessible in {x: "i"$sorted["i"$x*count sorted]}. However, if I declare them outside the function then they are accessible (and I can call the function successfully). Is there a way to make them available to the {...}?

To access sorted you can pass it in as a argument to the function.
{"i"$x["i"$y*count x]}[sorted]each q
Same applies to the second lambda and on the last line too, again passing the arguments qt and k to it:
{x y y binr "i"$z}[qt;k]

Related

Can Julia macros be used to generate code based on specific function implementation?

I am fairly new to Julia and I am learning about metaprogramming.
I would like to write a macro that receive in input a function and returns another function based on the implementation details of its input.
For example given:
function f(x)
x + 100
end
function g(x)
f(x)*x
end
function h(x)
g(x)-0.5*f(x)
end
I would like to write a macro that returns something like that:
function h_traced(x)
f = x + 100
println("loc 1 x: ", x)
g = f * x
println("loc 2 x: ", x)
res = g - 0.5 * f
println("loc 3 x: ", x)
Now both code_lowered and code_typed seems to give me back the AST in the form of CodeInfo, however when I try to use it programmatically in my macro I get empty object.
macro myExpand(f)
body = code_lowered(f)
println("myExpand Body lenght: ",length(body))
end
called like this
#myExpand :(h)
however the same call outside the macro works ok.
code_lowered(h)
At last even the following return an empty CodeInfo.
macro myExpand(f)
body = code_lowered(Symbol("h"))
println("myExpand Body lenght: ",length(body))
end
This might be incredible trivial but I could not work out myseld why the h symbol does not resolve to the function defined. Am I missing something about the scope of symbols?
I find it useful to think about macros as a way to transform an input syntax into an output syntax.
So you could very well define a macro #my_macro such that
#my_macro function h(x)
g(x)-0.5*f(x)
end
would expand to something like
function h_traced(x)
println("entering function: x=", x)
g(x)-0.5*f(x)
end
But to such a macro, h is merely a name, an identifier (technically, a Symbol) that can be transformed into h_traced. h is not the function that is bound to this name (in the same way as x = 2 involves binding a name x, to an integer value 2, but x is not 2; x is merely a name that can be used to refer to 2). In contrast to this, when you call code_lowered(h), h gets evaluated first, and code_lowered is passed its value (which is a function) as argument.
Back to our macro: expanding to an expression that involves the definition of g and f goes way further than mere syntax transformations: we're leaving the purely syntactic domain, since such a transformation would need to "understand" that these are functions, look up their definitions and so on.
You are right to think about code_lowered and friends: this is IMO the adequate level of abstraction for what you're trying to achieve. You should probably look into tools like Cassette.jl or IRTools.jl. That being said, if you're still relatively new to Julia, you might want to get a bit more used to the language before delving too deeply into such topics.
You don't need a macro, you need a generated function. They can not only return code (Expr), but also IR (lowered code). Usually, for this kind of thing, people use Base.uncompressed_ast, not code_lowered. Both Cassette and IRTools simplify the implementation for you, in different ways.
The basic idea is:
Have a generated function that takes a function and its arguments
In that function, get the IR of that function, and modify it to your purposes
Return the new IR from the generated function. This will then be compiled and called on the original arguments.
A short demonstration with IRTools:
julia> IRTools.#dynamo function traced(args...)
ir = IRTools.IR(args...)
p = IRTools.Pipe(ir)
for (v, stmt) in p
IRTools.insertafter!(p, v, IRTools.xcall(println, "loc $v"))
end
return IRTools.finish(p)
end
julia> function h(x)
sin(x)-0.5*cos(x)
end
h (generic function with 1 method)
julia> #code_ir traced(h, 1)
1: (%1, %2)
%3 = Base.getfield(%2, 1)
%4 = Base.getfield(%2, 2)
%5 = Main.sin(%4)
%6 = (println)("loc %3")
%7 = Main.cos(%4)
%8 = (println)("loc %4")
%9 = 0.5 * %7
%10 = (println)("loc %5")
%11 = %5 - %9
%12 = (println)("loc %6")
return %11
julia> traced(h, 1)
loc %3
loc %4
loc %5
loc %6
0.5713198318738266
The rest is left as an exercise. The numbers of the variables are off, because they are, of course, shifted during the transformation. You'd have to add some bookkeeping for that, or use the substitute function on Pipe in some way (but I never quite understood it). If you need the name of the variables, you can get the IR with slots preserved by using a different method of the IR constructor.
(And now the advertisement: I have written something like this. It's currently quite inefficient, but you might get some ideas from it.)

kdb - resolving nested function when printing outer function body

I would like to print the function definition of any nested function when printing the definition of the outer function. Example:
g:{sin x}
f:{cos g x}
When I print f I get {cos g x} but I want to get {cos {sin x} x}
Thanks for the help
From what I am aware it is not possible to achieve that with in-build functions.
You can attempt to write your own function that does that but it will be a pain in the end. Something like this maybe:
q)m:string[v]!string value each v:value[f][3] except `
which creates a dictionary m :
q)m
,"g"| "{sin x}"
When given a function value returns a list containing (bytecode;parameters;locals(context;globals);constants[0];...;constants[n];definition)
However, if we pass a symbol to value it returns the value of that symbol (or function definition in this case).
You can then use ssr to replace the functions in f with the function definitions stored in your dictionary m.
q)ssr/[last value[f];key m;value m]
"{cos {sin x} x}"
but to ensure that your function is stable and adaptable to different functions would be very difficult.
For more details about how value have a look here: https://code.kx.com/q/ref/metadata/#value
For ssr check this link:
https://code.kx.com/q/ref/strings/#ssr

Difference between matlab function 'handle' and python function 'object'

It was suggested in this comment that there is a difference between how Matlab and Python pass around functions. From what I can tell by looking and using the two, there is no difference between the two, but maybe I'm missing something?
In Matlab, you would create a quick function handle like this:
fun = #(x) x.^2 + 1;
In Python, using a lambda function, you could create a similar function like this:
def fun(x):
return x^2
In both languages, it's possible to send the term 'fun' to another function as an argument - but the commenter I linked to insinuated that they are not the same and/or need to be used differently.
What am I missing?
The first comment seems to simply reiterate the idea that you can pass a MATLAB function handle as an argument (although the answer didn't state anything that would make me think otherwise). The second comment seemed to interpret this to mean that the first commenter thought that you couldn't do this in Python and responded to state that you can use either a lambda or pass the function directly.
Regardless, assuming that you use them correctly, a function handle in MATLAB is functionally equivalent to using either a lambda or function object as an input argument in Python.
In python, if you don't append the () to the end of the function, it doesn't execute the function and instead yields the function object which can then be passed to another function.
# Function which accepts a function as an input
def evalute(func, val)
# Execute the function that's passed in
return func(val)
# Standard function definition
def square_and_add(x):
return x**2 + 1
# Create a lambda function which does the same thing.
lambda_square_and_add = lambda x: x**2 + 1
# Now pass the function to another function directly
evaluate(square_and_add, 2)
# Or pass a lambda function to the other function
evaluate(lambda_square_and_add, 2)
In MATLAB, you have to use a function handle because MATLAB attempts to execute a function even if you omit the ().
function res = evaluate(func, val)
res = func(val)
end
function y = square_and_add(x)
y = x^2 + 1;
end
%// Will try to execute square_and_add with no inputs resulting in an error
evaluate(square_and_add)
%// Must use a function handle
evaluate(#square_and_add, 2)

Pass additional arguments to a built-in function

I'm pretty new on Julia and have a question that may appear simple. Say I have a function, which I will name test(x::Vector, arg1, arg2) where x is a vector of variables and the function has two arguments arg1 & arg2.
I would like to optimize (minimize) the function test with respect to the vector x. I can't figure out how to use the optimize function from the Optim package that accepts two arguments values. In R, one may do as following:
optim(initial guest, test, arg1=value1,arg2=value2)
Is there a similar way to declare argument value in Julia?
You can define another function that fixes the value of those arguments.
# Function to minimize
f(x::Vector, a, b) = (x[1] - a)^2 + (x[2] - b)^2
using Optim
g(x::Vector) = f(x, 3, 4)
optimize(g, [0.,0.])
You could also use an anonymous function (but it may be less efficient).
optimize(x -> f(x,3,4), [0.,0.])

Passing command lines to function to evaluate in Matlab

I have a function which is very open-ended that I use in several different applications. Instead of changing it everytime, I would like to pass several command lines as input for the function to evaluate using something like the eval function.
Thus, for example, my argument would be:
str={'a=32;
b=a+3*a^2+pi;
c=sin(a)+cos(b)^2;'}
then I could call the function with str as an argument:
x=func(str)
these lines would be evaluated inside the function
how?
Thanks alot!
I think #Daniel is right that function handles are the way forward. Based on your example, this is how you'd do it:
function x = testfun( a, bfun, cfun )
b = bfun(a);
c = cfun(a, b);
x = a + b + c;
end
Then you'd call it like this:
x = testfun( 32, #(a)(a+3*a^2+pi), #(a,b)(sin(a)+cos(b)^2) );