clojure / clojurescript中单个var名称空间的命名约定是什么?

What is the naming convention for a single var namespace in clojure/clojurescript?

我经常发现自己在clojurescript中定义名称空间,该名称空间仅包含一个将通过def或defn创建的变量,而该变量将在该名称空间之外使用。

当使用试剂时,这尤其常见,我在单独的文件/命名空间中定义了我的组件,而我只在命名空间之外使用了这些单个组件。

1
2
(ns project.components.component-name)
(defn component-name ...)

因此,我以这种方式导入它们,并且由于名称空间和组件都使用一个名称,因此我发现它相当重复且不清楚:

1
2
3
project.components.component-name :as [component-name]

component-name/component-name

或劣等:refer(因为不太明显var来自另一个名称空间)

1
2
3
project.components.component-name :refer [component-name]

component-name

我知道ECMAScript中有一个有用的模式:

1
export default function () { ... };

那么Clojure中有类似的东西吗? 也许为此有一些约定俗成的惯例?

以下是我最近开始使用的约定,对此我不

1
2
3
4
(ns project.components.component-name)
(defn _ ...)

project.components.component-name :as [component-name]

然后将其用作

1
component-name/_

我不确定每个名称空间一个组件是最好的方法。这将导致
在大量的名称空间和大量重复中。但是,这是
clojure和每个人都有不同的风格。我的方法是使用名称空间
分解功能。除了最简单的变化以外的所有变化
组件,我发现一个组件不会同时使用其他组件的情况很少见
组件。我会倾向于将用于
特定的功能以及用于大多数情况的各种低级组件
其他组件具有/ utility /或/ base /命名空间。例如,我可能
有类似的东西

1
2
3
4
5
6
7
8
9
project --|
          src --|
                my-app --|
                         core.cljs
                         interface --|
                                     base.cljs
                                     navbar.cljs
                                     sidebar.cljs
                                     tabber.cljs

在每个这些命名空间中,可能都有多个组件。其中一些可能
被定义为该命名空间的私有对象,而其他则是入口组件,
由core.cljs引用。我发现名称空间需要的部分也不会
大型或重复性文件,我不需要在不同文件中跳来跳去
YMMV。


下划线通常用于在Clojure中不关心的值,因此,我强烈建议您避免使用_作为函数名称。例如,您经常会在野外看到这样的代码:

1
2
3
4
5
6
7
8
9
;; Maybe when destructuring a let. Kinda contrived example.
(let [[a _ _ d] (list 1 2 3 4)]
   (+ a d 10))

;; Quite often in a protocol implementation where we don't care about 'this'.
(defrecord Foo []
  SomeProtocol
  (thing [_ x]
    (inc x)))

在命名空间中只有一个var没什么错,尽管我可能只会在功能合理的情况下才引入命名空间。您可以尝试使用my-app.components之类的命名空间,在其中保留所有小部分,直到它们足够大以保证有专用的空间为止。与此类似:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
(ns my-app.components
  ;; The profile stuff is really big lets say.
  (:require [my-app.components.profile :as profile]))

(defn- items->ul
  [items]
  [:ul (map #(vector :li (:text %)) items)])

(defn- render-nav
  [state]
  [:nav (-> state deref :nav-items items->ul)])

(defn- render-footer
  [state]
  [:footer (-> state deref :footer-items items->ul)])

(defn render-layout
  [state]
  [:html
   [:head [:title (:title @state)]]
   [:body
    [:main
     (render-nav state)
     (profile/render-profile (-> state deref :current-user))
     (render-footer state)]]])