Style Tips
How to Lose Style Points for Your Project
Most of you are wondering what we mean when we say "use good style for your projects". We decided to enumerate the ways you could lose
style points that you should avoid. These are listed in decreasing order of severity -- the first couple are things you should NEVER do.
Non-Functional Programming
- Changing the binding of variables midway through your code
- Use of the forbidden function
set!
- Use of
define to change a binding
- Overt use of global variables
- E.g., Trying to write the program as you would a basic or C program, sequentially
- Blatant use of let* to try to accomplish sequential programming
(let* ((a 1)
(b (* a 2))
(c (* b a))
(d (+ a b c)) ;; etc
Readability
- Poorly named functions and/or variables
- If it's a generic sentence, use
s or sent
- If it's a generic word, use
w or wd
- If it's a generic list, use
L or lst
- If it's a generic sentence or word, use
sw or sentwd
- If it's a generic number, use
x or num or n
- If it's a predicate, make sure the name ends with a
?
- If it's a specific data type or function, always use a name that makes sense.
E.g.,
(generate-moves position) returns a list of moves, so you would call that moves or move-list
- A function with way-too-many lines (much more than 24)
- A Line from the code that extends through the full width of
the screen (keep under 80 characters per line).
Abstraction
- Blatant DAVs (data abstraction violations) -- not using constructors and selectors. E.g.,
- Blatant DAVs -- not understanding data types. E.g.,
> (car (every square '(1 2 3))) ;; every returns a sentence, should use first
- Blatant DAVs -- not using constructors, like make-board
and make-position. E.g.,
Efficiency
- Proper use of
let to save you time computing things multiple times. E.g.,
(+ (hour-long-function-computing-foo)
(* 2 (hour-long-function-computing-foo))) ;; is better rewritten as
(let ((foo (hour-long-function-computing-foo)))
(+ foo (* 2 foo)))
- An enormous
cond when an association list would be more appropriate
- Many cascaded
if s when a cond would be more appropriate
- Using a
cond for only two cases where an if would be more approproate
- Inappropriate explicit
#t /#f in your code
(if (my-test? input) #f #t) should just be (not (my-test? input))
(if (my-test? input) #t #f) should just be (my-test? input)
#t and #f are allowed in recursion when defining a predicate, however.
- An
else that falls off the end. E.g.,
(define (my-choice input) ;; input is 1,2 or 3
(cond ((= input 1) (foo))
((= input 2) (bar))
(else (baz))))
- Instead, use
else to catch an error condition. E.g.,
(define (my-choice input) ;; input is 1,2 or 3
(cond ((= input 1) (foo))
((= input 2) (bar))
((= input 3) (baz))
(else (error "Input not 1, 2 or 3 -- MY-CHOICE"))))
Formatting
- Improper formatting (
emacs will format automatically for you in scheme-mode if you hit TAB )
- To go into
scheme-mode (which should happen automatically if you ever open a .scm file in emacs) you
simply type M-x scheme-mode
- You can indent an entire region in
scheme-mode by selecting the entire region (C-space at the beginning
then move your cursor to the end of the region you want) and typing M-x indent-region (shortcut: M-C-\ )
- To select the entire buffer as your region you first go to the top of the buffer with
M-< and then to the end
with M-> (then do your M-x indent-region )
;; E.g., The following code...
(let ((foo 1)) (every
(lambda (w)
(+ foo
(* foo w
))) my-sent)
;; should be reformatted as
(let ((foo 1))
(every (lambda (w) (+ foo (* foo w )))
my-sent)
;; or
(let ((foo 1))
(every (lambda (w)
(+ foo
(* foo w )))
my-sent)
|