Means of expression: Difference between revisions
(introduction) |
(variables instead of comments) |
||
Line 5: | Line 5: | ||
It is generally good style to remember the rule: | It is generally good style to remember the rule: | ||
: Prefer primary means of expression to secondary ones! | : ''Prefer primary means of expression to secondary ones!'' | ||
The reason is that, elements that are relevant to the compiler are checked by the compiler and can be processed by documentation, analysis and refactoring tools. | The reason is that, elements that are relevant to the compiler are checked by the compiler and can be processed by documentation, analysis and refactoring tools. | ||
Line 12: | Line 12: | ||
== Examples == | == Examples == | ||
=== Expressive variable names instead of comments === | |||
=== Expressive | |||
I recently saw code like | I recently saw code like | ||
Line 33: | Line 30: | ||
</haskell> | </haskell> | ||
=== | === Variables instead of comments === | ||
<haskell> | |||
solveSLE2 :: Fractional a => ((a,a), (a,a)) -> (a,a) -> (a,a) | |||
solveSLE2 ((a00,a10),(a01,a11)) (b0,b1) = | |||
let det = a00*a11 - a10*a01 | |||
in (-- determinant with first column replaced by b | |||
(b0*a11 - b1*a01) / det, | |||
-- determinant with second column replaced by b | |||
(a00*b1 - a10*b0) / det) | |||
</haskell> | |||
It is likely that logical units like the 2x2 determinant are reused later (e.g. for the vector product) | |||
or that they should be tested separately. | |||
Thus it is better to factor them out into separate functions. | |||
<haskell> | |||
solveSLE2 :: Fractional a => ((a,a), (a,a)) -> (a,a) -> (a,a) | |||
solveSLE2 a@(a0,a1) b = | |||
let det = det2 a | |||
in (det2 (b, a1) / det, | |||
det2 (a0, b) / det) | |||
det2 :: Num a => ((a,a), (a,a)) -> a | |||
det2 ((a00,a10),(a01,a11)) = a00*a11 - a10*a01 | |||
</haskell> | |||
=== Types instead of comments === | |||
<haskell> | |||
-- | returned list contains at most one element | |||
foo :: [a] -> [a] | |||
</haskell> | |||
This can be expressed without comments more safely and concisely | |||
<haskell> | |||
foo :: [a] -> Maybe a | |||
</haskell> | |||
== See also == | == See also == |
Revision as of 11:41, 4 March 2008
Programming languages have different types of means of expression:
- Primary means of expression: variables, types, parentheses, etc. in general all things that are relevant to the compiler
- Secondary means of expression: layout, comments, etc. that is language elements that are irrelevant for the compiler, and thus are made exclusively for the human reader
In Haskell (as well as in Python) one has to weaken that because layout is interpreted by the compiler.
It is generally good style to remember the rule:
- Prefer primary means of expression to secondary ones!
The reason is that, elements that are relevant to the compiler are checked by the compiler and can be processed by documentation, analysis and refactoring tools. Thus it is not good style to comment intensively if there are better ways to express our ideas.
Examples
Expressive variable names instead of comments
I recently saw code like
-- | first name
fn :: Person -> String
-- | surname
sn :: Person -> String
It was hard to read the program because there were several other two-character function names to remember, and the comment was only attached to the function definition, not the calls. The comments would be better replaced by expressive function names like
firstName :: Person -> String
surname :: Person -> String
Variables instead of comments
solveSLE2 :: Fractional a => ((a,a), (a,a)) -> (a,a) -> (a,a)
solveSLE2 ((a00,a10),(a01,a11)) (b0,b1) =
let det = a00*a11 - a10*a01
in (-- determinant with first column replaced by b
(b0*a11 - b1*a01) / det,
-- determinant with second column replaced by b
(a00*b1 - a10*b0) / det)
It is likely that logical units like the 2x2 determinant are reused later (e.g. for the vector product) or that they should be tested separately. Thus it is better to factor them out into separate functions.
solveSLE2 :: Fractional a => ((a,a), (a,a)) -> (a,a) -> (a,a)
solveSLE2 a@(a0,a1) b =
let det = det2 a
in (det2 (b, a1) / det,
det2 (a0, b) / det)
det2 :: Num a => ((a,a), (a,a)) -> a
det2 ((a00,a10),(a01,a11)) = a00*a11 - a10*a01
Types instead of comments
-- | returned list contains at most one element
foo :: [a] -> [a]
This can be expressed without comments more safely and concisely
foo :: [a] -> Maybe a
See also
Johannes Waldmann: Haskell mit Stil