Message Boards Message Boards


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

Posted 10 months ago
6 Replies
3 Total Likes

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.

6 Replies

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 10 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.

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

Posted 10 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.

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.


(* Out[377]= Expectation[x$49573, x$49573 \[Distributed] pDist[t, 0.5]] *)
Posted 10 months ago

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

Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
or Discard

Group Abstract Group Abstract