Common Lisp Style Guide

Source: Internet
Author: User

Ref: Common Lisp Style Guide-Ariel Networks Labs

PackageOne package per one file

Strangely enough, in case of legacy CL programs, their packages are declared in one file (maybe named "package. lisp "). in other hand, we recommend to declare each packages in each files.

You shoshould always put like following code at the top of each Lisp files.

(in-package :cl-user)(defpackage style-guide.core  (:use :cl))(in-package :style-guide.core);; body

If you adopt this style on your programs, you will notice you think about dependence of each components. It is a good signal. This style keeps a program to be loosely coupled.

Avoid: use

Don't use:useUnnecessarily. It is often hard to understand where a function came from. We recommend using:import-fromFor instead.

(in-package :cl-user)(defpackage style-guide.core  (:use :cl)  (:import-from :style-guide.util                :funky-feature))(in-package :style-guide.core)

We allow you to use:useOnly if most of symbols are needed or it is obvious.

(in-package :cl-user)(defpackage style-guide.core  (:use :cl        :anaphora)  (:import-from :style-guide.util                :funky-feature))(in-package :style-guide.core)

Why we recommend such a complicated rule is from our thoughts. we think codes are also documents, and furthermore if we say, they are also novels. if we say from the point, importing symbols are introducing characters. we think it might help readers.

AnnotationUse "cl-annot" positively

Though "Annotation" is not supported in Common Lisp, "cl-annot" provides the feature. we recommend using it almost always. for example, "@ export" annotation means exporting the following function or something.

@export(defun plus-ten (x)  (+ x 10))

If you want to know the truth, that is just a macro actually. So, you can say that just a shorthand. Of course, you can define your own annotations.

Why we recommend such an uugly syntax? Because it provides transparency to our code.

For example,defwidgetIs one of macros in Weblocks. It is justdefclass, Actually. Well, really? You have to expand the macro to know that. It is not transparent.

If I write Weblocks from scratch now, I will provide "@ widget" annotation, for insteaddefwidget. You can use familiardefclassTo define a widget. It makes you be relieved.

In that way, we can represent the will we won't disturb your code by using annotations. This is another expression we can use.

NamingSurround class name with "<" and ">"
(defclass <aluminium> (<metal>)    (color solidity cost))
Surround constants with "+"
(defconstant +kikuko-inoue-age+ 17)
Surround special vars "*"
(defvar *cache-table* (make-hash-table))(defparameter *debug* t)
Hierarchical Package Name
;; in core.lisp(in-package :cl-user)(defpackage style-guide.core  (:use :cl))(in-package :style-guide.core);; in util.lisp(in-package :cl-user)(defpackage style-guide.util  (:use :cl))(in-package :style-guide.util);; in class/metal.lisp(in-package :cl-user)(defpackage style-guide.class.metal  (:use :cl))(in-package :style-guide.class.metal)
CommentComments are Optional

All comments are optional. usually, comments are for writer of the program and it is you in most of the times. if you think that it shocould be known by users, it must be encoded in docstring, not comment.

Comments shoshould end with period

This is just a rule.

;; TODO: rewrite to recursive at tail position.(defun factorial (n)  (if (<= n 1)    1    (* n (factorial (1- n))))))
DocstringRequired (almost always)

Docstring is always needed for every parts. Don't forget Packages and ASDF Systems.

You can omit only if it is obvious what to do.

ClassAdd: type to each slots
(defclass <aluminium> (<metal>)    ((color :type string            :initarg :color            :initform "white")     (solidity :type (or integer <solidity>)               :initarg :solidity               :initform (make-instance '<solidity>))     (cost :type (or integer null)           :initarg :cost))  (:documentation "A class represents Aluminium."))

Don't forget a type "null" for optional slots.

MacroAvoid Macros in really meaning

You know Macro is one of the strongest feature in Common Lisp. But it is also a dangerous thing. You shoshould avoid using Macro if it is possible.

This is a really important warning. If you feel it is needed once, you shoshould think this well again.How do other versions ages manage it?They really manage the problems without macros.

For example, it is often used that defines something specialized type (like "defwidget"). Must it be a macro, not an annotation? Why don't you usedefclassFor instead. There are more choices than you think. Macro is the last one to choose.

Conditional FlowUse WHEN, UNLESS if possible

Don't useifWithout "else" expression.whenIs more precise for it.

Use ETYPECASE, ECASE if possible

etypecaseAndecaseAre a strict versiontypecaseAndcase. If you don't have CT other types specified, you shocould useetypecaseOrecaseFor safety.

Don't nest conditional flow

HoweverifIs a simple feature and most of history ages have it, it cocould make a program hard to understand.

;; Hard to understand(defun count-all-numbers (alist)  (if (null alist)    0    (+ (if (listp (first alist))         (count-all-numbers (first alist))         (if (numberp (first alist)) 1 0))       (count-all-numbers (rest alist)))))

Above example shocould be rewritten as following.

;; quoted from "Good Lisp Style"(defun count-all-numbers (exp)  (typecase exp    (cons   (+ (count-all-numbers (first exp))               (count-all-numbers (rest exp))))    (number 1)    (t      0)))

A largetypecaseMay be rewrittendefmethodOr Polymorphism.

Keep the condition expression short

Large condition expressions makes the codes hard to read. If you felt the condition will be larger, you shocould separate them into another function or method.

(if (and (person-name user)         (<= 20 (person-age user)))  (write-line "this person is valid.")  (error "Invalid person."))
(defmethod valid-person-p ((person <person>))  (and (person-name person)       (<= 20 (person-age person))))(if (valid-person-p person)  (write-line "this person is valid.")  (error "Invalid person."))

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.