Message Boards Message Boards

[✓] How to build a function? (as it is understood by a programmer)

GROUPS:

I am a beginner. I keep running into the same problem over and over. Please, consider this code:

P[N_Integer, p_] = BinomialDistribution[N,p];
Y[D_] = Expectation[x, x\[Distributed]P[D,0.5]];
DiscretePlot[Y[x], {x, 0, 20}, ExtentSize -> 0.8]

All I need is to plot expected value of BinomialDistribution[x,0.5] where x is in [0,20] range. But because the way symbolic substitution works -- this code fails (because I used x as parameter in both DiscretePlot invocation and Y definition).

How should I rewrite this code in such way that in DiscretePlot I don't need to care about parameter names used by Y (or any other symbols/definitions it may depends on)? Should I use CompileFunction?

Thank you.

POSTED BY: Michael Kilburn
Answer
5 months ago

Unscoped x from Expectation interferes with DiscretePlot's x. Don't have experience with Expectation and friends so don't know what is the best practice but you can either scope x writing:

Y[D_] = Module[{x}, Expectation[x, x \[Distributed] P[D, 0.5]]]

or use formal variables like so:

Y[D_] = Expectation[\[FormalX], \[FormalX] \[Distributed] P[D, 0.5]];

Additinaly, try to avoid single capital letters, D and N are built in symbols. Lookup the difference between = and := too. Does not matter here but that is a general note.

Summing up:

ClearAll[P, Y];
P[n_Integer, p_] := BinomialDistribution[n, p];
Y[d_] := Expectation[\[FormalX], \[FormalX] \[Distributed] P[d, 0.5]];

DiscretePlot[Y[x], {x, 0, 20}, ExtentSize -> 0.8]

enter image description here

POSTED BY: Kuba Podkalicki
Answer
5 months ago

Pretty sure formal parameter doesn't help in this case. I never seen this concept in introductory material, but I looked it up and its seems like just a symbol with extra condition attached -- "can't be used on left side of = or :=".

This example supports this notion -- it fails exactly with the same error message as code in original post:

ClearAll[P, Y];
P[n_Integer, p_] = BinomialDistribution[n, p];
Y[d_] = Expectation[\[FormalX], \[FormalX] \[Distributed] P[d, 0.5]];
DiscretePlot[Y[\[FormalX]], {\[FormalX], 0, 20}, ExtentSize -> 0.8]

Using Module works. Thank you very much. Maybe this idea makes sense -- a mode where "Module logic" is applied to every expression automatically, unless I specifically denote symbol as "belonging to outside". Smth like:

ClearAll[::P, ::Y];
P[n_Integer, p_] = ::BinomialDistribution[n, p];
Y[d_] = ::Expectation[x, x \[Distributed] ::P[d, 0.5]];
::DiscretePlot[::Y[x], {x, 0, 20}, ExtentSize -> 0.8]

Hmm... doesn't look very readable, but very explicit and hard to make the error I am having trouble with.

POSTED BY: Michael Kilburn
Answer
5 months ago

I did not say to use \[FormalX] in Plot.

POSTED BY: Kuba Podkalicki
Answer
5 months ago

Yes, that suggestion seems to boil down to "use different class of identifiers and this will guarantee absence of name collisions". Unfortunately it is not going to work in more generic case of formulas/functions with multiple nesting levels.

POSTED BY: Michael Kilburn
Answer
5 months ago

One way to avoid the scope-capture issue is to hide the dummy variable. Could use Module for this.

pDist[n_Integer, p_] = BinomialDistribution[n, p];
y[d_] = Module[{x}, Expectation[x, x \[Distributed] pDist[d, 0.5]]];

Does not look so pretty, but it effectively gets the desired the scoping.

y[t]

(* Out[377]= Expectation[x$49573, x$49573 \[Distributed] pDist[t, 0.5]] *)
POSTED BY: Daniel Lichtblau
Answer
5 months ago

Thank you, Daniel. It seems that this is the only way -- I can't find any other...

POSTED BY: Michael Kilburn
Answer
5 months ago

Group Abstract Group Abstract