I need to recreate the lists from the arguments
Is this all you really meant? Inside fn
, al
is a list of the arguments.
fn[args___] := Module[{al=List[args]},
...
]
The arguments can also be given their own names:
On[Assert];
fn[args : PatternSequence[a1_, a2_]] := Module[{al = List[args]},
Assert[a1 == al[[1]]];
Assert[a2 == al[[2]]];
Echo["OK"];
]
fn[1, 2]
Inside the 2nd function,
I would like to define, inside f
, a list={a1,a2}
and then redefine f[a1_,a2_]:=list[[1]]+list[[2]]
What do you mean by "redefine"? The best I can tell is that you're asking for a functor (a function-rewriting-function) that takes a function in one form, and returns a function that does the same job but in another form. Please provide concrete examples of a function before and after the modification.
If I were to guess, you want to write, literally, a function like: fn[a1_,a2_]:=a1+a2
, pass it to a functor, and get back a function like fn[args:PatternSequence[a1_,a2_]]:=Module[{al=List[args]}, al[[1]]+al[[2]] ]
.
More concretely, you'd want a rewriter
that can be used as follows: rewriter[fn[a1_,a2_]:=a1+a2]
returns HoldForm[fn[args:PatternSequance[a1_,a2_]]:=Module[{al=List[args]}, al[[1]]+al[[2]] ] ]
.
The held form can be then released (using ReleaseHold
), and the replacement function will be created. The original function can be Clear
-ed in the meantime, i.e. after using the rewriter
but before the held form is released.
Please confirm that that is indeed what you'd want. Otherwise, provide a concrete example of what you'd pass into the rewriter
, and what result you expect back. Thank you.
there is a bug that makes this not work in my case, we don't have to get into it
That has a strong smell of an XY Problem. Perhaps fixing that "bug" would be desirable instead of devising clumsy workarounds? Could you please give concrete examples of the "bug" you allude to?
I have a much more complicated function in my real case and I want to automate list by using such Mathematica constructs as Table and Array.
There are no fundamental differences between code that generates Part[argList, index]
vs code that generates Symbol["arg"<>ToString[index]]
.
For example, here's a function that creates a function definition for a function that sums a certain number of arguments. The function definition action (SetDelayed
) is inactive, so the form of the function can be inspected before the function definition is performed.
makeSum[fn_Symbol, count_Integer] :=
Module[{argSymbols, argPatterns},
argSymbols = Table[Symbol["a" <> ToString[i]], {i, count}];
argPatterns =
Activate[ Inactive[Pattern][#, Blank[]] & /@ argSymbols];
Inactivate[
fn[Sequence @@ argPatterns] := Total[argSymbols]
, SetDelayed
]
]
Clear[f2]
f2[3, 4] (* evaluates to f2[3,4] since f2 was cleared *)
makeSum[f2, 2] (* returns an inactive function definition *)
Echo[% // Activate, "Activating"] (* now the function definition is performed *)
f2[3, 4] (* evaluates to 7, since f2 is now defined: f2[a1_,a2_]:=a1+a2 *)
Mathematica's approach to controlling evaluation in the core language is a bit more clumsy than what you'd get in, say LISP macros. There is macro functionality in Mathematica, but it's not documented, so I didn't use it, even though it would get rid of some of the wrangling with active and inactive heads.
The argument symbols could have been also shielded from evaluating to something else by temporarily making them have no values (using a Block
), but I didn't bother with that. That's a TODO.
And of course, what Mathematica version do you use?
A bit of explanation of inactivations folllows. Recall that :=
is syntactic sugar for SetDelayed
. The two lines below are equivalent:
fn[_] := foo
SetDelayed[fn[_], foo]
Thus, we can create an inert function definition that will define the function only once SetDelayed
is activated:
Inactivate[ fn[_] := foo, SetDelayed ]
(* equivalent to *)
Inactivate[ SetDelayed[fn[_], foo], SetDelayed ]
(* evaluates to *)
Inactive[SetDelayed][fn[_], foo]
Thus, depending on preference and circumstances, we can either use Inactivate
and tell it what heads to deactivate, or use heads wrapped in Inactive
directly.
Inactivate[expr_]
wraps certain heads inside the expression inside an Inactive
head. In Mathematica, expression forms are fully recursive - the head of an expression is usually a symbol, e,g, SetDelayed
, but can be an expression itself, e.g. Inactive[SetDelayed]
. Example:
Inactivate[5 + 6, Plus]
(* evaluates to *)
Inactive[Plus][5,6]
Then, Activate[%]
will reactivate all inactive heads, then the expression will be evaluated, and the addition will be performed, thus Activate[%]
here will evaluate to 11.