I was hoping you could give me some insight into your overall objective, but I think we're having some communication impedence because of unstated assumptions. So, I'll try to work up from basic principles. You could just jump to Daniel's example and take note of the Hold and ReleaseHold pattern, but maybe the following will also help.
"How do you pass an expression to a function". You just pass it. Based on your examples, though, this isn't quite what you wanted to ask. What you seem to want is to assign an unevaluated expression to a variable and then pass that variable to a function. Well, this is easy. The way to keep an expression from being evaluated is to wrap it in Hold
(or HoldComplete
or whichever Hold*
wrapper is appropriate for your situation). That entire Hold-wrapped expression is now available for whatever inspection you want to perform on it (pattern matching, extracting parts, etc). You can assign it to a variable and then reference that variable wherever you want.
In your notebook you say: "The defineF function is to define a global function with dynamic name, arguments and delayed body". This is a completely different question. The mechanisms for defining a function are already available with normal Mathematica patterns, and these mechanisms already deal with the need to hold expressions in unevaluated form. If you think about it, this must be the case. You wouldn't be able to inspect functions at all (e.g. with Information
) otherwise.
So, if you want a function named myFunc
that takes formal argument variables x
and y
and evaluates a body that uses those formal argument variables such as If[y=0=0,Indeterminate,x/y]
, then you can use SetDelayed
:
myFunc[x_,y_]:=If[y === 0, Indeterminate, x/y]
In effect, SetDelayed
is the defineF
that you're trying to define. But you know all of this. So, this is why I was asking about your ultimate objective. I understand that it's obvious in your mind, but if you can't elaborate, then I'll have to make some inferences.
Maybe you want to define an expression that represents the computation of a function and then assign that computational expression to a variable name. The simplest way to do that is to just use Function
:
myFunc = Function[{x, y}, If[y === 0, Indeterminate, x/y]]
The Function
expression on the right hand side could have been built up in whatever manner you want. Function
has the HoldAll
attribute, so you don't have to worry about premature evaluation.
Understand that this is different than SetDelayed
. It has to do with OwnValues
, UpValues
, DownValues
, and so forth. I don't know whether this is relevant in your context.
At this point you might be thinking, "but I want a DefineFunction function that takes three arguments: a function name, an argument list, and an expression body". But I'm going to assume that this thought is due to a misunderstanding. I know that's arrogant and dangerous, but I just can't see my way around it without more context from you. Here's the problem, the argument list and the expression body cannot be independent. You seem to be thinking of the body as an expression using formal variables. Thus, the argument list must be provided to indicate which are the formal variables. But formal variables are just a way to bind things. In the above example, I could have used this function:
Function[If[#2 === 0, Indeterminate, #1/#2]]
So, I'm guessing (and I apologize if I'm just missing a critical piece of your context) that what you really want is a way to bind an arbitrary variable to a function. I'm guessing that the need to separate out the computational expression from the argument list was just due to you thinking that you needed to dynamically generate a SetDelayed
expression.
If I'm on the right track here, then all you need to do to make this process "dynamic", is to define a function that takes a Symbol
(to use as the function name) and a Function
expression that will be used to do the computation.
DefineFunction[name_Symbol, body_Function] := (name = body)
Now, if you don't like requiring the body to already be a Function
, and instead you just want to pass in an expression, then there is a real semantic problem here, because you'll have to infer the formal arguments. You may be thinking, "exactly, that's why I wanted the arguments of DefineFunction to include an argument list for the formal arguments of the function to be defined". But the problem here is that if the caller has enough information to provide the formal arguments together with the expression that uses them, then the caller already has enough information to define a Function
. If you provide a convenience function for defining a function with an argument list and an expression body, then you've basically re-defined Function
.
I hope that with this information you can see your way to getting the behavior you want. I'm worried that I'm completely off base because I've misunderstood your actual objective, but I don't see how to proceed any further without more clarification from you.