It is possible to define my own With
construct where each local constant can depend on the previous defined local constants?
I wish to replace something like this
With[{m=10},
With[{h=1/m},
Table[{i h}, {i, 0, m}]
]
]
with something like this
WithMany[{m=10, h=1/m},
Table[{i h}, {i, 0, m}]
]
The very basic idea is to use Fold
:
Attributes[WithMany] := {HoldAll};
WithMany[{vars___}, body_] := Fold[With[{#2}, #1] &, body, {vars}]
but we need to properly evaluate the argumens in a non-standard way, possibly using Hold
and related constructs. I'm not so fluent with this.
An improvement would be to use the minimum number of With constructs depending on the dependencies between variables.
Any help will be appreciated.
EDIT As several people pointed out the original question has already been answered. This solve my immediate needs but I'm still interested to other implementation.
@Leonid Shifrin think the referred answer already use the best approach, the simplest, the most elegant, the most efficient and so, but, even if true, I consider an interesting programming exercise to try different approach, like the one in my original question, using functional programming and Fold
The sketch of a possible implementation is the following:
Attributes[WithMany] := {HoldAll};
WithMany[vars : {__}, body_] :=
Block[{With},
Attributes[With] = {HoldAll};
ReleaseHold@Fold[
With[{#2}, #1] &,
Hold[body],
Reverse@Thread@Hold@vars
]
]
I don't understand if there is some limit or issue with this implementation, or if it is fully equivalent to the one in the referred answer and to nested With
costruct (after adding Syntax coloring and handling SetDelayed
)?
At a first sight I like more my approach (if it works properly of course) and I think is cleaner. It also appears slightly faster, according to some very basic tests. But I recognize that some people might prefer a different approach.
With
, recursion is IMO the most natural road to proceed here. $\endgroup$Fold
is a construct for implementing recursion without the need of spreading the definition of a construct across multiple rules. IMO, if usable here, is better. So I edited the question to investigate this approach... $\endgroup$Fold
here, but at the point where you start being interested not in just having a solution to the problem, but having it in a specific way, it all becomes speculative. So, in this new formulation I'd consider this either opinion-based, or too narrow. Technically, I don't see here anything deeper than just another exercise in evaluation control. But may be I am wrong. Let's see what others think. $\endgroup$Fold
does not implement recursion. It actually does the opposite - it kills it, for a rather small subset of all cases where recursion can be used. There are lots of more complex cases where recursion can not be reduced toFold
. And I personally view recursion cleaner and more idiomatic, in lots of cases. And, as I said, strictly more powerful thanFold
. This is not to say that I don't appreciateFold
- if you look at the code I posted on this site, you'll see that I useFold
rather frequently. $\endgroup$