I guess "apply" and "let" can do some work here. But I do not know the
variable names and number that the user would use.
So now I need a macro that can construct the let-apply block with the
variable number undetermined. The macro should be able to accept any number
of variables.
Suppose that the user inputs
func(x, y) = x+2y and x = 1, y = 2
@my_macro func (x=1, y=2) would be expanded to
let x = 1, y = 2
apply(func,1, 2)
end
And if the user inputs
func(a, b, c, d) = a + b + c + d, and a = 1, b = 2, c = 3, d=4
@my_macro func (a = 1, b = 2, c = 3, d = 4) would expand to
let a = 1, b = 2, c = 3, d = 4
apply(func, 1,2,3,4)
end
How to write a macro like this?
If I knew the function and the variables, of course I could directly call
the function or use let-apply, but the problem is that these are the inputs
of the user, which I cannot know beforehand.
On Sunday, February 2, 2014 8:11:34 AM UTC-8, Keno Fischer wrote:
>
> Or you could just call the function directly:
>
> f = (x,y,z)->x+y+z^2
> let x=3, y=4, z=5
> f(x,y,z)
> end
>
> or
>
> f((x,y,z)...)
>
> or
>
> f((1,2,3)...)
>
>
>
> On Sun, Feb 2, 2014 at 10:59 AM, Johan Sigfrids
> <[email protected]<javascript:>
> > wrote:
>
>> Can't you just do this with apply? Something like this:
>>
>> f = (x, y, z) -> x + y + z^2
>> let x=3, y=4, z=5
>> apply(f, x, y, z)
>> end
>>
>>
>> On Sunday, February 2, 2014 5:47:36 PM UTC+2, Walking Sparrow wrote:
>>>
>>> Let me clarify a little bit. My question is actually the following:
>>>
>>> In R, one can do something like
>>>
>>> > f <- function(x1, x2, x3, x4, x5, x6) { some expressions that you like
>>> to use }
>>> > evaluate.at <- list(x1 = 2, x2 = 2.3, x3 = 2, x4 = 1.2, x5 = 3.4, x6
>>> = 5.6)
>>> > do.call(f, evaluate.at) # get the value
>>>
>>> "do.call" can accept any valid function, and a list of variable values.
>>> There is no restriction to the function or the number of variables.
>>> Sometimes this is very useful.
>>>
>>> How do we do similar things in Julia? Does Julia have a function or
>>> macro similar to "do.call"?
>>>
>>> On Sunday, February 2, 2014 4:09:05 AM UTC-8, Mauro wrote:
>>>>
>>>> I don't quite comprehend your problem, so maybe this doesn't help. But
>>>> as far as I can tell, there is no need for macros:
>>>>
>>>> Just define your function as a normal function, which can be evaluated
>>>> for any (x,z):
>>>>
>>>> julia> f(x,z) = x + x*z + log(sin(x) + 2) * log(cos(z) + 2)
>>>> f (generic function with 1 method)
>>>> julia> x0 = 2.3; z0 = 1.4;
>>>> julia> f(x0,z0)
>>>> 6.302488546391614
>>>>
>>>> For the first step: use automatic differentiation on the function in
>>>> question. The package https://github.com/scidom/DualNumbers.jl can do
>>>> this:
>>>>
>>>> julia> using DualNumbers
>>>> julia> xdu = dual(x0,1)
>>>> 2.3 + 1.0du
>>>>
>>>> # this gives (f(x0,z0), \partial f / \partial x at (x0,z0)) :
>>>> julia> f(xdu,z)
>>>> 6.302488546391614 + 2.2120074784516013du
>>>>
>>>> julia> zdu = dual(z,1)
>>>> 1.4 + 1.0du
>>>> # this gives (f(x0,z0), \partial f / \partial z at (x0,z0)) :
>>>> julia> f(x,zdu)
>>>> 6.302488546391614 + 1.8413102782559223du
>>>>
>>>> (double check that the derivatives are right but I think that is how it
>>>> should work)
>>>>
>>>> On Sat, 2014-02-01 at 23:42, [email protected] wrote:
>>>> > You are right about that I have an R background. What I am trying to
>>>> do is
>>>> > to evaluate a function given by the user. For example,
>>>> >
>>>> > I want to write a function that can compute the marginal effects of a
>>>> > linear or logistic model. For simplicity, let's just use linear
>>>> regression.
>>>> > If the user did a linear regression using the following model (I am
>>>> using
>>>> > the formula syntax from R)
>>>> >
>>>> > y ~ x + z + sin(x) * sin(z) for the data set my_data, which has three
>>>> > columns x, y, and z
>>>> >
>>>> > Then the marginal effects at the mean are computed like this: First,
>>>> > compute the first derivative of 1+ x + z + sin(x) * sin(z). This can
>>>> be
>>>> > done in R using the function "deriv" to get the expression of the
>>>> first
>>>> > derivative. In the second step, I need to substitute the mean values
>>>> of x
>>>> > and z into the result of the first step. An example of this would be
>>>> the
>>>> > "margins" function in the R package "PivotalR"
>>>> > (http://cran.r-project.org/web/packages/PivotalR/ and
>>>> > https://github.com/gopivotal/PivotalR)
>>>> >
>>>> > Right now, I have no idea how to do the first step in Julia. But that
>>>> is
>>>> > OK, because I just started learning Julia.
>>>> >
>>>> > Now my question is in the second step. The user can use any complex
>>>> > expressions in the linear regression like y ~ x + x*z + log(sin(x) +
>>>> 2) *
>>>> > log(cos(z) + 2), and the data set my_data and formula can have any
>>>> number
>>>> > of variables like x1, x2, ...., x1000. So when you write the code for
>>>> the
>>>> > value substitution in the second step, you cannot know which function
>>>> and
>>>> > what variables you will have.
>>>> >
>>>> > So in Julia or R, I need a function or macro F(f, [....]) that does
>>>> this:
>>>> > given a function f, whose format is the input from the user, and a
>>>> set of
>>>> > variable values [...], whose number and names are also the input from
>>>> the
>>>> > user, F(f, [...]) returns the value of f evaluated at the values
>>>> [...]. For
>>>> > example, the user inputs
>>>> >
>>>> > f = 1 + z + cos(x)*log(2+cos(z))/(2+sin(x))
>>>> >
>>>> > and [x = 2.3, z = 1.4],
>>>> >
>>>> > F should return the value of f evaluated at x = 2.3 and z = 1.4.
>>>> >
>>>> > This can be done in R, see "margins" function in PivotalR, which
>>>> actually
>>>> > does big data computation in-database. The problem is how to do the
>>>> same
>>>> > thing in Julia?
>>>> >
>>>> > Hope my explanation makes my question clearer.
>>>> >
>>>> > On Saturday, February 1, 2014 2:35:38 PM UTC-8, Jameson wrote:
>>>> >>
>>>> >> You need to provide more detail on what you are trying to do with
>>>> this.
>>>> >> You seem
>>>> >> to be confusing several concepts involving the usage of expressions,
>>>> >> macros, and functions. I can't tell if you are trying to write
>>>> special
>>>> >> syntax, or are just unaware of anonymous functions:
>>>> >>
>>>> >> Mostly, why is :(sin(x) + cos(y) * sin(z)) an expression, and not a
>>>> >> function? It seems like you perhaps have an R background?
>>>> >>
>>>> >> f(x,y,z) = (sin(x) + cos(y) * sin(z))
>>>> >> f(1,2,3)
>>>> >>
>>>> >> On Sat, Feb 1, 2014 at 12:04 PM, Walking Sparrow <
>>>> [email protected]<javascript:>>
>>>> >> wrote:
>>>> >> > So the real question is how to generate a code block like this
>>>> >> >
>>>> >> > quote
>>>> >> > x = 2
>>>> >> > y = 3
>>>> >> > .....
>>>> >> > x + y + ....
>>>> >> > end
>>>> >> >
>>>> >> > Need to embed a for loop inside the macro definition?
>>>> >> >
>>>> >> >
>>>> >> >
>>>> >> > On Saturday, February 1, 2014 8:52:30 AM UTC-8, Walking Sparrow
>>>> wrote:
>>>> >> >>
>>>> >> >> Please forgive me if this is a stupid question. Suppose I have an
>>>> >> >> expression
>>>> >> >>
>>>> >> >> :(sin(x) + cos(y) * sin(z))
>>>> >> >>
>>>> >> >> and the values of x, y, z.
>>>> >> >>
>>>> >> >> How can I write a macro that can substitute the values of x, y, z
>>>> into
>>>> >> the
>>>> >> >> above expression? The number of values that I want to substitute
>>>> >> depends on
>>>> >> >> the actual use cases and thus is unknown.
>>>> >> >>
>>>> >> >> I wrote a function that can do this
>>>> >> >>
>>>> >> >> function substitute(expr::Expr, vals::Array{Expr,1})
>>>> >> >> for i = 1:length(vals)
>>>> >> >> @eval $(vals[i])
>>>> >> >> end
>>>> >> >> @eval $expr
>>>> >> >> end
>>>> >> >>
>>>> >> >> x = 10
>>>> >> >> y = 23
>>>> >> >>
>>>> >> >> substitute(:(x+y), [:(x = 2), :(y = 3)])
>>>> >> >>
>>>> >> >> x
>>>> >> >> y
>>>> >> >>
>>>> >> >> But if you run the above code, you will see that the values of
>>>> global x
>>>> >> >> and y are changed, which is not what I intend to do. This is
>>>> because
>>>> >> "eval"
>>>> >> >> does the evaluation in the global scope. Besides, I think it is a
>>>> bad
>>>> >> coding
>>>> >> >> pattern to use eval and it is slow.
>>>> >> >>
>>>> >> >> It would be better if this can be done using macro. But I have no
>>>> idea
>>>> >> >> about how to do this.
>>>> >>
>>>>
>>>> --
>>>> Sent with my mu4e
>>>>
>>>>
>