22
  • defn=公開
  • defn-= プライベート

おそらく私は Clojure のコーディング スタイルが悪いのかもしれませんが、Clojure で記述したほとんどの関数は、公開したくない小さなヘルパー関数であることがわかりました。

構成オプションはありますか?

  • defn= デフォルトで非公開、
  • 何かを公開するには、私はしなければなりませdefn+んか?

ありがとう!

4

4 に答える 4

17

いいえ、ありません。

うまくいくかもしれないしうまくいかないかもしれない別のアプローチは、foo.bar.internal名前空間で使用されるすべてのプライベート ヘルパーを含む名前空間を宣言することですfoo.bar。マクロ展開でプライベート関数を使用する場合、これにはプライベート関数宣言よりも利点があります。

于 2012-04-23T05:57:18.110 に答える
6

Lisp である Clojure の優れた点は、必要に応じて言語を構築および適応できることです。Paul Graham の On Lispを読むことを強くお勧めします。彼は今、自分の本を無料で配っています。

defn+ vs defn vs defn- の提案について。これは、独自のマクロを作成するための良いケースのように思えます。 defnは関数でdefn-あり、マクロです。必要に応じて単純に再定義するか、独自にラップすることができます。

以下は、主に Clojure 独自の実装 (単純なユーティリティーとテストを含む) に基づいた実装の提案です。

(defmacro defn+
    "same as Clojure's defn, yielding public def"
    [name & decls]
    (list* `defn (with-meta name (assoc (meta name) :public true)) decls))

(defmacro defn
    "same as Clojure's defn-, yielding non-public def"
    [name & decls]
    (list* `defn (with-meta name (assoc (meta name) :private true)) decls))

(defn mac1
    "same as `macroexpand-1`"
    [form]
    (. clojure.lang.Compiler (macroexpand1 form)))

(let [  ex1 (mac1 '(defn f1 [] (println "Hello me.")))
        ex2 (mac1 '(defn+ f2 [] (println "Hello World!"))) ]
    (defn f1 [] (println "Hello me."))
    (defn+ f2 [] (println "Hello World!"))
    (prn ex1) (prn (meta #'f1)) (f1)
    (prn ex2) (prn (meta #'f2)) (f2) )
于 2015-12-26T10:03:36.470 に答える
5

「ヘルパー関数」が一度だけ使用される可能性が非常に高い場合は、それらをより大きな関数のローカルにするか、無名関数として記述するかを選択できます。http://clojuredocs.org/clojure_core/clojure.core/letfnおよびhttp://clojuredocs.org/clojure_core/clojure.core/fnを参照してletfnください。

自分はほとんど使いませletfnん。

于 2012-04-24T06:02:09.960 に答える
5

@kotarak が述べたように、(私の知る限り)それを行う方法はなく、望ましくもありません。

私が嫌いな理由は次のdefn-とおりです。

さまざまな Clojure ライブラリを使用しているときに、特定のニーズに合わせて 1 つの関数を少し変更する必要がある場合があることがわかりました。多くの場合、それは非常に小さなものであり、それは私の特定のケースでのみ意味があります. 多くの場合、これは 1 文字か 2 文字です。

しかし、この関数が内部のプライベート関数を再利用すると、変更が難しくなります。これらのプライベート関数をすべてコピーして貼り付ける必要があります。

これは、プログラマーが「これは予告なしに変更される可能性がある」という言い方であることを理解しています。

とにかく、私は反対の慣習が欲しいです:

  • を常に使用defnし、すべてを公開します
  • defn+(まだ存在していません) を使用して、使用することになっているパブリック API の一部である関数をプログラマーに指定します。defn+他のものと変わらないはずdefnです。

また、いずれにしてもプライベート関数にアクセスできることに注意してください。

;; in namespace user
user> (defn- secret []
        "TOP SECRET")

;; from another namespace
(#'user/secret) ;;=> "TOP SECRET"
于 2015-07-06T12:40:51.817 に答える