Skip to main content

coding style - Is there a guideline about when to end expressions with semicolons?


Whether for nested Ifs or within scoping constructs like Module and Block, I never know whether to end the final expression with a semicolon. I know the semicolon suppresses output, but, for example, in a series of nested Ifs, one needs only to semicolon the outermost If to suppress output.


So, is it better practice to semicolon everything unless output is needed? Or is it better to semicolon nothing until the last point where output is unwanted?



Answer



I may be missing the point of this question, but I think it is important to note that ; is the short form of CompoundExpression, and it is not primarily for suppressing output.


You can see how ; is interpreted using one of the methods I described here:


HoldForm @ FullForm[a; b; c]
HoldForm @ FullForm[a; b;]



CompoundExpression[a, b, c]
CompoundExpression[a, b, Null]

Note that when a final expression is omitted Null is inserted, just like this behavior with ,:


{1, 2,}


{1, 2, Null}


The suppression of output is not a behavior of CompoundExpression but rather Null, which when returned as output (alone) is not printed. For example 2 Null/2 evaluates to Null, therefore when given as input no output is printed.


There is little point in sprinkling ; around your code without need, unless perhaps as a visual reminder that the evaluated form of a given expression is not directly used by the surrounding head. One exception is when writing code that will eventually be made into a function or Module as line breaks are not valid separators in this case, therefore even functions that already return Null such as SetDelayed should be terminated with a ;, e.g.:


foo[bar_Integer] := bar^2;
foo[bar_Real] := bar/2;

This avoids the error seen with:


Module[{foo},
foo[bar_Integer] := bar^2
foo[bar_Real] := bar/2
]




What ; is really for


The actual function of CompoundExpression is described in the documentation:



expr1;expr2; ... evaluates the expri in turn, giving the last one as the result.



CompoundExpression, while more succinct and canonical than other methods, is not the only way to accomplish this. For example you could use


Last[{expr1, expr2, ...}]

in the same manner, e.g.:

a = 5; b = a^2; Binomial[b, a]
Last[{a = 5, b = a^2, Binomial[b, a]}]


53130

53130

And suppression of output:




x = Range@500;           
Last[{x = Range@500,}] (* no output printed *)

You can also return a specific expression using Slot in a simple Function:


#2 &[a = 5, b = a^2, Binomial[b, a]]


25

This is specifically appropriate when you need to perform some action after generating an expression, such as closing a stream:



str = StringToStream["abcdefg 123456"];
# &[Read[str, Word], Close @ str]


"abcdefg"

I would be remiss not to mention that these alternative methods are not actually equivalent to CompoundExpression because even though they only return one expression (possibly Null) they still accumulate all of them in memory. Compare these, each pair of lines run in a fresh Kernel:


Range@1*^7; Range@1*^7; Range@1*^7; Range@1*^7;
MaxMemoryUsed[]



94923152

Last[{Range@1*^7, Range@1*^7, Range@1*^7, Range@1*^7,}]
MaxMemoryUsed[]


174925336

To get the memory performance of ; one would need something more complex, such as:



SetAttributes[ce, HoldAll]
ce[x__] := Fold[#2 &, , Hold @ x]

ce[Range@1*^7, Range@1*^7, Range@1*^7, Range@1*^7,]
MaxMemoryUsed[]


93506816




Additional reading:



Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

equation solving - Invert and fit implicitly defined curve

I need to fit an implicitly defined curve. I thought I could get some data out of Solve , and then using FindFit . Therefore, I would like to find the relation the parametric curve defined by $F(x,y)=0$: Solve[-(1/2) + 1/2 (0.41202 BesselK[0, 0.1 Sqrt[x^2 + y^2]] + (0.101483 x BesselK[1, 0.1 Sqrt[x^2 + y^2]])/Sqrt[x^2 + y^2]) == 0, y] But I can't get an output: Solve was unable to solve the system with inexact coefficients or the system obtained by direct rationalization of inexact numbers present in the system. Since many of the methods used by Solve require exact input, providing Solve with an exact version of the system may help. >> Edit: In particular, I would like to fit the data coming from the curve with the expression of another curve, and not with a function $f(x)$. In particular, since this clearly looks like a cardioid , I would like it to fit to something like it. What other strategies could I try?

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...