name: cl-coding-style description: Common Lispのコーディング規約を適用。Lispコード作成・レビュー時に使用 allowed-tools: Read, Grep, Glob references: - @references/google-common-lisp-style-guide.md
Common Lisp Coding Style
Based on Google Common Lisp Style Guide (@references/google-common-lisp-style-guide.md)
命名規則
関数・変数
- 通常の名前:
kebab-case(例:find-user-by-id,parse-json-string) - 述語関数:
-pサフィックス (例:valid-user-p,empty-list-p) - 変換関数:
foo->bar形式 (例:string->symbol,list->vector)
特殊変数
- 動的変数:
*earmuffs*(例:*default-timeout*,*current-connection*) - 定数:
+plus-signs+(例:+max-retries+,+default-buffer-size+)
クラス・条件
- クラス名:
kebab-case(例:user-account,http-request) - 条件型:
-error,-warningサフィックス (例:invalid-input-error)
アクセサ
- リーダー:
class-slot(例:user-name,request-method) - ライター:
(setf class-slot)形式 - アクセサ: 両方を提供する場合
インデント
- 基本: 2スペースインデント
- タブ禁止: スペースのみ使用
- Emacsスタイル: 標準的なLispインデントに従う
;; Good
(defun process-items (items)
(loop for item in items
when (valid-p item)
collect (transform item)))
;; Bad - インデント不正
(defun process-items (items)
(loop for item in items
when (valid-p item)
collect (transform item)))
パッケージ参照
シンボル形式
- 推奨:
#:形式 (uninterned symbol) - 許容: キーワード形式
:symbol - 非推奨: 文字列形式
"SYMBOL"
;; Good
(defpackage #:my-project
(:use #:cl)
(:import-from #:alexandria
#:if-let
#:when-let)
(:export #:main
#:run))
;; Acceptable
(defpackage :my-project
(:use :cl)
(:export :main))
;; Bad - 文字列形式
(defpackage "MY-PROJECT"
(:use "CL"))
import-from vs use
- :import-from: 明示的なシンボル指定(推奨)
- :use: パッケージ全体の取り込み(CLのみ推奨)
フォーマット
行長
- 推奨: 100文字以内
- 最大: 120文字
空行
- 関数間: 1行
- セクション間: 2行まで
- 連続空行: 最大2行
括弧
- 閉じ括弧: 同一行に連続配置
- 開き括弧後の改行: 必要な場合のみ
;; Good - 閉じ括弧は連続
(defun foo ()
(let ((x 1)
(y 2))
(+ x y)))
;; Bad - 閉じ括弧が分離
(defun foo ()
(let ((x 1)
(y 2))
(+ x y)
)
)
ドキュメント
Docstring
- 関数: 目的と引数を説明
- 変数: 用途を説明
- クラス: 役割を説明
(defun find-user (id &key (include-deleted nil))
"Find a user by ID.
Arguments:
ID - The user's unique identifier
INCLUDE-DELETED - If true, include soft-deleted users
Returns:
USER object or NIL if not found"
...)
(defvar *connection-pool*
"Pool of database connections for reuse.")
制御構造
when/unless vs if
- when: else節なしの場合
- unless: 否定条件の場合
- if: 両方の分岐がある場合
;; Good
(when (valid-p x)
(process x))
(unless (empty-p list)
(first list))
(if (ready-p)
(start)
(wait))
;; Bad - ifをwhenで書くべき
(if (valid-p x)
(process x)
nil)
cond vs if
- cond: 3つ以上の分岐
- if: 2分岐
;; Good - condを使用
(cond
((< n 0) 'negative)
((= n 0) 'zero)
(t 'positive))
;; Bad - ネストしたif
(if (< n 0)
'negative
(if (= n 0)
'zero
'positive))