The one and only general guideline to good programming style is: "Make it clear!" And one might extend that to
Make it clear – first of all to you, and then to the poor persons that take over your project (after you have been fired, because of writing illegible code).
Every possible style feature of the language should be used to express the meaning of the code more clearly.
Although often underestimated, the format, i.e. the visual layout of the source code itself can greatly help in the understanding of the actions described therein.
We often run into code like this
x=a*c+(x-y)^2*b
This is not bad, especially when typed at the command line for one-time use. However, the expression is not as clear as it could be. It can easily be improved by making the precedence levels (see also Section 4.3) of the operators stand out, as e.g.
x = a*c + b*(x-y)^2
Now, the assignment is intuitively clear at first glance. We use the word "intuitive" here alert the reader of the consequences of incorrectly formatting an expression. Then our intuition will mislead us, as in
x = a * c+(x-y)^2*b
Ouch! This expression is evaluated differently from what it is telling us. We should call it a liar.
See also Section 2.2 for the influence of whitespace on the evaluation of dotted operators.
Breaking a long expression into lines can improve its readability dramatically. It is particularly recommended for matrix definitions with the square bracket operator. See also Section 2.2.
For example
m1 = [ 1+%i -1+%i; .. -1+%i 1-%i ]
is superior to
m1 = [1+%i -1+%i; -1+%i 1-%i]
If an arithmetic expression is split into lines the operator at which the split occurs always goes onto the next line. Preferred break points occur right before operators of equal precedence.
d2 = fact * (a/(a+d)*(b*(1-delta) + d*delta) - d) * (P./K).^theta
for example becomes
d2 = fact * (a/(a+d)*(b*(1-delta) + d*delta) - d) .. * (P./K).^theta
or
d2 = fact .. * (a/(a+d)*(b*(1-delta) + d*delta) - d) .. * (P./K).^theta
or more dramatic
d2 = fact .. * ( .. a / (a+d) * (b*(1-delta) + d*delta) .. - d .. ) .. * (P./K).^theta
If spaces right inside parentheses or brackets of an expressions make the subexpression stand out more clearly, they should be used. That way
B(k) = a1 * exp(-b1*P(k)/K(k) + b2*Q(k)/K(k))
becomes
B(k) = a1 * exp( -b1*P(k)/K(k) + b2*Q(k)/K(k) )
All previous formatting suggestions of this sections have been concerned with horizontal spacing, and indentation. Vertical spacing is as important as horizontal!
As sentences belonging together go into one paragraph and paragraphs are seperated by one ore more blank lines, Scilab statements that belong together go into one visual block and the blocks should be seperated by single blank lines.
n = 1; lo = 1.0 - n*2*epslo(); // lo = pred(1) hi = 1.0 + n* epshi(); // hi = succ(1) for k = 2 : 4 x = lo : (hi - lo)/(k - 1) : hi; y = linspace(lo, hi, k); disp(size(x, "c") - k); disp(x - 1); disp(y - 1); end
If blank lines tear apart blocks of code within functions, it might be preferable to seperate pairs of adjacent functions by at least two blank lines.
function y = baseconv(x, b) // Convert decimal fraction X into a base-B number. Each // "digit" of the result is one element in the result // vector Y. To get a monolithic string, apply strcat to Y, // like // strcat(["#", baseconv(x, b), "#", string(b)]) if x >= 0 y = [] else y = ["-"] end y = [y, baseconv_integral(int(abs(x)), b)] if frac(x) == 0.0 return end if y == [] | y == ["-"] y = [y, "0"] end y = [y, ".", baseconv_frac(frac(abs(x)), b)] function y = baseconv_integral(x, b) // Convert decimal integer X >= 0 into a base-B number. Each // "digit" of the result is one element in the result // vector Y. if x < 0 error("integer X (arg 1) out of range; X >= 0.") end if b < 2 | b > 36 error("base B (arg 2) out of range; 2 <= B <= 36.") end if x == 0 y = ["0"] return end y = [] xv = abs(x) while xv >= 1 r = modulo(xv, b) if r <= 9 rs = string(r) else rs = code2str(r) end xv = int(xv / b) y = [rs, y] end function y = baseconv_frac(x, b) // Convert decimal fraction 0 < X < 1 into a base-B number. Each // "digit" of the result is one element in the result // vector Y. if x <= 0 | x >= 1 error("fraction X (arg 1) out of range; 0 < X < 1.") end if b < 2 | b > 36 error("base B (arg 2) out of range; 2 <= B <= 36.") end y = [] xv = x * b max_mant = prod(2.0 * ones(1, 52)) // 2^52 n = 1 while xv > 0 & n <= max_mant r = int(xv) if r <= 9 rs = string(r) else rs = code2str(r) end xv = frac(xv) * b y = [y, rs] n = n * b end if n >= max_mant warning("loss of precision") end function f = frac(x) // Return the fractional part of X. // int(X) + frac(X) == X for all X. f = x - int(x)