Re: Length of a held expression
- To: mathgroup at smc.vnet.net
- Subject: [mg96599] Re: Length of a held expression
- From: Jens-Peer Kuska <kuska at informatik.uni-leipzig.de>
- Date: Tue, 17 Feb 2009 06:23:46 -0500 (EST)
- Organization: Uni Leipzig
- References: <gn8jdj$7qa$1@smc.vnet.net> <gncmhe$flg$1@smc.vnet.net>
- Reply-to: kuska at informatik.uni-leipzig.de
Hi, and Rules[] will not help ?? {a->10,b->20} intead of assigments ?? Regards Jens Nikolaus Rath wrote: > Hi, > > Nikolaus Rath <Nikolaus at rath.org> writes: >> Hello, >> >> How can I get the length of a list in a Hold[] expression? > > It seems that in my attempt to produce a short example, I also > simplified away the actual problem. So here it comes in slightly > longer form. > > I have written a function that propagates uncertainties in the > parameters of a function into the uncertainty of the result. It is > used as follows: > > error[a*b, {a, b}, {aErr, bErr}] > > --> {a b, Sqrt[Abs[aErr b]^2 + Abs[a bErr]^2]} > > so it yields the formula again, together with its error. > > However, usually the parameter already have values assigned to them > when I call the function. As was correctly pointed out, I can easily > circumvent this problem by packing the call into a Block[]: > > a = 10; > b = 20; > aErr = 1; > bErr = 2; > Block[{a,b}, > error[a*b, {a, b}, {aErr, bErr}]] > > > However, I was wondering if it might not be possible to handle this > case entirely in the error function, so that I can call > > a = 10; > b = 20; > aErr = 1; > bErr = 2; > error[a*b, {a, b}, {aErr, bErr}] > > and get the correct result. *So I am not really solving an actual > problem here*, I'm just playing with Mathematica's programming model > to see if it would allows me to do such a thing. > > > I figured out that, in order to be really able to work with the > unevaluated expression I cannot to wrap it in Hold[], but I have to > "escape" all the parameters that might otherwise be evaluated. So what > I'm doing is this: > > > SetAttributes[error, HoldAll]; > error::varno = "There must be the same number of variables and errors"; > error[expr_, vars_, errs_] := > Module[{safeExpr, safeVars, res, escapeRule, restoreRule, varno}, > varno = Length[vars]; > > If[varno != Length[errs], > Message[error::varno]; > Throw[$Failed]; > ]; > > (* This replaces the given variables (which may have global definition= > s) by local ones *) > escapeRule = Table[ > Extract[Hold[vars], {1, i}, HoldPattern] -> safeVars[i], > {i, varno}]; > > (* This restores the original values of the variables *) > restoreRule = Table[safeVars[i] -> vars[[i]], {i, varno}]; > > (* Escape variables, so that we can differentiate the expression *) > safeExpr = ReleaseHold[Hold[expr] /. escapeRule]; > > (* Calculate result with error *) > {expr, > Sqrt[Plus @@ Table[ > Abs[D[safeExpr, safeVars[i]] errs[[i]] /. restoreRule ]^2, > {i, varno}]]} > ] > > This indeed works nicely, except for one thing: in order to replace > all the global variables in the expression by local ones, I have to > iterate over the list of parameters, which in turn requires me to know > it's length. > > However, if I'm calculating the length with Length[vars] as above, > vars is evaluated first which may, in theory, change its length. (I > cannot really come up with an example where this may actually happen, > but as I said I'm not trying to solve a real problem anyway). > > > Now that I've written this all up so nicely, I also realize that the > solution with Length[Unevaluated[vars]] will also work for this case. > I'm mailing this anyway now, since I've already spend so much time > writing it. Maybe someone else can come up with a more elegant version > to do the above, so this mail wasn't entirely pointless :-). > > > > Best, > > -Nikolaus > > -- > =C2=BBTime flies like an arrow, fruit flies like a Banana.=C2=AB > > PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C >