Ad-hoc conversion to markdown.
This commit is contained in:
parent
3667e0f898
commit
173c721611
|
@ -1,6 +1,4 @@
|
||||||
|
# su4sml coding style
|
||||||
su4sml coding style
|
|
||||||
===================
|
|
||||||
|
|
||||||
We here document coding-style guidelines that should be adhered to.
|
We here document coding-style guidelines that should be adhered to.
|
||||||
Much of the existing code is not yet following these guidelines,
|
Much of the existing code is not yet following these guidelines,
|
||||||
|
@ -8,8 +6,7 @@ patches are welcome. This style-guide was inspired by the SML Style Guide
|
||||||
from Cornell university [1].
|
from Cornell university [1].
|
||||||
|
|
||||||
|
|
||||||
Chapter 1: Indentation and breaking long lines
|
## Chapter 1: Indentation and breaking long lines
|
||||||
==========
|
|
||||||
|
|
||||||
The limit on the length of lines is 80 columns and this is a hard
|
The limit on the length of lines is 80 columns and this is a hard
|
||||||
limit. Using more than 80 columns causes your code to wrap around to
|
limit. Using more than 80 columns causes your code to wrap around to
|
||||||
|
@ -20,21 +17,21 @@ spaces to control indenting. Indent by two spaces.
|
||||||
|
|
||||||
Long expressions can be broken up and the parts aligned, as in the second
|
Long expressions can be broken up and the parts aligned, as in the second
|
||||||
example. Either is acceptable.
|
example. Either is acceptable.
|
||||||
|
```sml
|
||||||
val x = "Long line..."^
|
val x = "Long line..."^
|
||||||
"Another long line."
|
"Another long line."
|
||||||
|
|
||||||
val x = "Long line..."^
|
val x = "Long line..."^
|
||||||
"Another long line."
|
"Another long line."
|
||||||
|
```
|
||||||
Case expressions should be indented as follows:
|
Case expressions should be indented as follows:
|
||||||
|
```sml
|
||||||
case expr of
|
case expr of
|
||||||
pat1 => ...
|
pat1 => ...
|
||||||
| pat2 => ...
|
| pat2 => ...
|
||||||
|
```
|
||||||
If expressions should be indented according to one of the following schemes:
|
If expressions should be indented according to one of the following schemes:
|
||||||
|
```sml
|
||||||
if exp1 then exp2 if exp1 then
|
if exp1 then exp2 if exp1 then
|
||||||
else if exp3 then exp4 exp2
|
else if exp3 then exp4 exp2
|
||||||
else if exp5 then exp6 else exp3
|
else if exp5 then exp6 else exp3
|
||||||
|
@ -42,13 +39,12 @@ else if exp5 then exp6 else exp3
|
||||||
|
|
||||||
if exp1 then exp2 else exp3 if exp1 then exp2
|
if exp1 then exp2 else exp3 if exp1 then exp2
|
||||||
else exp3
|
else exp3
|
||||||
|
```
|
||||||
Comments should be indented to the level of the line of code that follows the
|
Comments should be indented to the level of the line of code that follows the
|
||||||
comment.
|
comment.
|
||||||
|
|
||||||
|
|
||||||
Chapter 2: Factoring
|
## Chapter 2: Factoring
|
||||||
==========
|
|
||||||
|
|
||||||
Avoid breaking expressions over multiple lines. If a tuple consists of more
|
Avoid breaking expressions over multiple lines. If a tuple consists of more
|
||||||
than two or three elements, you should consider using a record instead of a
|
than two or three elements, you should consider using a record instead of a
|
||||||
|
@ -60,16 +56,17 @@ multiple lines to something that has good style is to factor the code using a
|
||||||
let expression. Consider the following:
|
let expression. Consider the following:
|
||||||
|
|
||||||
Bad
|
Bad
|
||||||
|
```sml
|
||||||
fun euclid (m:int,n:int) : (int * int * int) =
|
fun euclid (m:int,n:int) : (int * int * int) =
|
||||||
if n=0
|
if n=0
|
||||||
then (b 1, b 0, m)
|
then (b 1, b 0, m)
|
||||||
else (#2 (euclid (n, m mod n)), u - (m div n) *
|
else (#2 (euclid (n, m mod n)), u - (m div n) *
|
||||||
|
|
||||||
(euclid (n, m mod n)), #3 (euclid (n, m mod n)))
|
(euclid (n, m mod n)), #3 (euclid (n, m mod n)))
|
||||||
|
```
|
||||||
|
|
||||||
Better
|
Better
|
||||||
|
```sml
|
||||||
fun euclid (m:int,n:int) : (int * int * int) =
|
fun euclid (m:int,n:int) : (int * int * int) =
|
||||||
if n=0
|
if n=0
|
||||||
then (b 1, b 0, m)
|
then (b 1, b 0, m)
|
||||||
|
@ -78,7 +75,7 @@ Better
|
||||||
u - (m div n) * (euclid (n, m mod n)),
|
u - (m div n) * (euclid (n, m mod n)),
|
||||||
|
|
||||||
#3 (euclid (n, m mod n)))
|
#3 (euclid (n, m mod n)))
|
||||||
|
```
|
||||||
Best
|
Best
|
||||||
|
|
||||||
fun euclid (m:int,n:int) : (int * int * int) =
|
fun euclid (m:int,n:int) : (int * int * int) =
|
||||||
|
@ -94,38 +91,36 @@ Best
|
||||||
|
|
||||||
|
|
||||||
Do not factor unnecessarily.
|
Do not factor unnecessarily.
|
||||||
|
|
||||||
Bad
|
Bad
|
||||||
|
```sml
|
||||||
let
|
let
|
||||||
val x = TextIO.inputLine TextIO.stdIn
|
val x = TextIO.inputLine TextIO.stdIn
|
||||||
in
|
in
|
||||||
case x of
|
case x of
|
||||||
...
|
...
|
||||||
end
|
end
|
||||||
|
```
|
||||||
|
|
||||||
Good
|
Good
|
||||||
|
```sml
|
||||||
case TextIO.inputLine TextIO.stdIn of
|
case TextIO.inputLine TextIO.stdIn of
|
||||||
...
|
...
|
||||||
|
```
|
||||||
Bad (provided y is not a large expression):
|
Bad (provided y is not a large expression):
|
||||||
|
```sml
|
||||||
let val x = y*y in x+z end
|
let val x = y*y in x+z end
|
||||||
|
```
|
||||||
|
|
||||||
Good
|
Good
|
||||||
|
```sml
|
||||||
y*y + z
|
y*y + z
|
||||||
|
```
|
||||||
|
|
||||||
|
## Chapter 3: Comments
|
||||||
Chapter 3: Comments
|
|
||||||
==========
|
|
||||||
|
|
||||||
Comments should be written with SMLDoc [2] in mind; a, nightly updated, API
|
Comments should be written with SMLDoc [2] in mind; a, nightly updated, API
|
||||||
documentation is available [3]. For example:
|
documentation is available [3]. For example:
|
||||||
|
```sml
|
||||||
(**
|
(**
|
||||||
* opens a file.
|
* opens a file.
|
||||||
* @params {fileName, mode}
|
* @params {fileName, mode}
|
||||||
|
@ -133,21 +128,22 @@ documentation is available [3]. For example:
|
||||||
* @param mode mode flag
|
* @param mode mode flag
|
||||||
* @return file stream *)
|
* @return file stream *)
|
||||||
val openFile : {fileName : string, mode : openMode} -> stream
|
val openFile : {fileName : string, mode : openMode} -> stream
|
||||||
|
```
|
||||||
We mainly restrict ourselves to the following SMLDoc tags:
|
We mainly restrict ourselves to the following SMLDoc tags:
|
||||||
|
```
|
||||||
@params gives names to formal parameters of functions and value constructors
|
@params gives names to formal parameters of functions and value constructors
|
||||||
@param a description of a formal parameter
|
@param a description of a formal parameter
|
||||||
@return a description about return value of the function
|
@return a description about return value of the function
|
||||||
@see related items (specified text is not analyzed in the current version)
|
@see related items (specified text is not analyzed in the current version)
|
||||||
@throws same as the @exception tag
|
@throws same as the @exception tag
|
||||||
|
```
|
||||||
Signatures must be commented using SMLDoc.
|
Signatures must be commented using SMLDoc.
|
||||||
|
|
||||||
Comments go above the code they reference, as in the following example:
|
Comments go above the code they reference, as in the following example:
|
||||||
|
```sml
|
||||||
(** Sums a list of integers. *)
|
(** Sums a list of integers. *)
|
||||||
val sum = foldl (op +) 0
|
val sum = foldl (op +) 0
|
||||||
|
```
|
||||||
Avoid Useless Comments. Avoid comments that merely repeat the code they
|
Avoid Useless Comments. Avoid comments that merely repeat the code they
|
||||||
reference or state the obvious. Comments should state the invariants, the
|
reference or state the obvious. Comments should state the invariants, the
|
||||||
non-obvious, or any references that have more information about the code.
|
non-obvious, or any references that have more information about the code.
|
||||||
|
@ -172,17 +168,16 @@ Multi-line Commenting. When comments are printed on paper, the reader lacks the
|
||||||
advantage of color highlighting performed by an editor such as Emacs.
|
advantage of color highlighting performed by an editor such as Emacs.
|
||||||
Multiline comments can be distinguished from code by preceding each line of the
|
Multiline comments can be distinguished from code by preceding each line of the
|
||||||
comment with a * similar to the following:
|
comment with a * similar to the following:
|
||||||
|
```sml
|
||||||
(**
|
(**
|
||||||
* This is one of those rare but long comments
|
* This is one of those rare but long comments
|
||||||
* that need to span multiple lines because
|
* that need to span multiple lines because
|
||||||
* the code is unusually complex and requires
|
* the code is unusually complex and requires
|
||||||
* extra explanation. *)
|
* extra explanation. *)
|
||||||
fun complicatedFunction () = ...
|
fun complicatedFunction () = ...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Chapter 4: Parentheses
|
||||||
Chapter 4: Parentheses
|
|
||||||
==========
|
|
||||||
|
|
||||||
Over Parenthesizing. Parentheses have many semantic purposes in ML, including
|
Over Parenthesizing. Parentheses have many semantic purposes in ML, including
|
||||||
constructing tuples, grouping sequences of side-effect expressions, forcing a
|
constructing tuples, grouping sequences of side-effect expressions, forcing a
|
||||||
|
@ -198,7 +193,7 @@ already wrapped by a let...in...end block, you can drop the parentheses.
|
||||||
Alternative Block Styles. Blocks of code such as let...in...end, struct...end,
|
Alternative Block Styles. Blocks of code such as let...in...end, struct...end,
|
||||||
and sig...end should be indented as follows. There are several alternative
|
and sig...end should be indented as follows. There are several alternative
|
||||||
styles to choose from.
|
styles to choose from.
|
||||||
|
```sml
|
||||||
fun foo bar = fun foo bar = fun foo bar = let
|
fun foo bar = fun foo bar = fun foo bar = let
|
||||||
let let val p = 4 val p = 4
|
let let val p = 4 val p = 4
|
||||||
val p = 4 val q = 38 val q = 38
|
val p = 4 val q = 38 val q = 38
|
||||||
|
@ -206,11 +201,10 @@ fun foo bar = fun foo bar = fun foo bar = let
|
||||||
in bar * (p + q) bar * (p + q)
|
in bar * (p + q) bar * (p + q)
|
||||||
bar * (p + q) end end
|
bar * (p + q) end end
|
||||||
end
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Chapter 5: Pattern matching
|
||||||
Chapter 5: Pattern matching
|
|
||||||
==========
|
|
||||||
|
|
||||||
No Incomplete Pattern Matches. Incomplete pattern matches are flagged with
|
No Incomplete Pattern Matches. Incomplete pattern matches are flagged with
|
||||||
compiler warnings, which should be treated as errors.
|
compiler warnings, which should be treated as errors.
|
||||||
|
@ -219,7 +213,7 @@ Pattern Match in the Function Arguments When Possible. Tuples, records and
|
||||||
datatypes can be deconstructed using pattern matching. If you simply
|
datatypes can be deconstructed using pattern matching. If you simply
|
||||||
deconstruct the function argument before you do anything useful, it is better
|
deconstruct the function argument before you do anything useful, it is better
|
||||||
to pattern match in the function argument. Consider these examples:
|
to pattern match in the function argument. Consider these examples:
|
||||||
|
```sml
|
||||||
Bad Good
|
Bad Good
|
||||||
fun f arg1 arg2 = let fun f (x,y) (z,_) = ...
|
fun f arg1 arg2 = let fun f (x,y) (z,_) = ...
|
||||||
val x = #1 arg1
|
val x = #1 arg1
|
||||||
|
@ -237,7 +231,7 @@ fun f arg1 = let fun f {foo=x, bar=y, baz} = ...
|
||||||
in
|
in
|
||||||
...
|
...
|
||||||
end
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Avoid Unnecessary Projections. Prefer pattern matching to projections with
|
Avoid Unnecessary Projections. Prefer pattern matching to projections with
|
||||||
|
@ -246,6 +240,7 @@ as it is infrequent and the meaning is clearly understood from the context.
|
||||||
The above rule shows how to pattern-match in the function arguments. Here is
|
The above rule shows how to pattern-match in the function arguments. Here is
|
||||||
an example for pattern matching with value declarations.
|
an example for pattern matching with value declarations.
|
||||||
|
|
||||||
|
```sml
|
||||||
Bad Good
|
Bad Good
|
||||||
let let
|
let let
|
||||||
val v = someFunction() val (x,y) = someFunction()
|
val v = someFunction() val (x,y) = someFunction()
|
||||||
|
@ -254,7 +249,7 @@ let let
|
||||||
in end
|
in end
|
||||||
x+y
|
x+y
|
||||||
end
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Combine nested case Expressions. Rather than nest case expressions, you can
|
Combine nested case Expressions. Rather than nest case expressions, you can
|
||||||
|
@ -262,7 +257,7 @@ combine them by pattern matching against a tuple, provided the tests in the
|
||||||
case expressions are independent. Here is an example:
|
case expressions are independent. Here is an example:
|
||||||
|
|
||||||
Bad
|
Bad
|
||||||
|
```sml
|
||||||
let
|
let
|
||||||
val d = Date.fromTimeLocal(Time.now())
|
val d = Date.fromTimeLocal(Time.now())
|
||||||
in
|
in
|
||||||
|
@ -277,11 +272,11 @@ Bad
|
||||||
10 => print "Happy Metric Day"
|
10 => print "Happy Metric Day"
|
||||||
| _ => ())
|
| _ => ())
|
||||||
end
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Good
|
Good
|
||||||
|
```sml
|
||||||
let
|
let
|
||||||
val d = Date.fromTimeLocal(Time.now())
|
val d = Date.fromTimeLocal(Time.now())
|
||||||
in
|
in
|
||||||
|
@ -291,7 +286,7 @@ Good
|
||||||
| (Date.Oct, 10) => print "Happy Metric Day"
|
| (Date.Oct, 10) => print "Happy Metric Day"
|
||||||
| _ => ()
|
| _ => ()
|
||||||
end
|
end
|
||||||
|
```
|
||||||
Avoid the use valOf, hd, or tl. The functions valOf, hd, and tl are used to
|
Avoid the use valOf, hd, or tl. The functions valOf, hd, and tl are used to
|
||||||
deconstruct option types and list types. However, they raise exceptions on
|
deconstruct option types and list types. However, they raise exceptions on
|
||||||
certain inputs. You should avoid these functions altogether. It is usually
|
certain inputs. You should avoid these functions altogether. It is usually
|
||||||
|
@ -299,8 +294,7 @@ easy to achieve the same effect with pattern matching. If you cannot manage to
|
||||||
avoid them, you should handle any exceptions that they might raise.
|
avoid them, you should handle any exceptions that they might raise.
|
||||||
|
|
||||||
|
|
||||||
Chapter 6: Naming and declarations
|
## Chapter 6: Naming and declarations
|
||||||
==========
|
|
||||||
|
|
||||||
Naming Conventions. The best way to tell at a glance something about the type
|
Naming Conventions. The best way to tell at a glance something about the type
|
||||||
of a variable is to use the standard SML naming conventions. The following are
|
of a variable is to use the standard SML naming conventions. The following are
|
||||||
|
@ -309,20 +303,20 @@ SML/NJ libraries:
|
||||||
|
|
||||||
Token SML Naming Convention
|
Token SML Naming Convention
|
||||||
Variables Symbolic or initial lower case. Use embedded caps for multiword names.
|
Variables Symbolic or initial lower case. Use embedded caps for multiword names.
|
||||||
Example: getItem
|
Example: `getItem`
|
||||||
Functions Initial lower case. Use embedded caps for multiword names.
|
Functions Initial lower case. Use embedded caps for multiword names.
|
||||||
Example: nameOf
|
Example: `nameOf`
|
||||||
Constructors Initial upper case. Use embedded caps for multiword names. Historic
|
Constructors Initial upper case. Use embedded caps for multiword names. Historic
|
||||||
exceptions are nil, true, and false. Rarely are symbolic names like :: used.
|
exceptions are nil, true, and false. Rarely are symbolic names like :: used.
|
||||||
Example: Node, EmptyQueue
|
Example: `Node`, `EmptyQueue`
|
||||||
Types All lower case. Use underscores for multiword names.
|
Types All lower case. Use underscores for multiword names.
|
||||||
Example: priority_queue
|
Example: `priority_queue`
|
||||||
Signatures All upper case. Use underscores for multiword names.
|
Signatures All upper case. Use underscores for multiword names.
|
||||||
Example: PRIORITY_QUEUE
|
Example: `PRIORITY_QUEUE`
|
||||||
Structures Initial upper case. Use embedded caps for multiword names.
|
Structures Initial upper case. Use embedded caps for multiword names.
|
||||||
Example: PriorityQueue
|
Example: `PriorityQueue`
|
||||||
Functors Same as structure convention, except Fn completes the name.
|
Functors Same as structure convention, except Fn completes the name.
|
||||||
Example: PriorityQueueFn
|
Example: `PriorityQueueFn`
|
||||||
|
|
||||||
These conventions are not enforced by the compiler, though violations of the
|
These conventions are not enforced by the compiler, though violations of the
|
||||||
variable/constructor conventions ought to cause warning messages because of the
|
variable/constructor conventions ought to cause warning messages because of the
|
||||||
|
@ -333,7 +327,7 @@ variable names that reflect their intended use. Choose words or combinations
|
||||||
of words describing the value. Variable names may be one letter in short let
|
of words describing the value. Variable names may be one letter in short let
|
||||||
blocks. Functions used in a fold, filter, or map are often bound to the name
|
blocks. Functions used in a fold, filter, or map are often bound to the name
|
||||||
f. Here is an example for short variable names:
|
f. Here is an example for short variable names:
|
||||||
|
```sml
|
||||||
let
|
let
|
||||||
val d = Date.fromTimeLocal(Time.now())
|
val d = Date.fromTimeLocal(Time.now())
|
||||||
val m = Date.minute d
|
val m = Date.minute d
|
||||||
|
@ -342,7 +336,7 @@ let
|
||||||
in
|
in
|
||||||
List.filter f [m,s]
|
List.filter f [m,s]
|
||||||
end
|
end
|
||||||
|
```
|
||||||
|
|
||||||
Avoid Global Mutable Variables. Mutable values should be local to closures and
|
Avoid Global Mutable Variables. Mutable values should be local to closures and
|
||||||
almost never declared as a structure's value. Global mutable values cause many
|
almost never declared as a structure's value. Global mutable values cause many
|
||||||
|
@ -362,26 +356,26 @@ by functions within the current structure are aliased to one or two letter
|
||||||
variables at the top of the struct block. This serves two purposes: it shortens
|
variables at the top of the struct block. This serves two purposes: it shortens
|
||||||
the name of the structure and it documents the structures you use. Here is an
|
the name of the structure and it documents the structures you use. Here is an
|
||||||
example:
|
example:
|
||||||
|
```sml
|
||||||
struct
|
struct
|
||||||
structure H = HashTable
|
structure H = HashTable
|
||||||
structure T = TextIO
|
structure T = TextIO
|
||||||
structure A = Array
|
structure A = Array
|
||||||
...
|
...
|
||||||
end
|
end
|
||||||
|
```
|
||||||
Order of Declarations in a Structure. When declaring elements in a structure,
|
Order of Declarations in a Structure. When declaring elements in a structure,
|
||||||
you should first alias the structures you intend to use, followed by the types,
|
you should first alias the structures you intend to use, followed by the types,
|
||||||
followed by exceptions, and lastly list all the value declarations for the
|
followed by exceptions, and lastly list all the value declarations for the
|
||||||
structure. Here is an example:
|
structure. Here is an example:
|
||||||
|
```sml
|
||||||
struct
|
struct
|
||||||
structure L = List
|
structure L = List
|
||||||
type foo = unit
|
type foo = unit
|
||||||
exception InternalError
|
exception InternalError
|
||||||
fun first list = L.nth(list,0)
|
fun first list = L.nth(list,0)
|
||||||
end
|
end
|
||||||
|
```
|
||||||
|
|
||||||
Every declaration within the structure should be indented the same amount.
|
Every declaration within the structure should be indented the same amount.
|
||||||
|
|
||||||
|
@ -389,14 +383,14 @@ Moreover, every top-level structure should be restricted by a (documented)
|
||||||
signature.
|
signature.
|
||||||
|
|
||||||
Functions should declared in their their curried form, e.g.,
|
Functions should declared in their their curried form, e.g.,
|
||||||
|
```sml
|
||||||
fun f x y = ... instead of fun f(x,y) = ...
|
fun f x y = ... instead of fun f(x,y) = ...
|
||||||
|
```
|
||||||
Datatypes should be preferred to type synonyms in particular for
|
Datatypes should be preferred to type synonyms in particular for
|
||||||
record types
|
record types
|
||||||
|
|
||||||
|
|
||||||
Chapter 7: Verbosity
|
## Chapter 7: Verbosity
|
||||||
==========
|
|
||||||
|
|
||||||
Don't Rewrite Library Functions. The basis library and the SML/NJ library have
|
Don't Rewrite Library Functions. The basis library and the SML/NJ library have
|
||||||
a great number of functions and data structures -- use them! Often students
|
a great number of functions and data structures -- use them! Often students
|
||||||
|
@ -412,6 +406,7 @@ case that the type is bool, you should not be using if at all. Consider the
|
||||||
following:
|
following:
|
||||||
|
|
||||||
|
|
||||||
|
```sml
|
||||||
Bad Good
|
Bad Good
|
||||||
if e then true else false e
|
if e then true else false e
|
||||||
if e then false else true not e
|
if e then false else true not e
|
||||||
|
@ -421,40 +416,40 @@ if x then true else y x orelse y
|
||||||
if x then y else false x andalso y
|
if x then y else false x andalso y
|
||||||
if x then false else y not x andalso y
|
if x then false else y not x andalso y
|
||||||
if x then y else true not x orelse y
|
if x then y else true not x orelse y
|
||||||
|
```
|
||||||
|
|
||||||
Misusing case Expressions. The case expression is misused in two common
|
Misusing case Expressions. The case expression is misused in two common
|
||||||
situations. First, case should never be used in place of an if expression
|
situations. First, case should never be used in place of an if expression
|
||||||
(that's why if exists). Note the following:
|
(that's why if exists). Note the following:
|
||||||
|
```sml
|
||||||
case e of
|
case e of
|
||||||
true => x
|
true => x
|
||||||
| false => y
|
| false => y
|
||||||
|
|
||||||
if e then x else y
|
if e then x else y
|
||||||
|
```
|
||||||
The latter is much better. Another situation where if expressions are
|
The latter is much better. Another situation where if expressions are
|
||||||
preferred over case expressions is as follows:
|
preferred over case expressions is as follows:
|
||||||
|
```sml
|
||||||
case e of
|
case e of
|
||||||
c => x (* c is a constant value *)
|
c => x (* c is a constant value *)
|
||||||
| _ => y
|
| _ => y
|
||||||
|
|
||||||
if e=c then x else y
|
if e=c then x else y
|
||||||
|
```
|
||||||
The latter is definitely better. The other misuse is using case when pattern
|
The latter is definitely better. The other misuse is using case when pattern
|
||||||
matching with a val declaration is enough. Consider the following:
|
matching with a val declaration is enough. Consider the following:
|
||||||
|
```sml
|
||||||
val x = case expr of (y,z) => y
|
val x = case expr of (y,z) => y
|
||||||
|
|
||||||
val (x,_) = expr
|
val (x,_) = expr
|
||||||
|
```
|
||||||
The latter is better.
|
The latter is better.
|
||||||
|
|
||||||
Other Common Misuses. Here are some other common mistakes to watch out for:
|
Other Common Misuses. Here are some other common mistakes to watch out for:
|
||||||
|
|
||||||
|
```sml
|
||||||
Bad Good
|
Bad Good
|
||||||
|
|
||||||
l::nil [l]
|
l::nil [l]
|
||||||
l::[] [l]
|
l::[] [l]
|
||||||
length + 0 length
|
length + 0 length
|
||||||
|
@ -471,30 +466,30 @@ Int.compare(x,y)=GREATER x>y
|
||||||
Int.sign(x)=~1 x<0
|
Int.sign(x)=~1 x<0
|
||||||
Int.sign(x)=0 x=0
|
Int.sign(x)=0 x=0
|
||||||
Int.sign(x)=1 x>0
|
Int.sign(x)=1 x>0
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not re-wrap Functions. When passing a function as an argument to another
|
||||||
Don't Re-wrap Functions. When passing a function as an argument to another
|
|
||||||
function, don't re-wrap the function unnecessarily. Here's an example:
|
function, don't re-wrap the function unnecessarily. Here's an example:
|
||||||
|
```sml
|
||||||
List.map (fn x => Math.sqrt x) [1.0, 4.0, 9.0, 16.0]
|
List.map (fn x => Math.sqrt x) [1.0, 4.0, 9.0, 16.0]
|
||||||
|
|
||||||
List.map Math.sqrt [1.0, 4.0, 9.0, 16.0]
|
List.map Math.sqrt [1.0, 4.0, 9.0, 16.0]
|
||||||
|
```
|
||||||
The latter is better. Another case for rewrapping a function is often
|
The latter is better. Another case for rewrapping a function is often
|
||||||
associated with infix binary operators. To prevent rewrapping the binary
|
associated with infix binary operators. To prevent rewrapping the binary
|
||||||
operator, use the op keyword as in the following example:
|
operator, use the op keyword as in the following example:
|
||||||
|
```sml
|
||||||
foldl (fn (x,y) => x + y) 0
|
foldl (fn (x,y) => x + y) 0
|
||||||
|
|
||||||
foldl (op +) 0
|
foldl (op +) 0
|
||||||
|
```
|
||||||
The latter is better.
|
The latter is better.
|
||||||
|
|
||||||
Don't Needlessly Nest let Expressions. Multiple declarations may occur in the
|
Don't Needlessly Nest let Expressions. Multiple declarations may occur in the
|
||||||
first block of a let...in...end expression. The bindings are performed
|
first block of a let...in...end expression. The bindings are performed
|
||||||
sequentially, so you may use a name bound earlier in the same block. Consider
|
sequentially, so you may use a name bound earlier in the same block. Consider
|
||||||
the following:
|
the following:
|
||||||
|
```sml
|
||||||
let
|
let
|
||||||
val x = 42
|
val x = 42
|
||||||
in
|
in
|
||||||
|
@ -511,7 +506,7 @@ let
|
||||||
in
|
in
|
||||||
x + y
|
x + y
|
||||||
end
|
end
|
||||||
|
```
|
||||||
|
|
||||||
The latter is better.
|
The latter is better.
|
||||||
|
|
||||||
|
@ -522,8 +517,7 @@ This has the added benefit of letting you document the purpose of the value
|
||||||
with a name.
|
with a name.
|
||||||
|
|
||||||
|
|
||||||
Chapter 9: File names and encoding
|
## Chapter 8: File names and encoding
|
||||||
==========
|
|
||||||
|
|
||||||
In general, a source file should only contain one signature or structure. In more
|
In general, a source file should only contain one signature or structure. In more
|
||||||
detail:
|
detail:
|
||||||
|
@ -537,8 +531,7 @@ and separated by underscore, e.g., ocl_term.sig
|
||||||
Source files should use the Unix line ending convention and be either encoding
|
Source files should use the Unix line ending convention and be either encoding
|
||||||
using ASCII (preferred) or UTF-8.
|
using ASCII (preferred) or UTF-8.
|
||||||
|
|
||||||
Chapter 9: Compatibility
|
## Chapter 9: Compatibility
|
||||||
==========
|
|
||||||
|
|
||||||
Any code developed must be portable among the supported SML systems
|
Any code developed must be portable among the supported SML systems
|
||||||
(currently: sml/NJ, mlton, polyml 5.x). Moreover, the code should
|
(currently: sml/NJ, mlton, polyml 5.x). Moreover, the code should
|
||||||
|
@ -547,25 +540,23 @@ warnings as errors. Keep in mind that polyml does only provide a subset
|
||||||
of the SML standard library.
|
of the SML standard library.
|
||||||
|
|
||||||
|
|
||||||
Appendix I: Machine-support
|
## Appendix
|
||||||
===========
|
### Appendix I: Machine-support
|
||||||
The following elisp-snippet provides marginal support for this coding-style for
|
The following elisp-snippet provides marginal support for this coding-style for
|
||||||
the sml-mode [4] of Emacs [5]:
|
the sml-mode [4] of Emacs [5]:
|
||||||
|
|
||||||
|
```emacs
|
||||||
(setq sml-indent-level 2)
|
(setq sml-indent-level 2)
|
||||||
(setq sml-pipe-indent -2)
|
(setq sml-pipe-indent -2)
|
||||||
(setq sml-case-indent t)
|
(setq sml-case-indent t)
|
||||||
(setq sml-nested-if-indent t)
|
(setq sml-nested-if-indent t)
|
||||||
(setq sml-type-of-indent nil)
|
(setq sml-type-of-indent nil)
|
||||||
(setq sml-electric-semi-mode nil)
|
(setq sml-electric-semi-mode nil)
|
||||||
|
```
|
||||||
|
|
||||||
Appendix II: References
|
### Appendix II: References
|
||||||
============
|
1. http://www.cs.cornell.edu/Courses/cs312/2007fa/handouts/style.htm
|
||||||
|
2. SMLDoc. http://www.pllab.riec.tohoku.ac.jp/smlsharp/?SMLDoc
|
||||||
[1] http://www.cs.cornell.edu/Courses/cs312/2007fa/handouts/style.htm
|
3. http://projects.brucker.ch/su4sml/smldoc/
|
||||||
[2] SMLDoc. http://www.pllab.riec.tohoku.ac.jp/smlsharp/?SMLDoc
|
4. http://www.smlnj.org/doc/Emacs/sml-mode.html
|
||||||
[3] http://projects.brucker.ch/su4sml/smldoc/
|
5. http://www.gnu.org/software/emacs/
|
||||||
[4] http://www.smlnj.org/doc/Emacs/sml-mode.html
|
|
||||||
[5] http://www.gnu.org/software/emacs/
|
|
||||||
--
|
|
||||||
Last updated on $Date:$
|
|
Loading…
Reference in New Issue